Recherche…


GridLayoutManager avec comptage dynamique

Lors de la création d'une recyclerview avec un gestionnaire de disposition gridlayout, vous devez spécifier le comptage de port dans le constructeur. Le nombre de plages correspond au nombre de colonnes. Ceci est assez encombrant et ne prend pas en compte les grandes tailles d'écran ou l'orientation de l'écran. Une approche consiste à créer plusieurs dispositions pour les différentes tailles d'écran. Une autre approche plus dynamique peut être vue ci-dessous.

Tout d'abord, nous créons une classe RecyclerView personnalisée comme suit:

public class AutofitRecyclerView extends RecyclerView {
    private GridLayoutManager manager;
    private int columnWidth = -1;

    public AutofitRecyclerView(Context context) {
        super(context);
        init(context, null);
    }

    public AutofitRecyclerView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    public AutofitRecyclerView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        if (attrs != null) {
            int[] attrsArray = {
                    android.R.attr.columnWidth
            };
            TypedArray array = context.obtainStyledAttributes(attrs, attrsArray);
            columnWidth = array.getDimensionPixelSize(0, -1);
            array.recycle();
        }

        manager = new GridLayoutManager(getContext(), 1);
        setLayoutManager(manager);
    }

    @Override
    protected void onMeasure(int widthSpec, int heightSpec) {
        super.onMeasure(widthSpec, heightSpec);
        if (columnWidth > 0) {
            int spanCount = Math.max(1, getMeasuredWidth() / columnWidth);
            manager.setSpanCount(spanCount);
        }
    }
}

Cette classe détermine le nombre de colonnes pouvant être intégrées à la recyclerview. Pour l'utiliser, vous devrez le mettre dans votre layout.xml comme suit:

<?xml version="1.0" encoding="utf-8"?>
<com.path.to.your.class.autofitRecyclerView.AutofitRecyclerView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/auto_fit_recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:columnWidth="200dp"
    android:clipToPadding="false"
    />

Notez que nous utilisons l'attribut columnWidth. Recyclerview en aura besoin pour déterminer le nombre de colonnes pouvant être insérées dans l'espace disponible.

Dans votre activité / fragment, vous obtenez une référence à la recylerview et définissez-y un adaptateur (ainsi que les décorations ou animations que vous souhaitez ajouter). NE DÉFINISSEZ PAS DE GESTIONNAIRE DE MISE EN PAGE

RecyclerView recyclerView = (RecyclerView) findViewById(R.id.auto_fit_recycler_view);
recyclerView.setAdapter(new MyAdapter());

(où MyAdapter est votre classe d'adaptateur)

Vous avez maintenant une liste de recyclage qui ajustera le compte (c.-à-d. Les colonnes) en fonction de la taille de l'écran. En dernier lieu, vous voudrez peut-être centrer les colonnes dans la recyclerview (par défaut, elles sont alignées sur layout_start). Vous pouvez le faire en modifiant un peu la classe AutofitRecyclerView. Commencez par créer une classe interne dans la recyclerview. Ce sera une classe qui s'étend de GridLayoutManager. Il ajoutera suffisamment de remplissage à gauche et à droite pour centrer les lignes:

public class AutofitRecyclerView extends RecyclerView {

    // etc see above

    private class CenteredGridLayoutManager extends GridLayoutManager {

        public CenteredGridLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
            super(context, attrs, defStyleAttr, defStyleRes);
        }

        public CenteredGridLayoutManager(Context context, int spanCount) {
            super(context, spanCount);
        }

        public CenteredGridLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout) {
            super(context, spanCount, orientation, reverseLayout);
        }

        @Override
        public int getPaddingLeft() {
            final int totalItemWidth = columnWidth * getSpanCount();
            if (totalItemWidth >= AutofitRecyclerView.this.getMeasuredWidth()) {
                return super.getPaddingLeft(); // do nothing
            } else {
                return Math.round((AutofitRecyclerView.this.getMeasuredWidth() / (1f + getSpanCount())) - (totalItemWidth / (1f + getSpanCount())));
            }
        }

        @Override
        public int getPaddingRight() {
            return getPaddingLeft();
        }
    }
}

