Android 数据绑定 layout_width 和 layout_height
Posted
技术标签:
【中文标题】Android 数据绑定 layout_width 和 layout_height【英文标题】:Android Data Binding layout_width and layout_height 【发布时间】:2016-05-19 14:52:00 【问题描述】:我需要能够动态设置 EditText 的高度属性。我在整个应用程序中对其他属性使用数据绑定,因此我希望能够使用数据绑定来控制元素的高度。这是我的 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_
android:layout_
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>
这是我的视图模型的精简版:
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
ComponentInfocom.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 的帖子,但没有明确的答案或方法不起作用。当然,这是一种常见的实现。提前感谢您的帮助。
【问题讨论】:
“这肯定是一种常见的实现”——考虑到数据绑定仍然是一个候选版本,我不会认为与数据绑定相关的任何东西都是“常见的” ”。如果您不能以这种方式设置高度和宽度,我不会感到惊讶,因为该数据会在布局膨胀后立即得到验证,到那时您还没有注入模型,更不用说设置这些属性了。可能有一些解决方法,使用您应用绑定表达式的合成属性(例如,app:width
)来调整视图的LayoutParams
。
你可能是完全正确的。我猜是因为我熟悉其他平台(Windows)上的数据绑定,我只是希望它在 Android 上也很常见。
【参考方案1】:
在 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_
像这样导入应用程序
xmlns:app="http://schemas.android.com/apk/res-auto"
【讨论】:
我必须为它添加一个默认值才能工作 android:layout_ @Shubham 我不知道什么时候会使用默认值。 smallScreen 只有 2 种情况(真或假) @PhanVanLinh 对我来说它给出了错误 java.lang.RuntimeException: Binary XML file line #21: You must provide a layout_width attribute if I didn't add a default value 别忘了转换成 intlayoutParams.height = height.toInt()
到
@Shubham 您需要提供一个默认值。 app:layout_height="@ viewModel.isBig ? @dimen/dp_20 : @dimen/dp_5 , default=wrap_content"
【参考方案2】:
当使用数据绑定时,我们会从 XML 中删除值。您可以添加一个在剥离时使用的默认值以避免该问题。
请参阅:http://developer.android.com/tools/data-binding/guide.html(页面底部)。
android:layout_
【讨论】:
它对我不起作用:Error:(13, 34) Cannot find the setter for attribute 'android:layout_width' with parameter type float on android.widget.LinearLayout.
@GuilhermeTorresCastro 请在下面查看我的答案
我们要设置什么计算高度而不是从 xml?【参考方案3】:
根据Android问题跟踪器的讨论,如果不创建自定义绑定适配器,就无法使用数据绑定设置布局高度或宽度:
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);
【讨论】:
谢谢,它为我节省了数小时的搜索时间! 对我不起作用,我得到“你必须提供 layout_height 属性”【参考方案4】:我用 Kotlin 而不是 Java 解决了这个问题。
制作一个名为
的文件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_
bind:customHeight="@loginVM.compact ? @dimen/verificationHeightCompact : @dimen/verificationHeightFull"
android:layout_/>
【讨论】:
【参考方案5】:对我来说,这是诀窍:
@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_
【讨论】:
【参考方案6】:您可以为 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_
android:layout_
附言: 不要忘记设置默认值
【讨论】:
【参考方案7】:这是一种简洁的、可扩展的机制,用于使用布尔值在两个 layout_height
或 layout_width
状态之间切换。您需要将 LayoutWidthHeightBindingAdapterVariants 类导入布局,以在布局中指定其值之一:
@BindingAdapter(value = ["android:layout_height", "app:layout_widthHeightVariant"])
fun expandContractHeight(view: View, flag: Boolean, variant: LayoutWidthHeightBindingAdapterVariants)
val params = view.layoutParams
params.height = if (flag) variant.valueWhenTrue else variant.valueWhenFalse
view.layoutParams = params
view.invalidate()
@BindingAdapter(value = ["android:layout_width", "app:layout_widthHeightVariant"])
fun expandContractWidth(view: View, flag: Boolean, variant: LayoutWidthHeightBindingAdapterVariants)
val params = view.layoutParams
params.height = if (flag) variant.valueWhenTrue else variant.valueWhenFalse
view.layoutParams = params
view.invalidate()
enum class LayoutWidthHeightBindingAdapterVariants(val valueWhenFalse: Int, val valueWhenTrue: Int)
// format: <falseValue>_TO_<trueValue>
WRAP_TO_MATCH(WRAP_CONTENT, MATCH_PARENT),
MATCH_TO_WRAP(MATCH_PARENT, WRAP_CONTENT),
WRAP_TO_ZERODP(WRAP_CONTENT, 0),
ZERODP_TO_WRAP(0, WRAP_CONTENT)
【讨论】:
以上是关于Android 数据绑定 layout_width 和 layout_height的主要内容,如果未能解决你的问题,请参考以下文章
绑定MvvmCross TextColor不适用于Android