En-tête et pied de page de RecyclerView

peut-être cette question a-t-elle déjà été posée, mais je n'ai pas pu trouver de réponse ou de solution précise. J'ai commencé à utiliser le RecyclerView, et je l'ai implémenté en utilisant le Gestionnaire de lignes. Maintenant, je veux ajouter des éléments d'en-tête et de pied de page personnalisés, qui diffèrent du reste des éléments dans mon RecyclerView. L'en-tête et le pied de page ne doivent pas être collants, je veux qu'ils fassent défiler avec le reste des articles. Quelqu'un peut-il nous montrer un exemple ou simplement nous faire part de ses idées? Je vous en seront reconnaissants très bien. Thx

43
demandé sur Sandra 2014-10-27 13:53:37

10 réponses

dans votre adaptateur, ajouter cette classe:

private class VIEW_TYPES {
        public static final int Header = 1;
        public static final int Normal = 2;
        public static final int Footer = 3;
}

modifier ensuite la méthode suivante comme ceci:

@Override
public int getItemViewType(int position) {

    if(items.get(position).isHeader)
        return VIEW_TYPES.Header;
    else if(items.get(position).isFooter)
        return VIEW_TYPES.Footer;
    else
        return VIEW_TYPES.Normal;

}

maintenant dans la méthode onCreateViewHolder gonfler votre mise en page basée sur le type de vue::

@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {

    View rowView;

    switch (i)
    {
        case VIEW_TYPES.Normal:
            rowView=LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.normal, viewGroup, false);
            break;
        case VIEW_TYPES.Header:
            rowView=LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.header, viewGroup, false);
            break;
        case VIEW_TYPES.Footer:
            rowView=LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.footer, viewGroup, false);
            break;
        default:
            rowView=LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.normal, viewGroup, false);
            break;
    }
    return new ViewHolder (rowView);
}

j'Espère que cela peut aider.

45
répondu Bronx 2015-08-25 06:46:34

c'est très facile avec Itemdécorations et sans modifier aucun autre code:

recyclerView.addItemDecoration(new HeaderDecoration(this,
                               recyclerView,  R.layout.test_header));

réserver un peu d'espace pour le dessin, gonfler la mise en page que vous voulez dessiner et le dessiner dans l'espace réservé.

le code de la décoration:

public class HeaderDecoration extends RecyclerView.ItemDecoration {

    private View mLayout;

    public HeaderDecoration(final Context context, RecyclerView parent, @LayoutRes int resId) {
        // inflate and measure the layout
        mLayout = LayoutInflater.from(context).inflate(resId, parent, false);
        mLayout.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
                View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
    }


    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDraw(c, parent, state);
        // layout basically just gets drawn on the reserved space on top of the first view
        mLayout.layout(parent.getLeft(), 0, parent.getRight(), mLayout.getMeasuredHeight());
        for (int i = 0; i < parent.getChildCount(); i++) {
            View view = parent.getChildAt(i);
            if (parent.getChildAdapterPosition(view) == 0) {
                c.save();
                final int height = mLayout.getMeasuredHeight();
                final int top = view.getTop() - height;
                c.translate(0, top);
                mLayout.draw(c);
                c.restore();
                break;
            }
        }
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        if (parent.getChildAdapterPosition(view) == 0) {
            outRect.set(0, mLayout.getMeasuredHeight(), 0, 0);
        } else {
            outRect.setEmpty();
        }
    }
}
20
répondu David Medenjak 2015-11-01 01:33:12

vous pouvez utiliser cette bibliothèque GitHub] pour ajouter un en-tête ou un pied de page à votre RecyclerView de la manière la plus simple possible.

vous devez ajouter le HFRecyclerView bibliothèque dans votre projet ou vous pouvez également l'attraper de Gradle:

compile 'com.mikhaellopez:hfrecyclerview:1.0.0'

cette bibliothèque est basée sur un travail à @hister

C'est un résultat en image:

Preview

6
répondu lopez.mikhael 2017-05-23 11:47:21

cliquez sur ici . J'ai fait une extension de RecyclerView.Adaptateur. Facile à ajouter en-tête et pied de page.

class HFAdapter extends HFRecyclerViewAdapter<String, HFAdapter.DataViewHolder>{

    public HFAdapter(Context context) {
        super(context);
    }

    @Override
    public DataViewHolder onCreateDataItemViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.data_item, parent, false);
        return new DataViewHolder(v);
    }

    @Override
    public void onBindDataItemViewHolder(DataViewHolder holder, int position) {
        holder.itemTv.setText(getData().get(position));
    }

    class DataViewHolder extends RecyclerView.ViewHolder{
        TextView itemTv;
        public DataViewHolder(View itemView) {
            super(itemView);
            itemTv = (TextView)itemView.findViewById(R.id.itemTv);
        }
    }
}

//add header
View headerView = LayoutInflater.from(this).inflate(R.layout.header, recyclerView, false);
hfAdapter.setHeaderView(headerView);
//add footer
View footerView = LayoutInflater.from(this).inflate(R.layout.footer, recyclerView, false);
hfAdapter.setFooterView(footerView);

//remove
hfAdapter.removeHeader();
hfAdapter.removeFooter();
2
répondu F.Will 2015-09-07 01:31:49

pour les en-têtes linéaires sectionnées avec GridView articles dans Recyclerview: -