Ensuite, lorsque vous définissez le LayoutManager dans AutofitRecyclerView, utilisez le CenteredGridLayoutManager comme suit:

private void init(Context context, AttributeSet attrs) {
    if (attrs != null) {
        int[] attrsArray = {
                android.R.attr.columnWidth
        };
        TypedArray array = context.obtainStyledAttributes(attrs, attrsArray);
        columnWidth = array.getDimensionPixelSize(0, -1);
        array.recycle();
    }

    manager = new CenteredGridLayoutManager(getContext(), 1);
    setLayoutManager(manager);
}

Et c'est tout! Vous disposez d'un compte dynamique, centré sur la grille, basé sur le centre de grille.

Sources:

Ajout de la vue d'en-tête à recyclerview avec le gestionnaire gridlayout

Pour ajouter un en-tête à une recyclerview avec un gridlayout, il faut d'abord indiquer à l'adaptateur que la vue d'en-tête est la première position, plutôt que la cellule standard utilisée pour le contenu. Ensuite, le gestionnaire de disposition doit être informé que la première position doit avoir une portée égale au nombre * span de la liste entière. *

Prenez une classe RecyclerView.Adapter régulière et configurez-la comme suit:

public class HeaderAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private static final int ITEM_VIEW_TYPE_HEADER = 0;
    private static final int ITEM_VIEW_TYPE_ITEM = 1;

    private List<YourModel> mModelList;

    public HeaderAdapter (List<YourModel> modelList) {
        mModelList = modelList;
    }

    public boolean isHeader(int position) {
        return position == 0;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());

        if (viewType == ITEM_VIEW_TYPE_HEADER) {
            View headerView = inflater.inflate(R.layout.header, parent, false);
            return new HeaderHolder(headerView);
        }

        View cellView = inflater.inflate(R.layout.gridcell, parent, false);
        return new ModelHolder(cellView);
    }

    @Override
    public int getItemViewType(int position) {
        return isHeader(position) ? ITEM_VIEW_TYPE_HEADER : ITEM_VIEW_TYPE_ITEM;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder h, int position) {
        if (isHeader(position)) {
            return;
        }

        final YourModel model = mModelList.get(position -1 ); // Subtract 1 for header

        ModelHolder holder = (ModelHolder) h;
        // populate your holder with data from your model as usual
    }

    @Override
    public int getItemCount() {
        return _categories.size() + 1; // add one for the header
    }
}

Puis dans l'activité / fragment:

final HeaderAdapter adapter = new HeaderAdapter (mModelList);
final GridLayoutManager manager = new GridLayoutManager(); 
manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
    @Override
    public int getSpanSize(int position) {
        return adapter.isHeader(position) ? manager.getSpanCount() : 1;
    }
});
mRecyclerView.setLayoutManager(manager);
mRecyclerView.setAdapter(adapter);

La même approche peut être utilisée en ajoutant un pied de page en plus ou au lieu d'un en-tête.

Source: blog Square Chiu-Ki Chan

Liste simple avec LinearLayoutManager

Cet exemple ajoute une liste des lieux avec l' image et le nom en utilisant une ArrayList de la coutume Place des objets comme jeu de données.

Disposition de l'activité

La disposition de l'activité / du fragment ou de l'emplacement où RecyclerView est utilisé doit uniquement contenir RecyclerView. Il n'y a pas de ScrollView ou une disposition spécifique nécessaire.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/my_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>

Définir le modèle de données

Vous pouvez utiliser n'importe quel type de données de classe ou primitive en tant que modèle, comme int , String , float[] ou CustomObject . RecyclerView fera référence à une List de ces objets / primitives.

