2016-02-09 4 views
8

Мне нужно иметь возможность динамически устанавливать свойство высоты EditText. Я использую привязку данных для других свойств в моем приложении, поэтому мне бы хотелось использовать привязку данных для управления высотой моих элементов. Вот урезанная версия моего XML:привязка данных Android layout_width и layout_height

<?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 относительно этой проблемы, но нет окончательных ответов или в подход не работает. Конечно, это обычная реализация. Заранее спасибо за помощь.

+1

«Конечно, это реализация, которая является общим» - учитывая, что связывание данных по-прежнему является релиз-кандидат, Я бы не рассматривал * что-либо *, связанное с привязкой данных, чтобы быть «общим». Я не удивлюсь, если вы не сможете установить высоту и ширину таким образом, поскольку эти данные будут проверены сразу же после раздувания макета, и к этому моменту вы еще не ввели бы модель, не говоря уже об установке этих атрибутов. Возможно, существует некоторое обходное решение, использующее синтетическое свойство (например, 'app: width'), к которому вы применяете свое выражение привязки, которое настраивает« LayoutParams »вашего представления. – CommonsWare

+0

Возможно, вы абсолютно правы. Я думаю, из-за моего знакомства с привязкой данных к другим платформам (Windows), я просто ожидал, что это будет обычным явлением и на Android. –

ответ

18

При использовании привязки данных мы удаляем значения из XML. Вы можете добавить значение по умолчанию, которое будет использоваться, когда оно будет удалено, чтобы избежать проблемы.

см: http://developer.android.com/tools/data-binding/guide.html (внизу страницы).

android:layout_height="@{loginVM.compact ? @dimen/verificationHeightCompact : @dimen/verificationHeightFull, default=wrap_content}" 
+0

Я не видел этого ни на одной другой нити SO. Спасибо! –

+2

Это не сработало для меня: 'Ошибка: (13, 34) Не удается найти установщик для атрибута 'android: layout_width' с типом параметра float на android.widget.LinearLayout. ' –

+0

@GuilhermeTorresCastro, пожалуйста, проверьте мой ответ ниже –

1

Согласно дискуссии по вопросу отслеживания 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); 
} 
8

В 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" 
+1

Это должен быть правильный ответ – Badjano

+1

спасибо, что напомнилось мне, сделано! – Badjano

+0

Мне пришлось добавить значение по умолчанию для работы на Android: layout_height = "@ {smallScreen? @ Dimen/dp_20: @ dimen/dp_5, default = wrap_content}" – Shubham

Смежные вопросы