2016-01-14 5 views
27

Android data binding guide обсуждает значения привязки в рамках действия или фрагмента, но есть ли способ выполнить привязку данных к пользовательскому представлению?привязка данных к андроиду с настраиваемым представлением

Я хотел бы сделать что-то вроде:

<LinearLayout 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 

    <com.mypath.MyCustomView 
     android:id="@+id/my_view" 
     android:layout_width="match_parent" 
     android:layout_height="40dp"/> 

</LinearLayout> 

с my_custom_view.xml:

<layout> 

<data> 
    <variable 
     name="myViewModel" 
     type="com.mypath.MyViewModelObject" /> 
</data> 

<LinearLayout 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 

    <TextView 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:text="@{myViewModel.myText}" /> 

</LinearLayout> 

</layout> 

Хотя представляется возможным сделать это путем установки пользовательских атрибутов пользовательского вида, это быстро станет неразборчивым если есть много значений для привязки.

Есть ли хороший способ добиться того, что я пытаюсь сделать?

+0

Пробовали ли вы связывание данных в классе MyCustomView после раздувания вида логотего? –

+0

Я пробовал несколько вещей, чтобы выполнить это, но функции привязки, похоже, требуют информации, содержащейся в действии или фрагменте. В их примерах не приводится образец того, как это сделать в пользовательском представлении. Краткий фрагмент кода о том, как это сделать, будет очень оценен. – Dave

+0

FYI: Я думаю, что файлы макета xml называются с обозначением подчеркивания по соглашению. –

ответ

31

В вашем настраиваемое представление, раздуть макет, однако вы обычно делаете, и обеспечить сеттера для атрибута вы хотите установить:

private MyCustomViewBinding mBinding; 
public MyCustomView(...) { 
    ... 
    LayoutInflater inflater = (LayoutInflater) 
     context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
    mBinding = MyCustomViewBinding.inflate(inflater); 
} 

public void setMyViewModel(MyViewModelObject obj) { 
    mBinding.setMyViewModel(obj); 
} 

Затем в макете вы используете его в:

<layout xmlns...> 
    <data> 
     <variable 
      name="myViewModel" 
      type="com.mypath.MyViewModelObject" /> 
    </data> 

    <LinearLayout 
     android:layout_width="match_parent" 
     android:layout_height="match_parent"> 

     <com.mypath.MyCustomView 
      android:id="@+id/my_view" 
      app:myViewModel="@{myViewModel}" 
      android:layout_width="match_parent" 
      android:layout_height="40dp"/> 

    </LinearLayout> 
</layout> 

В приведенном выше атрибуте автоматической привязки создается для приложения: myViewModel, потому что есть сеттер с именем setMyViewModel.

+0

Спасибо! Часть борьбы, с которой я столкнулась, была из Android Studio, требующей, чтобы ее кеш недействителен, и проект несколько раз перестраивался, чтобы избавиться от файлов-посредников и сгенерировать новые файлы привязки. Трудно было понять, что случилось со всем красным. – Dave

+1

Где создается тип 'MyCustomViewBinding'? –

+0

MyCustomViewBinding генерируется через обработчик аннотации как часть структуры привязки данных. Файл xml (Dave использовал MyCustomView.xml, но он действительно имел в виду my_custom_view.xml, так как случай должен быть всем нижним регистром для файлов ресурсов) вызывает имя класса привязки по умолчанию для MyCustomViewBinding (с верблюжьей оболочкой, суффикс с привязкой). Вы также можете настроить имя класса Binding: http://developer.android.com/tools/data-binding/guide.html#custom_binding_class_names –

4

Во-первых, не делайте этого, если этот пользовательский вид уже является <include> в другом макете, таком как активность и т. Д. Вы просто получите исключение из-за неожиданного значения тега. Связывание данных уже выполнило привязку на нем, поэтому вы настроены.

Вы попробовали использовать onFinishInflate для запуска связывания? (Пример Котлин)

override fun onFinishInflate() { 
    super.onFinishInflate() 
    this.dataBinding = MyCustomBinding.bind(this) 
} 

Имейте в виду, что если вы используете связывание с вашей точки зрения, он не сможет быть создан программно, по крайней мере, это было бы очень запутанным, чтобы поддержать и даже если вы можете.

1

Following the solution presented by george графический редактор в андроид-студии больше не смог отобразить пользовательский вид. Причина в том, что ни один вид не на самом деле завышены в следующем коде:

public MyCustomView(...) { 
    ... 
    LayoutInflater inflater = (LayoutInflater) 
     context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
    mBinding = MyCustomViewBinding.inflate(inflater); 
} 

Я полагаю, что связывание обрабатывает инфляцию, однако графический редактор не нравится.

В моем конкретном случае использования я хотел связать одно поле, а не всю модель представления. Я придумал (kotlin входящий):

class LikeButton @JvmOverloads constructor(
     context: Context, 
     attrs: AttributeSet? = null, 
     defStyleAttr: Int = 0 
) : ConstraintLayout(context, attrs, defStyleAttr) { 

    val layout: ConstraintLayout = LayoutInflater.from(context).inflate(R.layout.like_button, this, true) as ConstraintLayout 

    var numberOfLikes: Int = 0 
     set(value) { 
      field = value 
      layout.number_of_likes_tv.text = numberOfLikes.toString() 
     } 
} 

Подобная кнопка состоит из изображения и текстового вида. Текстовый вид содержит количество понравившихся, которые я хочу установить через привязку данных.

Используя сеттера для numberOfLikes в качестве атрибута в следующем XML, связывание данных автоматически делает ассоциацию:

<views.LikeButton 
    android:id="@+id/like_btn" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    app:numberOfLikes="@{story.numberOfLikes}" /> 

Дальнейшее чтение: https://medium.com/google-developers/android-data-binding-custom-setters-55a25a7aea47

0

Основываясь на том, что вы делаете, я пытался do MyCustomBinding.bind(this), и это больше не работало для меня.Связывание уже имело место, но мы вместо этого находим его.

private MyCustomBinding binding; 

@Override 
protected void onAttachedToWindow() { 
    super.onAttachedToWindow(); 

    binding = DataBindingUtil.getBinding(this); //got the binding! 
    MyViewModelObject model = MyViewModelObject.get("myText"); 

    binding.setVariable(BR.myViewModel, model); 
} 

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

  • Нет связанных вопросов^_^