Check SectionedGridRecyclerViewAdapter

enter image description here

2
répondu Harpreet 2017-07-15 10:01:42

je suggère de ne pas personnaliser l'adaptateur rv.

gardez-le comme il est...dans votre disposition d'article de rv il suffit d'ajouter le pied de page avec la mise en page et de mettre la visisbilty disparu.

ensuite, lorsque vous atteignez le dernier article dans Adaptateur...rendre visible.

et quand vous essayez cela, assurez-vous d'ajouter ceci à votre adaptateur rv.

   @Override
    public void onBindViewHolder(final PersonViewHolder personViewHolder, int i) {
           if(i==List.size()) // Last item in recycle view
           personViewHolder.tv_footer.setVisibility(VISIBLE);// Make footer visible now }

 @Override
    public int getItemViewType(int position) {
        return position;
    }

Faire la même chose pour l'en-Tête. Ici i= = 0 / / premier élément de la liste

la solution la plus facile pour moi.

2
répondu Raktim Bhattacharya 2018-07-09 07:13:25

peut être GroupAdapter est ce que vous voulez.

spécialisé RecyclerView.Adaptateur qui présente les données d'une séquence de RecyclerView.Adaptateur. La séquence est statique, mais chaque adaptateur peut être présenté en zéro ou plusieurs points de vue. L'adaptateur enfant peut utiliser ViewType en toute sécurité. De plus, nous pouvons ajouter headerview ou addFooterView comme ListView.

1
répondu Xiong 2016-05-04 01:24:44

vous pouvez utiliser la bibliothèque SectionedRecyclerViewAdapter , il a le concept de" Sections", où quelle Section a un en-tête, pied de page et le contenu (liste des éléments). Dans votre cas, vous pourriez n'avoir besoin que D'une Section, mais vous pouvez en avoir plusieurs:

enter image description here

1) Créer une classe de section personnalisée:

class MySection extends StatelessSection {

    List<String> myList = Arrays.asList(new String[] {"Item1", "Item2", "Item3" });

    public MySection() {
        // call constructor with layout resources for this Section header, footer and items 
        super(R.layout.section_header, R.layout.section_footer,  R.layout.section_item);
    }

    @Override
    public int getContentItemsTotal() {
        return myList.size(); // number of items of this section
    }

    @Override
    public RecyclerView.ViewHolder getItemViewHolder(View view) {
        // return a custom instance of ViewHolder for the items of this section
        return new MyItemViewHolder(view);
    }

    @Override
    public void onBindItemViewHolder(RecyclerView.ViewHolder holder, int position) {
        MyItemViewHolder itemHolder = (MyItemViewHolder) holder;

        // bind your view here
        itemHolder.tvItem.setText(myList.get(position));
    }
}

2) Créer un afficheur personnalisé pour les articles:

class MyItemViewHolder extends RecyclerView.ViewHolder {

    private final TextView tvItem;

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

        tvItem = (TextView) itemView.findViewById(R.id.tvItem);
    }
}

3) configurer votre ReclyclerView avec la Sectionrecyclerviewadapter

// Create an instance of SectionedRecyclerViewAdapter 
SectionedRecyclerViewAdapter sectionAdapter = new SectionedRecyclerViewAdapter();

MySection mySection = new MySection();

// Add your Sections
sectionAdapter.addSection(mySection);

// Set up your RecyclerView with the SectionedRecyclerViewAdapter
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerview);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setAdapter(sectionAdapter);
1
répondu Gustavo 2016-06-14 15:36:42

voici quelques en-tête Decoration Pour recyclerview

avec une modification partielle vous pouvez changer en pied de page

public class HeaderItemDecoration extends RecyclerView.ItemDecoration {

private View customView;

public HeaderItemDecoration(View view) {
    this.customView = view;
}

@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
    super.onDraw(c, parent, state);
    customView.layout(parent.getLeft(), 0, parent.getRight(), customView.getMeasuredHeight());
    for (int i = 0; i < parent.getChildCount(); i++) {
        View view = parent.getChildAt(i);
        if (parent.getChildAdapterPosition(view) == 0) {
            c.save();
            final int height = customView.getMeasuredHeight();
            final int top = view.getTop() - height;
            c.translate(0, top);
            customView.draw(c);
            c.restore();
            break;
        }
    }
}

@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
    if (parent.getChildAdapterPosition(view) == 0) {
        customView.measure(View.MeasureSpec.makeMeasureSpec(parent.getMeasuredWidth(), View.MeasureSpec.AT_MOST),
                View.MeasureSpec.makeMeasureSpec(parent.getMeasuredHeight(), View.MeasureSpec.AT_MOST));
        outRect.set(0, customView.getMeasuredHeight(), 0, 0);
    } else {
        outRect.setEmpty();
    }
}
}      
1
répondu Trunks ssj 2016-10-12 17:54:11

une autre façon serait d'envelopper en-tête et reyclerview dans un coordinatorlayout :

<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.design.widget.AppBarLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:elevation="0dp">

    <View
        android:id="@+id/header"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_scrollFlags="scroll" />

</android.support.design.widget.AppBarLayout>

<android.support.v7.widget.RecyclerView
    android:id="@+id/list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior" />

1
répondu lenhuy2106 2018-07-16 13:45:13