アクティビティクラスにObservableBoolean
フィールドがあり、ToggleButton
の「checked」属性にバインドされています。
Android:checked="@{activity.editing}"
これによりボタンとブール値の間に双方向の関係が作成されることを期待していましたが、フィールドからボタンへの変更のみを保持し、他の方法では保持しません。私は何を間違えていますか、またはこれはAndroid DataBinding
の範囲内にありませんか?
双方向データバインディングを使用することをAndroidに伝えるには、別の '='が必要です。
Android:checked="@={activity.editing}"
詳細については、こちらをご覧ください wordpress George Mountの記事 :
双方向データバインディング
Androidは通常のデータ入力の影響を受けません。多くの場合、ユーザーの入力からの変更をモデルに反映することが重要です。たとえば、上記のデータが連絡先フォームにある場合、EditTextからデータをプルすることなく、編集したテキストをモデルに押し戻すことができます。方法は次のとおりです。
<layout ...>
<data>
<variable type="com.example.myapp.User" name="user"/>
</data>
<RelativeLayout ...>
<EditText Android:text="@={user.firstName}" .../>
</RelativeLayout>
</layout>
かなり気の利いた、え?ここでの唯一の違いは、式が
@={}
ではなく@{}
でマークされていることです。ほとんどのデータバインディングは一方向であり続けるため、これらのリスナーをすべて作成し、決して発生しない変更を監視することは望ましくありません。
ObservableBoolean
を使用する必要はありません。ブール変数の通常のgetter-setterメソッドでこの操作を実行できます。あなたのモデルクラスでこのように
public class User{
private boolean checked;
public boolean isChecked() {
return checked;
}
public void setChecked(boolean checked) {
this.checked = checked;
}
}
ToggleButton
で双方向バインディングを実行します。
<ToggleButton
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:checked="@={user.checked}"/>
バインド変数を使用してこの値を取得します。
binding.getUser().isChecked()
ToggleButtonのようなCheckedプロパティも持つSwitchを使用した2方向のデータバインディングの簡単な例を次に示します。
Item.Java:
import Android.databinding.BaseObservable;
import Android.databinding.Bindable;
public class Item extends BaseObservable {
private Boolean checked;
@Bindable
public Boolean getChecked() {
return this.checked;
}
public void setChecked(Boolean checked) {
this.checked = checked;
notifyPropertyChanged(BR.checked);
}
}
MainActivity.Java:
public class MainActivity extends AppCompatActivity {
public Item item;
ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
item = new Item();
item.setChecked(true);
/* By default, a Binding class will be generated based on the name of the layout file,
converting it to Pascal case and suffixing “Binding” to it.
The above layout file was activity_main.xml so the generate class was ActivityMainBinding */
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
binding.setItem(item);
}
public void button_onClick(View v) {
item.setChecked(!item.getChecked());
}
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:Android="http://schemas.Android.com/apk/res/Android">
<data>
<variable
name="item"
type="com.example.abc.twowaydatabinding.Item" />
</data>
<LinearLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:orientation="vertical">
<Switch
Android:id="@+id/switch_test"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:checked="@={item.checked}" />
<Button
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:text="change"
Android:onClick="button_onClick"/>
</LinearLayout>
</layout>
build.gradle:
Android {
...
dataBinding{
enabled=true
}
}
ソースドキュメント: https://developer.Android.com/topic/libraries/data-binding/index.html
データバインディングでOnCheckedChangeListener
を設定する方法は次のとおりです:
レイアウト内
<variable
name="activity"
type="com.innovanathinklabs.sample.activities.CalendarActivity"/>
<ToggleButton
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:checked="@={model.checked}"
Android:onCheckedChanged="@{activity::onGenderChanged}"
/>
アクティビティ中
class HomeActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = DataBindingUtil.setContentView<ActivityCalendarBinding>(this, R.layout.activity_calendar)
binding.activity = this
binding.model = Model()
}
fun onGenderChanged(buttonView: CompoundButton, isChecked: Boolean) {
println("buttonView = [$buttonView], isChecked = [$isChecked]")
}
}
<variable
name="model"
type="com.innovanathinklabs.sample.data.Model"/>
<variable
name="activity"
type="com.innovanathinklabs.sample.activities.HomeActivity"/>
<ToggleButton
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:checked="@={model.checked}"
Android:onCheckedChanged="@{(button, bool)-> activity.saveGender(bool)}"
/>
活動中
class HomeActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = DataBindingUtil.setContentView<ActivityCalendarBinding>(this, R.layout.activity_calendar)
binding.activity = this
binding.model = Model()
}
fun saveGender(isChecked: Boolean) {
println("isChecked = [$isChecked]")
}
}
OnCheckedChangeListener
匿名クラスをレイアウトに渡します<variable
name="onGenderChange"
type="Android.widget.CompoundButton.OnCheckedChangeListener"/>
<ToggleButton
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:checked="@={model.checked}"
Android:onCheckedChanged="@{onGenderChange}"
/>
活動中
class HomeActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = DataBindingUtil.setContentView<ActivityCalendarBinding>(this, R.layout.activity_calendar)
binding.model = Model()
binding.setOnGenderChange { buttonView, isChecked ->
println("buttonView = [$buttonView], isChecked = [$isChecked]")
}
}
}
OnCheckedChangeListener
を参照渡し<variable
name="onGenderChange2"
type="Android.widget.CompoundButton.OnCheckedChangeListener"/>
<ToggleButton
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:checked="@={model.checked}"
Android:onCheckedChanged="@{onGenderChange2}"
/>
アクティビティ
class HomeActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = DataBindingUtil.setContentView<ActivityCalendarBinding>(this, R.layout.activity_calendar)
binding.model = Model()
binding.onGenderChange2 = onGenderChange
}
private val onGenderChange: CompoundButton.OnCheckedChangeListener = CompoundButton.OnCheckedChangeListener { buttonView, isChecked ->
println("buttonView = [$buttonView], isChecked = [$isChecked]")
}
}
1つのコンポーネントに2つのコールバックを設定できないためです。 1つのコールバックはすでに双方向バインディングによって設定されているため、コールバックは機能しません。
binding.toggleButton.setOnCheckedChangeListener { buttonView, isChecked -> println("buttonView = [$buttonView], isChecked = [$isChecked]") }
CheckCompoundButtonBindingAdapterclass Switch Bindingの動作を確認します。