it-swarm.com.de

Android-Spinner-Datenbindung mithilfe von XML und Anzeige der ausgewählten Werte

Ich benutze die neue Android-Datenbindung und es funktioniert super. Ich kann Datenbindung mit EditText, TextView, Radio und Kontrollkästchen durchführen. Nun kann ich die Datenbindung in Spinner nicht durchführen.

Im folgenden Link finden Sie einige Hinweise: Android-Spinner-Datenbindung mit XML-Layout

Aber immer noch nicht in der Lage, die Lösung zu finden. Müssen auch die bidirektionale Datenbindung durchführen. Sollte den ausgewählten Spinner-Datenwert widerspiegeln.

Kann mir jemand bitte ein Beispiel zeigen?

Hier ist mein xml Code:

<layout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/tools"
    xmlns:card_view="http://schemas.Android.com/apk/res-auto">

    <data>
        <import type="Android.view.View" />
        <variable
            name="viewModel"
            type="com.ViewModels.model" />
    </data>

     <Spinner
                    Android:id="@+id/assessmemt_spinner"
                    Android:layout_width="match_parent"
                    Android:layout_height="wrap_content"
                    Android:layout_alignParentRight="true"
                    Android:layout_margin="@dimen/carview_margin"
                    Android:layout_toRightOf="@+id/text_bp"
                    Android:drawSelectorOnTop="true"
                    Android:spinnerMode="dropdown"
                   Android:visibility="@{viewModel.type.equals(@string/spinner_type)?  View.VISIBLE : View.GONE}" />
</layout>

Modell anzeigen:

 public class AssessmentGetViewModel {
    private String valueWidth;
    private ArrayList<String> values;
    private String type;
    public String getValueWidth() { return this.valueWidth; }
    public void setValueWidth(String valueWidth) { this.valueWidth = valueWidth; }
    public ArrayList<String> getvalues() { return this.values; }
    public void setvalues(ArrayList<String> values) { this.values = values; }
    public String gettype() { return this.type; }
    public void settype(String type) { this.type = type; }
    }
19
San Jaisy

Ich fand, dass etwas hilfreich sein könnte, aber es ist nicht in der offiziellen Dokumentation für die bidirektionale Datenbindung enthalten.

1. '@ =' Verwendung für die bidirektionale Datenbindung

2. Für die benutzerdefinierte bidirektionale Datenbindung sind die Annotationen "BindingAdapter" und "InverseBindingAdapter" erforderlich.

Für das erste Element zeigten viele Blogger die Verwendung von "@ =" für die bidirektionale Datenbindung. https://halfthought.wordpress.com/2016/03/23/2-way-data-binding-on-Android/

Für das zweite Element, wie @George Mound hier geantwortet hat ( Der Editiercursor wird nach links zurückgesetzt, wenn der Standardtext von edittext ein Gleitkommawert ist ), kann der EditText mit den Annotationen "BindingAdapter" und "InverseBindingAdapter" in beide Richtungen gebunden werden . 

Befolgen Sie die Anweisungen, um eine bidirektionale Bindungsmethode für den Spinner aufzubauen.

Erstellen Sie zunächst Ihr ViewModel oder verwenden Sie Pojo

ViewModel

public class ViewModel {
    private ObservableField<String> text;
    public ViewModel() {
        text = new ObservableField<>();
    }
    public ObservableField<String> getText() {
        return text;
    }
}

Pojo

public class ViewModel {
    private String text;
    public String getText() {
        return text;
    }

    public void setText(String text)
    {
       this.text = text;
    }
}

Zweitens fügen Sie es in Ihre XML ein.

  <Android.support.v7.widget.AppCompatSpinner
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:entries="@array/days"
            bind:selectedValue="@={viewModel.text}"/>

Fügen Sie drittens Ihre Bindung hinzu

public class SpinnerBindingUtil {

    @BindingAdapter(value = {"selectedValue", "selectedValueAttrChanged"}, requireAll = false)
    public static void bindSpinnerData(AppCompatSpinner pAppCompatSpinner, String newSelectedValue, final InverseBindingListener newTextAttrChanged) {
        pAppCompatSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                newTextAttrChanged.onChange();
            }
            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });
        if (newSelectedValue != null) {
            int pos = ((ArrayAdapter<String>) pAppCompatSpinner.getAdapter()).getPosition(newSelectedValue);
            pAppCompatSpinner.setSelection(pos, true);
        }
    }
    @InverseBindingAdapter(attribute = "selectedValue", event = "selectedValueAttrChanged")
    public static String captureSelectedValue(AppCompatSpinner pAppCompatSpinner) {
        return (String) pAppCompatSpinner.getSelectedItem();
    }

}