Lorsqu'un élément de liste fait référence à différents types de données tels que du texte, des nombres, des images (comme dans cet exemple avec des espaces), il est souvent utile d'utiliser un objet personnalisé.

public class Place {
    // these fields will be shown in a list item
    private Bitmap image;
    private String name;

    // typical constructor
    public Place(Bitmap image, String name) {
        this.image = image;
        this.name = name;
    }

    // getters
    public Bitmap getImage() {
        return image;
    }
    public String getName() {
        return name;
    } 
}

Mise en page des éléments de la liste

Vous devez spécifier un fichier de présentation xml qui sera utilisé pour chaque élément de la liste. Dans cet exemple, un ImageView est utilisé pour l'image et un TextView pour le nom. Le LinearLayout positionne le ImageView à gauche et le TextView droit à l'image.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:orientation="horizontal"
    android:padding="8dp">

    <ImageView
        android:id="@+id/image"
        android:layout_width="36dp"
        android:layout_height="36dp"
        android:layout_marginEnd="8dp"
        android:layout_marginRight="8dp" />

    <TextView
        android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

Créez un adaptateur RecyclerView et ViewHolder

Ensuite, vous devez hériter de RecyclerView.Adapter et du RecyclerView.ViewHolder . Une structure de classe habituelle serait:

public class PlaceListAdapter extends RecyclerView.Adapter<PlaceListAdapter.ViewHolder> {
    // ...

    public class ViewHolder extends RecyclerView.ViewHolder {
        // ...
    }
}

Tout d'abord, nous implémentons le ViewHolder . Il hérite uniquement du constructeur par défaut et enregistre les vues nécessaires dans certains champs:

public class ViewHolder extends RecyclerView.ViewHolder {
    private ImageView imageView;
    private TextView nameView;

    public ViewHolder(View itemView) {
        super(itemView);

        imageView = (ImageView) itemView.findViewById(R.id.image);
        nameView = (TextView) itemView.findViewById(R.id.name);
    }
}

Le constructeur de l'adaptateur définit le jeu de données utilisé:

public class PlaceListAdapter extends RecyclerView.Adapter<PlaceListAdapter.ViewHolder> {
    private List<Place> mPlaces;

    public PlaceListAdapter(List<Place> contacts) {
        mPlaces = contacts;
    }

    // ...
}

Pour utiliser notre disposition d'élément de liste personnalisée, nous onCreateViewHolder(...) la méthode onCreateViewHolder(...) . Dans cet exemple, le fichier de disposition est appelé place_list_item.xml .

public class PlaceListAdapter extends RecyclerView.Adapter<PlaceListAdapter.ViewHolder> {
    // ...

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(
                R.layout.place_list_item,
                parent,
                false
        );
        return new ViewHolder(view);
    }

    // ...
}

Dans le onBindViewHolder(...) , nous définissons réellement le contenu des vues. Nous obtenons le modèle utilisé en le trouvant dans la List à la position donnée, puis nous définissons l'image et le nom sur les ViewHolder du ViewHolder .

public class PlaceListAdapter extends RecyclerView.Adapter<PlaceListAdapter.ViewHolder> {
    // ...

    @Override
    public void onBindViewHolder(PlaceListAdapter.ViewHolder viewHolder, int position) {
        Place place = mPlaces.get(position);

        viewHolder.nameView.setText(place.getName());
        viewHolder.imageView.setImageBitmap(place.getImage());
    }

    // ...
}

Nous devons également mettre en œuvre getItemCount() , qui renvoie simplement la List taille de.

public class PlaceListAdapter extends RecyclerView.Adapter<PlaceListAdapter.ViewHolder> {
    // ...

    @Override
    public int getItemCount() {
        return mPlaces.size();
    }

    // ...
}

(Générer des données aléatoires)

Pour cet exemple, nous allons générer des endroits aléatoires.

@Override
protected void onCreate(Bundle savedInstanceState) {
    // ...

    List<Place> places = randomPlaces(5);

    // ...
}

