C'est ma première tentative de liaison de données avec un RecyclerView mais pas ma première utilisation de RecyclerView lui-même.
Pour une raison quelconque, aucune des méthodes d'adaptateur n'est appelée - pas même getItemCount (). Cela pourrait être un problème stupide avec mon RecyclerView et rien à voir avec la liaison de données, mais je ne vois rien de mal.
View rootview = inflater.inflate(R.layout.fragment_profile_first, container, false);
// Initialize recycler view
RecyclerView badgesRV = (RecyclerView) rootview.findViewById(R.id.badgesRV);
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
llm.setOrientation(LinearLayoutManager.HORIZONTAL);
badgesRV.setLayoutManager(llm);
BadgeAdapter badgeAdapter = new BadgeAdapter(profileObject.badgesEntity.badges);
badgesRV.setAdapter(badgeAdapter);
Adaptateur:
public class BadgeAdapter extends RecyclerView.Adapter<BadgeAdapter.BadgeBindingHolder>{
private static final int MAX_BADGES_TO_DISPLAY = 5;
private BadgeObject[] badges;
public BadgeAdapter(BadgeObject[] badges){
this.badges = badges;
}
@Override
public BadgeBindingHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.profile_badge_row, parent, false);
BadgeBindingHolder holder = new BadgeBindingHolder(v);
return holder;
}
@Override
public void onBindViewHolder(BadgeBindingHolder holder, int position) {
final BadgeObject badgeObject = badges[position];
holder.getBinding().setVariable(BR.badge, badgeObject);
holder.getBinding().executePendingBindings();
}
@Override
public int getItemCount() {
Log.d(TAG, "item count = " + Math.min(MAX_BADGES_TO_DISPLAY, badges.length));
return Math.min(MAX_BADGES_TO_DISPLAY, badges.length);
}
public class BadgeBindingHolder extends RecyclerView.ViewHolder{
private ViewDataBinding binding;
public BadgeBindingHolder(View rowView) {
super(rowView);
binding = DataBindingUtil.bind(rowView);
}
public ViewDataBinding getBinding() {
return binding;
}
}
}
profile_badge_row.xml
<layout xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto">
<data>
<variable name="badge" type="parseJsonEntities.requestObjects.BadgeObject"/>
</data>
<LinearLayout
Android:orientation="vertical" Android:layout_width="match_parent"
Android:layout_height="match_parent">
<ImageView
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:src="@{badge.badgeImage}"/>
</LinearLayout>
J'ai vérifié et il y a certainement des données là-bas. Qu'est-ce que j'ai raté?
=====================
Mettre à jour:
D'après ce que je peux dire, RecyclerView ne fonctionne tout simplement pas dans une disposition de liaison de données. J'ai créé une mise en page séparée avec juste mon VR et cela a parfaitement fonctionné. Dès que je l'ai inclus avec ma mise en page principale, il a cessé de fonctionner.
Je ne sais pas s'il s'agit d'un bogue ou d'une fonctionnalité.
Donc, j'ai pensé que peut-être que si j'en fais une vue personnalisée, cela fonctionnera et ça marche. Mon problème est que je ne sais pas comment passer une valeur dans ma vue personnalisée.
J'ai regardé ici mais je n'ai pas pu comprendre exactement ce qu'il voulait dire. Ceci est mon code dans la vue personnalisée.
LayoutInflater inflater = (LayoutInflater)
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.profile_badges_layout, this, true);
ProfileBadgesLayoutBinding binding = ProfileBadgesLayoutBinding.inflate(inflater);
RecyclerView badgesRV = (RecyclerView) view.findViewById(R.id.badgesRV);
LinearLayoutManager llm = new LinearLayoutManager(context);
llm.setOrientation(LinearLayoutManager.HORIZONTAL);
badgesRV.setLayoutManager(llm);
BadgeAdapter badgeAdapter = new BadgeAdapter(null);
badgesRV.setAdapter(badgeAdapter);
Cela donne un message indiquant que ProfileBadgesLayoutBinding est introuvable.
Dans votre onCreateViewHolder
:
@Override
public BadgeBindingHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ProfileBadgeRowBinding binding = DataBindingUtil.inflate(inflater, R.layout.profile_badge_row, parent, false);
BadgeBindingHolder holder = new BadgeBindingHolder(binding.getRoot(), binding);
return holder;
}
Et ajoutez la reliure dans votre vue d'article
public class BadgeBindingHolder extends RecyclerView.ViewHolder{
private ProfileBadgeRowBinding binding;
public BadgeBindingHolder(View rowView, ProfileBadgeRowBinding binding) {
super(rowView);
this.binding = binding;
}
...
}
Et dans bindToViewHolder
définissez la variable
@Override
public void bindToViewHolder(RecyclerView.ViewHolder viewHolder) {
ProfileBadgeRowBinding binding = ((BadgeBindingHolder) viewHolder).binding;
binding.setVariable(BR.badge, badge);
binding.executePendingBindings(); // This line is important, it will force to load the variable in a custom view
}
Si vous souhaitez accéder à une vue, ajoutez un identifiant à une vue dans votre xml
.
<layout xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto">
<data>
<variable name="badge" type="parseJsonEntities.requestObjects.BadgeObject"/>
</data>
<LinearLayout
Android:orientation="vertical" Android:layout_width="match_parent"
Android:layout_height="match_parent">
<ImageView
Android:id="@+id/image"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content" />
</LinearLayout>
</layout>
Et puis vous pouvez accéder aux identifiants dans votre bindToViewHolder
@Override
public void bindToViewHolder(RecyclerView.ViewHolder viewHolder) {
ProfileBadgeRowBinding binding = ((BadgeBindingHolder) viewHolder).binding;
binding.setVariable(BR.badge, badge);
binding.executePendingBindings();
binding.image.setImage(...);
}
En savoir plus sur les vues personnalisées https://developer.Android.com/topic/libraries/data-binding/index.html#dynamic_variables
Il est beaucoup plus facile de le faire aujourd'hui, suivez cet exemple:
public class LanguageRecyclerAdapter extends RecyclerView.Adapter<LanguageRecyclerAdapter.LanguageViewHolder> {
private List<Language> languages;
public class LanguageViewHolder extends RecyclerView.ViewHolder {
final LanguageSetItemBinding item;
public void bind(final Language language) {
item.setLanguage(language.getName());
item.setFlag(language.getFlagRes());
item.getRoot().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//do somthing if you need
}
});
item.executePendingBindings();
}
public LanguageViewHolder(LanguageSetItemBinding itemView) {
super(itemView.getRoot());
item =itemView;
}
}
public LanguageRecyclerAdapter(List<Language> languages) {
this.languages = languages;
}
public void onBindViewHolder(LanguageViewHolder holder, int position) {
Language item = languages.get(position);
holder.bind(item);
}
public LanguageViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
LanguageSetItemBinding item = LanguageSetItemBinding.inflate(layoutInflater, parent,false);
return new LanguageViewHolder(item);
}
@Override
public int getItemCount() {
return languages.size();
}
@Override
public int getItemViewType(int position) {
return super.getItemViewType(position);
}
}
le LanguageSetItemBinding
xml ressemble à ceci, il a à l'intérieur un TextView
et ImageView
:
<?xml version="1.0" encoding="utf-8"?>
<layout >
<data>
<variable name="language" type="String" />
<variable name="flag" type="int" />
</data>
<Android.widget.LinearLayout
xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto"
Android:layout_width="166dp"
Android:layout_height="166dp"
Android:background="@color/colorWhite"
Android:orientation="vertical"
Android:layout_margin="20dp"
Android:gravity="center">
<TextView
Android:layout_marginTop="20dp"
Android:gravity="center"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:textSize="20sp"
Android:text="@{language}"
Android:textColor="@color/colorBlack"
Android:textAlignment="center"/>
<ImageView
Android:textColor="?attr/errorColor"
Android:layout_width="wrap_content"
Android:layout_height="match_parent"
Android:src="@{context.getDrawable(flag)}"
Android:gravity="center"
Android:paddingTop="3dp"/>
</Android.widget.LinearLayout>
</layout>
J'ai une activité avec une vue de recyclage à l'intérieur, et dans l'activité OmCreateView j'ai attaché ce recycleur à l'adaptateur que j'ai créé ci-dessus:
final ArrayList<Language> lang = new ArrayList(languageList.values());
final LanguageRecyclerAdapter adapter = new LanguageRecyclerAdapter(lang);
mBinding.languageRecyclerView.setAdapter(adapter);