web-dev-qa-db-fra.com

Liaison de données Android layout_width et layout_height

Je dois pouvoir définir de manière dynamique la propriété height d'un EditText. J'utilise la liaison de données pour d'autres propriétés dans l'application, alors j'aimerais pouvoir utiliser la liaison de données pour contrôler la hauteur de mes éléments. Voici une version allégée de mon 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> 

Et voici une version allégée de mon modèle View:

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();
}

Les dimensions sont dans le fichier dimens.xml. Et je modifie les propriétés dans le modèle de vue. Mais, lorsque je lance l'application, l'erreur suivante apparaît immédiatement après le lancement (bindingadapter ne se déclenche pas lors du débogage). J'ai plusieurs autres éléments à l'écran mais celui-ci est celui dont j'ai besoin pour changer la hauteur lorsqu'une action particulière se produit:

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.

Il y a quelques articles sur SO concernant cette question, mais aucune réponse définitive ou l'approche n'a pas fonctionné. C’est sûrement une implémentation courante. Merci d'avance pour l'aide.

13
John Murphy

En java

@BindingAdapter("layout_height")
public static void setLayoutHeight(View view, float height) {
    LayoutParams layoutParams = view.getLayoutParams();
    layoutParams.height = height;
    view.setLayoutParams(layoutParams);
}

Et dans votre XML

app:layout_height="@{ viewModel.isBig ? @dimen/dp_20 : @dimen/dp_5 }"

importer l'application comme ça

xmlns:app="http://schemas.Android.com/apk/res-auto"
20
Linh

Lorsque la liaison de données est utilisée, nous supprimons les valeurs du XML. Vous pouvez ajouter une valeur par défaut à utiliser lorsqu’elle est supprimée pour éviter le problème.

voir: http://developer.Android.com/tools/data-binding/guide.html (en bas de la page).

Android:layout_height="@{loginVM.compact ? @dimen/verificationHeightCompact : @dimen/verificationHeightFull, default=wrap_content}"
31
yigit

Selon la discussion sur Android Issue Tracker, il est impossible de définir la hauteur ou la largeur de la disposition avec la liaison de données sans créer d'adaptateurs de liaison personnalisés:

https://code.google.com/p/Android/issues/detail?id=180666

L'adaptateur de liaison nécessaire pour définir la hauteur de vue ressemblerait à ceci:

@BindingAdapter("Android:layout_height")
public static void setLayoutHeight(View view, int height) {
    LayoutParams layoutParams = view.getLayoutParams();
    layoutParams.height = height;
    view.setLayoutParams(layoutParams);
}
5
KubaK

Je l'ai résolu comme ça à Kotlin.

Faire un fichier appelé 

MyBindings.kt

Et mettre en:

@BindingAdapter("bind:customHeight")
fun setLayoutHeight(view: View, height: Float) {
    view.layoutParams = view.layoutParams.apply { this.height = height.toInt() }
}

Et vous pouvez ensuite utiliser cela dans vos mises en page:

<EditText 
Android:id="@+id/internalTopDisplay"
Android:layout_width="match_parent"
bind:customHeight="="@{loginVM.compact ? @dimen/verificationHeightCompact : @dimen/verificationHeightFull}"
Android:layout_height="wrap_content"/>
1
Andreas Rudolph

Pour moi, c'est le truc:

    @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);
    }

Et le xml:

Android:layout_height="@{item.isItemCollapsed ? @dimen/radar_item_first_background_height  : item.textMaxLines, default=@dimen/radar_item_first_background_height}"
0
rxDroid