imagen - cambiar nombre activity android
enlace de datos de Android con una vista personalizada (5)
La guía de enlace de datos de Android trata sobre los valores de enlace dentro de una actividad o fragmento, pero ¿hay alguna manera de realizar el enlace de datos con una vista personalizada?
Me gustaría hacer algo como:
<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>
con 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>
Aunque parece posible hacerlo estableciendo atributos personalizados en la vista personalizada, esto se volvería engorroso rápidamente si hay muchos valores para vincular.
¿Hay una buena manera de lograr lo que estoy tratando de hacer?
Aquí ya hay algunas buenas respuestas, pero quería ofrecer lo que creo que es lo más simple.
Cree su control personalizado con las etiquetas de diseño que lo rodean, al igual que cualquier otro diseño. Vea la siguiente barra de herramientas, por ejemplo. esto se usa en cada una de las clases de actividades
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable name="YACustomPrefs" type="com.appstudio35.yourappstudio.models.YACustomPreference" />
</data>
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/YATheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/colorPrimary"
app:popupTheme="@style/YATheme.PopupOverlay"/>
</android.support.design.widget.AppBarLayout>
</android.support.design.widget.CoordinatorLayout>
Ahora este diseño personalizado es un elemento secundario de cada actividad. Simplemente lo trata como tal en la configuración de enlace onCreate.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
binding.yaCustomPrefs = YACustomPreference.getInstance(this)
binding.toolbarMain?.yaCustomPrefs = YACustomPreference.getInstance(this)
binding.navHeader?.yaCustomPrefs = YACustomPreference.getInstance(this)
binding.activity = this
binding.iBindingRecyclerView = this
binding.navHeader?.activity = this
//local pointer for notify txt badge
txtNotificationCountBadge = txtNotificationCount
//setup notify if returned from background so we can refresh the drawer items
AppLifeCycleTracker.getInstance().addAppToForegroundListener(this)
setupFilterableCategories()
setupNavigationDrawer()
}
Observe que establezco el contenido de los niños al mismo tiempo que hago el padre y todo se hace a través del acceso de notación de puntos. Siempre que los archivos estén rodeados con etiquetas de diseño y los nombre, es simple de hacer.
Ahora bien, si la clase personalizada tiene su propio índice de inflación asociado, entonces puede hacer su propio enlace fácilmente en onCreate o constructor, pero usted obtiene la imagen. Si tiene su propia clase, simplemente agregue lo siguiente en el constructor para que coincida con su clase de enlace denominada. Sigue la convención del nombre del archivo de diseño pascal en caja, por lo que es fácil de encontrar y autocompletar.
LayoutInflater inflater = (LayoutInflater)
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mBinding = NameOfCustomControlBinding.inflate(inflater);
Espero que ayude.
En función de lo que está haciendo, intenté hacer MyCustomBinding.bind(this)
y eso ya no funcionó para mí. La vinculación ya se realizó, pero lo que hacemos es encontrarla.
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);
}
En primer lugar, no haga esto si esta vista personalizada ya se está <include>
en otro diseño, como actividad, etc. Obtendrá una excepción sobre el valor inesperado de la etiqueta. El enlace de datos ya ejecutó el enlace, por lo que está configurado.
¿ onFinishInflate
utilizar en onFinishInflate
para ejecutar el enlace? (Ejemplo de Kotlin)
override fun onFinishInflate() {
super.onFinishInflate()
this.dataBinding = MyCustomBinding.bind(this)
}
Tenga en cuenta que si utiliza el enlace en su vista, no podrá crearse mediante programación, al menos sería complicado para ambos, incluso si es posible.
En su vista personalizada, infle el diseño como lo haría normalmente y proporcione un colocador para el atributo que desea establecer:
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);
}
Luego en el diseño lo usas en:
<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>
En lo anterior, se crea un atributo de enlace automático para la aplicación: myViewModel porque hay un setter con el nombre setMyViewModel.
Siguiendo la solución presentada por george, el editor gráfico en android studio ya no podía renderizar la vista personalizada. La razón es que ninguna vista está realmente inflada en el siguiente código:
public MyCustomView(...) {
...
LayoutInflater inflater = (LayoutInflater)
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mBinding = MyCustomViewBinding.inflate(inflater);
}
Supongo que el enlace maneja la inflación, sin embargo, al editor gráfico no le gustó.
En mi caso de uso específico, quería vincular un único campo y no un modelo de vista completo. Se me ocurrió (kotlin entrante):
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()
}
}
El botón Me gusta consiste en una imagen y una vista de texto. La vista de texto contiene el número de me gusta, que quiero configurar a través de enlace de datos.
Al utilizar setter para numberOfLikes como atributo en el siguiente xml, el enlace de datos hace automáticamente la asociación:
<views.LikeButton
android:id="@+id/like_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:numberOfLikes="@{story.numberOfLikes}" />
Lectura adicional: https://medium.com/google-developers/android-data-binding-custom-setters-55a25a7aea47