EditTextのheightプロパティを動的に設定できる必要があります。アプリ全体で他のプロパティにデータバインディングを使用しているため、データバインディングを使用して要素の高さを制御できるようになりたいと考えています。これは、私のxmlの簡略版です。
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto">
<data>
<variable name="loginVM" type="com.testing.stuff.ViewModels.LoginViewModel" />
</data>
<EditText Android:inputType="number"
Android:id="@+id/txtVerificationCode"
Android:layout_height="@{loginVM.compact ? @dimen/verificationHeightCompact : @dimen/verificationHeightFull}"
Android:layout_width="match_parent"
Android:paddingRight="16dp"
Android:paddingLeft="16dp"
Android:focusable="true"
Android:focusableInTouchMode="true"
Android:layout_marginLeft="10dp"
Android:alpha="@{loginVM.verificationOpacity}"
Android:layout_marginStart="10dp"
Android:textAlignment="center"
Android:visibility="visible"
Android:hint="Enter verificationCode"
Android:text="@{loginVM.verificationCode}" />
</layout>
そして、これが私のView Modelの簡略版です:
public class LoginViewModel extends BaseObservable {
public final ObservableField<String> verificationCode;
public final ObservableField<Boolean> compact;
@Bindable
public String getVerificationCode() {
if (this.verificationCode == null) {
return "";
} else {
return this.verificationCode.get();
}
}
public void setVerificationCode(String verificationCode) {
this.verificationCode.set(verificationCode);
invalidateProperties();
}
@Bindable
public Boolean getCompact(){return this.compact.get();}
public void setCompact(Boolean value)
{
this.compact.set(value);
this.invalidateProperties();
}
@BindingAdapter("Android:layout_height")
public static void setLayoutHeight(EditText view, float height)
{
ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
layoutParams.height = (int)height;
view.setLayoutParams(layoutParams);
}
public LoginViewModel(Context ctx) {
verificationCode = new ObservableField();
compact = new ObservableField();
}
ディメンションはdimens.xmlファイルにあります。そして、ビューモデルのプロパティを変更しています。しかし、アプリを起動すると、起動直後に次のエラーが表示されます(バインディングアダプターがデバッグ時に起動しません)。画面には他にもいくつかの要素がありますが、特定のアクションが発生したときに高さを変更する必要があるのはこの特定の要素です。
FATAL EXCEPTION: main
Process: com.testing.stuff, PID: 32752
Java.lang.RuntimeException: Unable to start activity
ComponentInfo{com.testing.stuff/com.testing.stuff.Login}:
Java.lang.RuntimeException: Binary XML file line #69: You must supply
a layout_height attribute.
Caused by: Java.lang.RuntimeException: Binary XML file line #69: You
must supply a layout_height attribute.
この問題に関してSOにいくつかの投稿がありますが、明確な回答がないか、アプローチが機能しませんでした。確かにこれは一般的な実装です。助けてくれてありがとう。
Javaで
@BindingAdapter("layout_height")
public static void setLayoutHeight(View view, float height) {
LayoutParams layoutParams = view.getLayoutParams();
layoutParams.height = height;
view.setLayoutParams(layoutParams);
}
そしてあなたのXMLで
app:layout_height="@{ viewModel.isBig ? @dimen/dp_20 : @dimen/dp_5 }"
このようなアプリをインポートします
xmlns:app="http://schemas.Android.com/apk/res-auto"
データバインディングを使用する場合、XMLから値を取り除きます。この問題を回避するために、デフォルト値を削除するときに使用するデフォルト値を追加できます。
参照: http://developer.Android.com/tools/data-binding/guide.html (ページの下部)。
Android:layout_height="@{loginVM.compact ? @dimen/verificationHeightCompact : @dimen/verificationHeightFull, default=wrap_content}"
Android issue trackerの議論によると、カスタムバインディングアダプタを作成せずにデータバインディングでレイアウトの高さまたは幅を設定することは不可能です。
https://code.google.com/p/Android/issues/detail?id=180666
ビューの高さを設定するために必要なバインディングアダプターは次のようになります。
@BindingAdapter("Android:layout_height")
public static void setLayoutHeight(View view, int height) {
LayoutParams layoutParams = view.getLayoutParams();
layoutParams.height = height;
view.setLayoutParams(layoutParams);
}
Kotlinでこのように解決しました。
というファイルを作成する
MyBindings.kt
入れてください:
@BindingAdapter("bind:customHeight")
fun setLayoutHeight(view: View, height: Float) {
view.layoutParams = view.layoutParams.apply { this.height = height.toInt() }
}
そして、これをレイアウトで使用できます。
<EditText
Android:id="@+id/internalTopDisplay"
Android:layout_width="match_parent"
bind:customHeight="="@{loginVM.compact ? @dimen/verificationHeightCompact : @dimen/verificationHeightFull}"
Android:layout_height="wrap_content"/>
私にとってこれはトリックでした:
@BindingAdapter("Android:layout_height")
public static void setLayoutHeight(View view, final Number height) {
final ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
layoutParams.height = height.intValue();
view.setLayoutParams(layoutParams);
}
そして、xml:
Android:layout_height="@{item.isItemCollapsed ? @dimen/radar_item_first_background_height : item.textMaxLines, default=@dimen/radar_item_first_background_height}"
Android:layout_heightのフロートを取り込むバインディングアダプターを追加できます。
高さの場合:
@BindingAdapter("Android:layout_height")
public static void setLayoutHeight(View view, float height) {
ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
layoutParams.height = (int) height;
view.setLayoutParams(layoutParams);
}
幅:の場合
@BindingAdapter("Android:layout_width")
public static void setLayoutWidth(View view, float height) {
ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
layoutParams.width = (int) height;
view.setLayoutParams(layoutParams);
}
使用法:
Android:layout_width="@{model.isBig ? @dimen/big_dimen : @dimen/small_dimen, default=wrap_content}"
Android:layout_height="@{model.isBig ? @dimen/big_dimen : @dimen/small_dimen, default=wrap_content}"
[〜#〜] ps [〜#〜]:デフォルト値を設定することを忘れないでください