web-dev-qa-db-fra.com

Comment utiliser layout_weight dans la vue d'élément RecyclerView ou ListView pour que des éléments de même hauteur remplissent l'espace disponible à l'écran?

J'ai actuellement besoin d'utiliser un RecyclerView (ou ListView) mais le nombre d'éléments est fixé à 4. Je veux que ces 4 éléments utilisent également l'espace disponible à l'écran. RecyclerView est la seule vue à l'écran, à l'exception de la barre d'applications. C'est à dire. RecyclerView a layout_height défini sur match_parent. J'ai choisi RecyclerView car les éléments ont des dispositions différentes en fonction de l'état du modèle.

Je ne l'ai pas encore consultée, mais je suis sûr que je peux définir la hauteur par programmation en code Java pour chaque élément. Mais cela semble inélégant si je peux le spécifier dans le XML. Des questions similaires à ma droite, au moment où j'écris ceci, répondent à cette question.

J'ai essayé ce qui suit dans le fichier item_layout.xml, de la façon dont layout_weight est utilisé dans d'autres scénarios:

<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    Android:orientation="vertical"
    Android:layout_width="match_parent"
    Android:layout_weight="1"
    Android:layout_height="0dp">...</LinearLayout>

Mais alors rien ne s'affiche à l'écran. 

Ce que j'aimerais savoir, c'est: puis-je le faire dans le XML de présentation avec layout_weight ou quelque chose d'autre? Si c'est le cas, comment?

17
ageektrapped

Comme le API reference dit, layout_weight est un attribut de LinearLayout, donc ne peut pas être utilisé avec d'autres ViewGroups, comme par exemple RecyclerView et ListView. Au lieu de cela, vous devez définir la hauteur de l'élément par programme.

Puisque vous semblez préoccupé par la propreté de votre code, je pense que c'est une solution plutôt élégante au cas où vous utiliseriez une RecyclerView:

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater
            .from(parent.getContext())
            .inflate(R.layout.item_list, null);

    int height = parent.getMeasuredHeight() / 4;
    int width = parent.getMeasuredWidth();

    view.setLayoutParams(new RecyclerView.LayoutParams(width, height));

    return new ViewHolder(view);
}
24
josemigallas

Essayez ceci, travaillez pour moi

int weight = 3; //number of parts in the recycler view. 

@Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View rowView = LayoutInflater.from(parent.getContext()).inflate(R.layout.row,parent,false);
        rowView.getLayoutParams().height = parent.getHeight() / weight;
        return new ViewHolder(rowView);
    }
8
Heriberto Rivera

J'ai rencontré ce problème, car j'avais un RecyclerView avec des entrées variables. Mon RecyclerView horizontal devait s'adapter à au moins trois vues sans déborder. J'ai donc conçu mes vues pour qu'elles soient redimensionnées à l'exécution afin de s'adapter à l'écran.

class MyRecyclerView extends RecyclerView.Adapter<ViewHolder> {

    int mViewWidth;

    public MyRecyclerView(Context context) {
      mViewWidth = defineViewWidth(context);
    }

    private int defineViewWidth(Context context) {
      int definedWidth = (int) context.getResources().getDimension(R.dimen.default_view_width);
      DisplayMetrics dm = new DisplayMetrics();
      WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
      wm.getDefaultDisplay().getMetrics(dm);
      if (definedWidth * 3 > dm.widthPixels) {
        return dm.widthPixels / 3;
      }
      return definedWidth;
    }

    ...

}

Une fois que vous avez défini une largeur, vous devez définir la largeur de la vue:

@Override
public ViewHolder onCreateViewHolder(ViewHolder holder, int position) {
    View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.row, parent, false);
    ViewGroup.LayoutParams params = v.getLayoutParams();
    params.width = mViewWidth;
    v.setLayoutParams(params);
    return new ViewHolder(v);
}

Vous pouvez facilement modifier cela pour vous assurer que votre RecyclerView s'adapte à autant d'éléments (verticalement ou horizontalement) que vous avez besoin.

1
loadedion

Par ItemDecoration:

@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
    super.getItemOffsets(outRect, view, parent, state);
    int itemWidth = parent.getMeasuredWidth() / 7;
    view.getLayoutParams().width = itemWidth;
}
0
Shawn Racine