Wie Sie gesehen haben, hat es "selectedValue" als Variable für den standardmäßig ausgewählten Wert verwendet, aber was ist "selectedValueAttrChanged"? Ich dachte, das hier ist schwierig (ich weiß nicht, warum es nicht null ist, wenn es aufgerufen wird), es muss nicht in xml hinzugefügt werden, da es nur der Rückruf für das Abhören des im Spinner geänderten Elements ist. Dann setzen Sie den onItemSelectedListener und setzen ihn auf die Funktion InverseBindingListener onchange () (Dokumentation und Beispiel hier: https://developer.Android.com/reference/Android/databinding/InverseBindingAdapter.html ). Das Standardereignis lautet "Android: textAttrChanged". Wenn Sie eine benutzerdefinierte bidirektionale Bindungsumkehrung verwenden möchten, müssen Sie das Attribut mit dem Suffix "AttrChanged" verwenden.

Der Standardwert für event ist der Attributname mit dem Suffix "AttrChanged". Im obigen Beispiel wäre der Standardwert Android: textAttrChanged, auch wenn es nicht bereitgestellt wurde.

Zum Schluss in Ihrer Aktivität und in Ihrer string.xml

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ActivityMainBinding lBinding = DataBindingUtil.inflate(LayoutInflater.from(this), R.layout.activity_main, null, false);
    mViewModel = new ViewModel();
    mViewModel.getText().set("Wednesday");
    lBinding.setViewModel(mViewModel);
    lBinding.setHandler(new Handler());
    setContentView(lBinding.getRoot());
}

string.xml

<array name="days">
    <item name="Mon">Monday</item>
    <item name="Tue">Tuesday</item>
    <item name="Wed">Wednesday</item>
</array>

Wenn Sie den Code ausführen, wird "Mittwoch" als Standardwert für den Spinner angezeigt. Hoffe, das kann vielen Menschen helfen

22
Long Ranger

Sie können dies auf einfache Weise mit useItItSelected tun und die ausgewählte Position und den ausgewählten Elementtext erhalten.

1) Fügen Sie das onItemSelected -Attribut wie folgt zu Ihrem Spinner hinzu:

<Spinner
      Android:id="@+id/spinner"
      Android:layout_width="match_parent"
      Android:layout_height="wrap_content"
      Android:entries="@array/item_list"
      Android:onItemSelected="@{(parent,view,pos,id)->viewModel.onSelectItem(parent,view,pos,id)}"/>

2) Jetzt müssen Sie diese Methode zu Ihrem viewModel hinzufügen:

public void onSelectItem(AdapterView<?> parent, View view, int pos, long id)
{
    //pos                                 get selected item position
    //view.getText()                      get lable of selected item
    //parent.getAdapter().getItem(pos)    get item by pos
    //parent.getAdapter().getCount()      get item count
    //parent.getCount()                   get item count
    //parent.getSelectedItem()            get selected item
    //and other...
}

array könnte etwas sein, das in values ​​/ item_list.xml gespeichert werden muss:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <array name="item_list">
        <item>item1</item>
        <item>item2</item>
        <item>item3</item>
    </array>
</resources>

Wenn das Layout gezeichnet wird, wird onItemSelected aufgerufen, und Sie können den Anfangswert festlegen:

parent.setSelection(1); //1 is position of initializing value
8

1-Zeilen-Lösung

Android:selectedItemPosition="@={item.selectedItemPosition}"

Das ist es! Sie müssen keinen benutzerdefinierten BindingAdapter erstellen.

Der Spinner unterstützt die bidirektionale Bindung durch die Attribute selection und selectedItemPosition. Siehe Android-Dokumentation

Sie müssen nur die bidirektionale Bindung selectedItemPosition verwenden, damit Änderung beim Spinner reflektiert Ihr Modellfeld.

Beispiel

Item.class

public class Item extends BaseObservable {
    private int selectedItemPosition;

    @Bindable
    public int getSelectedItemPosition() {
        return selectedItemPosition;
    }

