2016-02-09 18 views
8

Ich muss die Eigenschaft height eines EditText dynamisch setzen können. Ich verwende Datenbindung für andere Eigenschaften in meiner App, daher würde ich gerne Datenbindung verwenden können, um die Höhe meiner Elemente zu steuern. Hier ist eine abgespeckte Version meiner xml:Android-Datenbindung layout_width und 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> 

Und hier ist eine abgespeckte Version meiner Ansicht Modell:

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

Die Abmessungen sind in der dimens.xml Datei. Und ich modifiziere die Eigenschaften im View-Modell. Aber wenn ich die App starte, erhalte ich unmittelbar nach dem Start den folgenden Fehler (der Bindungsadapter feuert nicht auf debug). Ich habe einige andere Elemente auf dem Bildschirm, aber diese besondere ist die, ich brauche die Höhe zu ändern, wenn eine bestimmte Aktion eintritt:

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. 

Es gibt ein paar Beiträge über SO bezüglich dieses Problems aber keine endgültigen Antworten oder die Ansatz hat nicht funktioniert. Sicher ist dies eine Implementierung, die üblich ist. Vielen Dank im Voraus für die Hilfe.

+1

"Sicherlich ist dies eine Implementierung, die üblich ist" - man bedenkt, dass die Datenbindung noch ein Release-Kandidat ist, Ich würde * nichts * in Bezug auf die Datenbindung als "üblich" betrachten. Ich würde nicht überrascht sein, wenn Sie die Höhe und Breite nicht auf diese Weise festlegen können, da diese Daten sofort beim Aufblasen des Layouts validiert werden, und zu diesem Zeitpunkt haben Sie das Modell noch nicht injiziert, geschweige denn diese Attribute festgelegt. Es ist möglich, dass es eine Problemumgehung gibt, indem Sie eine synthetische Eigenschaft (z. B. "app: width") verwenden, auf die Sie Ihren Bindungsausdruck anwenden, der die LayoutParams Ihrer Ansicht anpasst. – CommonsWare

+0

Sie können absolut richtig sein. Ich denke, aufgrund meiner Vertrautheit mit Datenbindung auf anderen Plattformen (Windows) habe ich nur erwartet, dass es auch auf Android üblich ist. –

Antwort

18

Wenn Datenbindung verwendet wird, entfernen wir Werte aus dem XML. Sie können einen Standardwert hinzufügen, der beim Entfernen verwendet wird, um das Problem zu vermeiden.

siehe: http://developer.android.com/tools/data-binding/guide.html (unten auf der Seite).

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

Ich habe das auf keinem anderen SO-Thread gesehen. Vielen Dank! –

+2

Es hat bei mir nicht funktioniert: 'Fehler: (13, 34) Der Setter für das Attribut 'android: layout_width' mit dem Parameter type float konnte nicht auf android.widget.LinearLayout gefunden werden. ' –

+0

@GuilhermeTorresCastro bitte überprüfen Sie meine Antwort unter –

1

Nach der Diskussion über Android issue tracker, ist es unmöglich, ohne benutzerdefinierte Bindung Adapter zu schaffen Bindung Layout Höhe oder Breite mit Daten einzustellen:

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

Die Bindung Adapter für die Einstellung Ansicht benötigt Höhe würde so aussehen, dass:

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

In Java

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

Und in Ihrem XML-

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

Import der App wie diese

xmlns:app="http://schemas.android.com/apk/res-auto" 
+1

Dies sollte die richtige Antwort sein – Badjano

+1

danke für die Erinnerung, fertig! – Badjano

+0

Ich musste einen Standardwert für Android hinzufügen: layout_height = "@ {smallScreen? @ Dimen/dp_20: @ dimen/dp_5, default = wrap_content}" – Shubham

Verwandte Themen