昨天了解如何使用databinding的單向綁定,把data放到view裡,那反過來當view發生變化,data也能跟著改變呢?
這時就會用到了databinding的雙向綁定。
當EditText在進行輸入時TextView也會跟著顯示EditText正在輸入的內容
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{dataItem.name}"
android:textSize="20sp"/>
<EditText
android:layout_width="200dp"
android:layout_height="wrap_content"
android:text="@={dataItem.name}"
android:textSize="20sp"/>
跟之前databinding的賦值一樣,只是EditText的text賦值會變成@={dataItem.name}(在@{}中間加個等號),當EditText的text一改變,那麼TextView的text也會及時改變,這是一個簡單的雙向綁定。
實作:將seekbar隨意調動,TextView會顯示其數字。
@BindingAdapter(value = {"progressNow"})
public static void setProgressNow(SeekBar seekBar,String progressNum){
int value = 0;
try {
value = Integer.parseInt(progressNum);
} catch (NumberFormatException e) {
}
seekBar.setProgress(value);
}
自定義屬性app:progressNow,將SeekBar與viewModel做雙向綁定,當app:progressNow發生改變時要如何get app:progressNow
的值,這時可以用InverseBindingAdapter
去達成。
//@InverseBindingAdapter(attribute = "attribute_name",event="")event屬性:雙向綁定時對view的變化發出通知。
@InverseBindingAdapter(attribute = "progressNow")
public static String getProgressNow(SeekBar seekBar){
return ""+seekBar.getProgress();
}
1.@InverseBindingAdapter
的屬性必須跟BindingAdapter自定義的屬性一樣
2.可以看到@InverseBindingAdapter只配置了一個(attribute = "progressNow"),而event沒有配置,那麼會使用Default:將event的屬性值為"{屬姓名}+AttrChanged" (EX:progressNowAttrChanged)。
@BindingAdapter(value = {"onProgressChanged","progressNowAttrChanged"},requireAll = false)
public static void setProgressNowAttrChanged(SeekBar seekBar,final SeekBar.OnSeekBarChangeListener listener,final InverseBindingListener attrChange){//註解中屬性的順序與方法中的參數順序要保持一致,也就是說屬性的`onProgressChanged`會對應到`SeekBar.OnSeekBarChangeListener listener`,而`progressNowAttrChanged`對應`InverseBindingListener attrChange`,
if (attrChange ==null){
seekBar.setOnSeekBarChangeListener(listener);
}else{
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
//當seekbar的值改變時,InverseBindingListener會進行 attrChange.onChange()。
attrChange.onChange();
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
}
設置MODEL
public class DataItem2 {
public final ObservableField<String> progressNum= new ObservableField<>();
}
設置UI
<SeekBar
android:layout_width="match_parent"
android:layout_height="50dp"
app:progressNow="@={observableData2.progressNum}"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{observableData2.progressNum}"
android:gravity="center"
android:textSize="50sp"/>
在seekbar加上@={}
MainActivity2
public class MainActivity2 extends AppCompatActivity {
ActivityMain2Binding main2Binding;
DataItem2 dataItem2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
init();
}
private void init() {
main2Binding=DataBindingUtil.setContentView(this,R.layout.activity_main2);
dataItem2=new DataItem2();
main2Binding.setObservableData2(dataItem2);
}
}
tip: BindingAdapter當成是setter,InverseBindingAdapter是getter
這樣就完成囉