Expandable list with RecyclerView?

后端 未结 6 2034
天涯浪人
天涯浪人 2020-11-27 10:45

It\'s possible to use expandable list items with new RecyclerView? Like ExpandableListView?

相关标签:
6条回答
  • 2020-11-27 11:26

    This is the sample code for what is mentioned by @TonicArtos to add and remove Items and to animate it while doing, this is taken from RecyclerView Animations and GitHub sample

    1) Add Listener inside your onCreateViewHolder() to register for onClick

    2) Create your custom OnClickListener inside your Adapter

    private View.OnClickListener mItemListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            TextView tv = (TextView) v.findViewById(R.id.tvItems);
            String selected = tv.getText().toString();
            boolean checked = itemsList.get(recyclerView.getChildAdapterPosition(v)).isChecked();
    
            switch (selected){
                case "Item1":
                    if(checked){
                        deleteItem(v);
                        itemsList.get(recyclerView.getChildAdapterPosition(v)).setChecked(false);
                    }else {
                        addItem(v);
                        itemsList.get(recyclerView.getChildAdapterPosition(v)).setChecked(true);
                    }
                    break;
                case "Item2":
                    if(checked){
                        deleteItem(v);
                        itemsList.get(recyclerView.getChildAdapterPosition(v)).setChecked(false);
                    }else {
                        addItem(v);
                        itemsList.get(recyclerView.getChildAdapterPosition(v)).setChecked(true);
                    }
                    break;                 
                default:
                    //In my case I have checkList in subItems,
                    //checkItem(v);
                    break;
            }
        }
    };
    

    3) Add your addItem() and deleteItem()

    private void addItem(View view){
        int position = recyclerView.getChildLayoutPosition(view);
        if (position != RecyclerView.NO_POSITION){
            navDrawItems.add(position+1,new mObject());
            navDrawItems.add(position+2,new mObject());
            notifyItemRangeInserted(position+1,2);
        }
    }
    
    
    private void deleteItem(View view) {
        int position = recyclerView.getChildLayoutPosition(view);
        if (position != RecyclerView.NO_POSITION) {
            navDrawItems.remove(position+2);
            navDrawItems.remove(position+1);
            notifyItemRangeRemoved(position+1,2);
        }
    }
    

    4) If your RecyclerViewAdapter is not in the same Activity as Recycler View, pass instance of recyclerView to the Adapter while creating

    5) itemList is a ArrayList of type mObject which helps maintain states of item (Open/Close) , name, type of Item(subItems/mainItem) and set Theme based on values

    public class mObject{
        private String label;
        private int type;
        private boolean checked;
    } 
    
    0 讨论(0)
  • 2020-11-27 11:27

    Someone complained about that the above mentioned solution is not usable with a listview as expandable content. But there's a simple solution: create a listview and fill this listview manually with your rows.

    Solution for the lazy ones: there's a simple solution if you don't want to change your code to much. Just manually use your adapter to create views and add them to the LinearLayout.

    Here's the example:

    if (mIsExpanded)
    {
        // llExpandable... is the expandable nested LinearLayout
        llExpandable.removeAllViews();
        final ArrayAdapter<?> adapter = ... // create your adapter as if you would use it for a ListView
        for (int i = 0; i < adapter.getCount(); i++)
        {
            View item = adapter.getView(i, null, null);
            // if you want the item to be selectable as if it would be in a default ListView, then you can add following code as well:
            item.setBackgroundResource(Functions.getThemeReference(context, android.R.attr.selectableItemBackground));
            item.setTag(i);
            item.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    // item would be retrieved with: 
                    // adapter.getItem((Integer)v.getTag())
                }
            });
            llExpandable.addView(item);
        }
        ExpandUtils.expand(llExpandable, null, 500);
    }
    else
    {
        ExpandUtils.collapse(llExpandable, null, 500);
    }
    

    helper functions: getThemeReference

    public static int getThemeReference(Context context, int attribute)
    {
        TypedValue typeValue = new TypedValue();
        context.getTheme().resolveAttribute(attribute, typeValue, false);
        if (typeValue.type == TypedValue.TYPE_REFERENCE)
        {
            int ref = typeValue.data;
            return ref;
        }
        else
        {
            return -1;
        }
    }
    

    helper class: ExpandUtils

    Kavin Varnan postet already how to animate a layout... But if you want to use my class, feel free to do so, I posted a gist: https://gist.github.com/MichaelFlisar/738dfa03a1579cc7338a

    0 讨论(0)
  • 2020-11-27 11:31

    Get the sample code implementation from here

    Set ValueAnimator inside onClick of ViewHolder

    @Override
    public void onClick(final View view) {
        if (mOriginalHeight == 0) {
            mOriginalHeight = view.getHeight();
        }
        ValueAnimator valueAnimator;
        if (!mIsViewExpanded) {
            mIsViewExpanded = true;
            valueAnimator = ValueAnimator.ofInt(mOriginalHeight, mOriginalHeight + (int) (mOriginalHeight * 1.5));
        } else {
            mIsViewExpanded = false;
            valueAnimator = ValueAnimator.ofInt(mOriginalHeight + (int) (mOriginalHeight * 1.5), mOriginalHeight);
        }
        valueAnimator.setDuration(300);
        valueAnimator.setInterpolator(new LinearInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            public void onAnimationUpdate(ValueAnimator animation) {
                Integer value = (Integer) animation.getAnimatedValue();
                view.getLayoutParams().height = value.intValue();
                view.requestLayout();
            }
        });
        valueAnimator.start();
    
    }
    

    Here is the final code

    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        private TextView mFriendName;
        private int mOriginalHeight = 0;
        private boolean mIsViewExpanded = false;
    
    
        public ViewHolder(RelativeLayout v) {
            super(v);
            mFriendName = (TextView) v.findViewById(R.id.friendName);
            v.setOnClickListener(this);
        }
    
        @Override
        public void onClick(final View view) {
            if (mOriginalHeight == 0) {
                mOriginalHeight = view.getHeight();
            }
            ValueAnimator valueAnimator;
            if (!mIsViewExpanded) {
                mIsViewExpanded = true;
                valueAnimator = ValueAnimator.ofInt(mOriginalHeight, mOriginalHeight + (int) (mOriginalHeight * 1.5));
            } else {
                mIsViewExpanded = false;
                valueAnimator = ValueAnimator.ofInt(mOriginalHeight + (int) (mOriginalHeight * 1.5), mOriginalHeight);
            }
            valueAnimator.setDuration(300);
            valueAnimator.setInterpolator(new LinearInterpolator());
            valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                public void onAnimationUpdate(ValueAnimator animation) {
                    Integer value = (Integer) animation.getAnimatedValue();
                    view.getLayoutParams().height = value.intValue();
                    view.requestLayout();
                }
            });
            valueAnimator.start();
    
        }
    }
    
    0 讨论(0)
  • 2020-11-27 11:39

    https://github.com/gabrielemariotti/cardslib

    This library has an implementation of an expandable list with a recyclerview (refer to the demo app under "CardViewNative" --> "List, Grid, and RecyclerView" --> "Expandable cards"). It also has a lot of other cool combinations of cards/lists.

    0 讨论(0)
  • 2020-11-27 11:44

    You can use ExpandableLayout that like a smooth expand/collapse animation CheckBox, so you can use it as CheckBox in ListView and RecyclerView.

    https://github.com/KyoSherlock/ExpandableLayout

    0 讨论(0)
  • 2020-11-27 11:51

    This is simple to do with the stock LayoutManagers, it all depends on how you manage your adapter.

    When you want to expand a section you just add new items to your adapter after the header. Remember to call notifyItemRangeInserted when you do this. To collapse a section you simply remove the relevant items, and call notifyItemRangeRemoved(). For any data changes that are appropriately notified, the recycler view will animate the views. When adding items, an area to be filled with the new items is made, with the new items fading in. Removal is the opposite. All you need to do besides the adapter stuff is to style your views to convey the logical structure to the user.

    Update: Ryan Brooks has now written an article on how to do this.

    0 讨论(0)
提交回复
热议问题