    public void setSelectedItemPosition(int selectedItemPosition) {
        this.selectedItemPosition = selectedItemPosition;
        notifyPropertyChanged(BR.selectedItemPosition);
    }
}

activity_main.xml

<variable
    name="item"
    type="com.sample.data.Item"/>

<Android.support.v7.widget.AppCompatSpinner
    ...
    Android:entries="@array/items"
    Android:selectedItemPosition="@={item.selectedItemPosition}"
    >

MainActivity.Java

public class MainActivity extends AppCompatActivity {
    ActivityMainBinding binding;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        binding.setItem(new Item());
        binding.getItem().setSelectedItemPosition(4); // this will change spinner selection.
        System.out.println(getResources().getStringArray(R.array.items)[binding.getItem().getSelectedItemPosition()]);
    }
}

Wenn Sie das ausgewählte Element jederzeit aus Ihrem Code holen müssen, verwenden Sie diese Option

binding.getItem().getSelectedItemPosition(); // get selected position
getResources().getStringArray(R.array.items)[binding.getItem().getSelectedItemPosition()]) // get selected item

Machen Sie Ihre Variable @Bindable, wenn Sie sie programmgesteuert ändern müssen. 

binding.getItem().setSelectedItemPosition(4);

Ansonsten können Sie @Bindable und notifyPropertyChanged(BR.selectedItemPosition); entfernen.

Sie können BaseObservable oder ObservableField oder Live Data verwenden. Es liegt an dir. Ich benutze BaseObservable weil es sehr einfach ist., gehen Sie einfach von BaseObservable aus und alle Felder sind jetzt einsehbar.

3
Khemraj

meine Antwort um einfachste Datenbindung mit dem Spinner zu erreichen In der Tat brauchen wir einen Adapter, um weitere Aufgaben zu erledigen.

XML-Code ist vorhanden.

Java:


    //  Data binding
        ActivityParentsRegBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_parents_reg);
        binding.setCities(ConstData.getCitiesList());
0
ForWebTech

1-Create One class Zum Benennen des Speicherorts und Festlegen des Codes für die Klasse Zum Beispiel

public class Location {

    private int Id;
    private String Title;

    public Location(int Id,String Title){
        this.Id=Id;
        this.Title=Title;
    }

    public int getId() {
        return Id;
    }

    public void setId(int id) {
        Id = id;
    }

    public String getTitle() {
        return Title;
    }

    public void setTitle(String title) {
        Title = title;
    }

    @Override
    public String toString() {
        return Title;
    }
}

2-Erstelle ein Spinner und schreibe diesen Code nach Java

Spinner cmb_Area = view.findViewById(R.id.Fragment_Add_Home_cmb_Area);

ArrayList<Location> locations= new ArrayList<>();

locations.add(new Location(1,"London"));
locations.add(new Location(2,"Paris"));

ArrayAdapter<Location> adapter2 = new ArrayAdapter<Location>(getActivity(), Android.R.layout.simple_spinner_dropdown_item, locations);

cmb_Area.setAdapter(adapter2);

3-Schreiben Sie diesen Code, um ein Element auszuwählen

cmb_Area.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
        Location location = (Location) parent.getSelectedItem();
        Toast.makeText(getActivity(),location.getId(),Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onNothingSelected(AdapterView<?> parent) {
    }
});
0
Diako Hasani

@Long Ranger Ich mag deine Antwort wirklich sehr, aber ich denke, es gibt etwas, was wir tun müssen, um die Schleife zu durchbrechen.

@BindingAdapter(value = {"bind:selectedValue", "bind:selectedValueAttrChanged"}, requireAll = false)
public static void bindSpinnerData(AppCompatSpinner pAppCompatSpinner, final String newSelectedValue, final InverseBindingListener newTextAttrChanged) {
    pAppCompatSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            if(newSelectedValue != null && newSelectedValue.equals(parent.getSelectedItem())){
               return;
            }
            newTextAttrChanged.onChange();
        }
        @Override
        public void onNothingSelected(AdapterView<?> parent) {
        }
    });
    if (newSelectedValue != null) {
        int pos = ((ArrayAdapter<String>) pAppCompatSpinner.getAdapter()).getPosition(newSelectedValue);
        pAppCompatSpinner.setSelection(pos, true);
    }
}
0
user2297951