private List<Place> randomPlaces(int amount) {
    List<Place> places = new ArrayList<>();
    for (int i = 0; i < amount; i++) {
        places.add(new Place(
                BitmapFactory.decodeResource(getResources(), Math.random() > 0.5 ?
                        R.drawable.ic_account_grey600_36dp :
                        R.drawable.ic_android_grey600_36dp
                ),
                "Place #" + (int) (Math.random() * 1000)
        ));
    }
    return places;
}

Connectez le RecyclerView à la PlaceListAdapter et à l'ensemble de données

Connecter un RecyclerView à un adaptateur est très simple. Vous devez définir LinearLayoutManager comme gestionnaire de disposition pour obtenir la disposition de liste.

@Override
protected void onCreate(Bundle savedInstanceState) {
    // ...

    RecyclerView recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
    recyclerView.setAdapter(new PlaceListAdapter(places));
    recyclerView.setLayoutManager(new LinearLayoutManager(this));
}

Terminé!

StaggeredGridLayoutManager

  1. Créez votre RecyclerView dans votre fichier XML de mise en page:
<android.support.v7.widget.RecyclerView
            android:id="@+id/recycleView"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
  1. Créez votre classe de modèle pour conserver vos données:

         public class PintrestItem {
         String url;
         public PintrestItem(String url,String name){
             this.url=url;
             this.name=name;
         }
         public String getUrl() {
             return url;
         }
     
        public String getName(){
            return name;
        }
         String name;
     }  
    
  2. Créez un fichier de disposition pour contenir les éléments RecyclerView:

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:scaleType="centerCrop"
        android:id="@+id/imageView"/>
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:id="@+id/name"
            android:layout_gravity="center"
            android:textColor="@android:color/white"/>
    
  3. Créez la classe d'adaptateur pour RecyclerView:

     public class PintrestAdapter extends  RecyclerView.Adapter<PintrestAdapter.PintrestViewHolder>{
        private ArrayList<PintrestItem>images;
        Picasso picasso;
        Context context;
        public PintrestAdapter(ArrayList<PintrestItem>images,Context context){
            this.images=images;
            picasso=Picasso.with(context);
            this.context=context;
    
        }
    
        @Override
        public PintrestViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.pintrest_layout_item,parent,false);
            return new PintrestViewHolder(view);
        }
    
        @Override
        public void onBindViewHolder(PintrestViewHolder holder, int position) {
              picasso.load(images.get(position).getUrl()).into(holder.imageView);
              holder.tv.setText(images.get(position).getName());
        }
    
        @Override
        public int getItemCount() {
            return images.size();
        }
    
        public class PintrestViewHolder extends RecyclerView.ViewHolder{
            ImageView imageView;
            TextView tv;
            public PintrestViewHolder(View itemView) {
                super(itemView);
                imageView=(ImageView)itemView.findViewById(R.id.imageView);
                tv=(TextView)itemView.findViewById(R.id.name);
                
            }
        }
    }
    
  1. Instanciez le RecyclerView dans votre activité ou fragment:

    RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recyclerView);
    //Create the instance of StaggeredGridLayoutManager with 2 rows i.e the span count and provide the orientation
    StaggeredGridLayoutManager layoutManager=new new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
    recyclerView.setLayoutManager(layoutManager);
    // Create Dummy Data and Add to your List<PintrestItem>
    List<PintrestItem>items=new ArrayList<PintrestItem>
    items.add(new PintrestItem("url of image you want to show","imagename"));
    items.add(new PintrestItem("url of image you want to show","imagename"));
    items.add(new PintrestItem("url of image you want to show","imagename"));
    recyclerView.setAdapter(new PintrestAdapter(items,getContext() );
    

N'oubliez pas d'ajouter la dépendance Picasso dans votre fichier build.gradle:

compile 'com.squareup.picasso:picasso:2.5.2'


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow