【问题标题】:Collapsing all other Recyclerview items when one is expanded展开时折叠所有其他 Recyclerview 项目
【发布时间】:2017-06-27 16:15:26
【问题描述】:

我有一个设置良好的可扩展回收器视图。单击任何项​​目时,它会展开以显示更多详细信息。但我想在这里改变一下。单击一项以展开时,应折叠所有其他项。这是我的适配器代码:

public class DataAdapter extends RecyclerView.Adapter<DataAdapter.ViewHolder> {
    private ArrayList<ListItem> android_versions;
    private List<ListItem> listItems;
    private LayoutInflater layoutInflater;
    private Animation animationUp, animationDown;
    private Context context;
    private final int COUNTDOWN_RUNNING_TIME = 500;
    int i =0;

    public DataAdapter(Context context, java.util.List<ListItem> android_versions,
                       Animation animationUp, Animation animationDown) {
        this.context = context;
        this.listItems = android_versions;
        this.animationDown = animationDown;
        this.animationUp = animationUp;
    }

    @Override
    public DataAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.row_layout, viewGroup, false);
        return new ViewHolder(view);
    }

    public String getRandomColor(int a){
        String colors[] = {"#ef5350","#f44336","#ef5350"};
        return colors[a];
    }

    @Override
    public void onBindViewHolder(final ViewHolder holder, int i) {
        ListItem listItem = listItems.get(i);
        if (i%2==2)
            holder.itemView.setBackgroundColor(Color.parseColor(getRandomColor(0)));
        else if (i%2==1)
            holder.itemView.setBackgroundColor(Color.parseColor(getRandomColor(1)));
        else if (i%2==0)
            holder.itemView.setBackgroundColor(Color.parseColor(getRandomColor(2)));

        holder.tv_android.setText(listItem.getSubName());
        holder.contentLayout.setText(listItem.getContent());
        holder.expandit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                if (holder.contentLayout.isShown()) {
                    holder.contentLayout.startAnimation(animationUp);
                    CountDownTimer countDownTimerStatic = new CountDownTimer(COUNTDOWN_RUNNING_TIME, 16) {
                        @Override
                        public void onTick(long millisUntilFinished) {
                        }

                        @Override
                        public void onFinish() {
                            holder.contentLayout.setVisibility(View.GONE);
                        }
                    };
                    countDownTimerStatic.start();
                } else {
                    holder.contentLayout.setVisibility(View.VISIBLE);
                    holder.contentLayout.startAnimation(animationDown);
                }
            }
        });
    }
    @Override
    public int getItemCount() {
        return listItems.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder{
        TextView tv_android;
        private TextView contentLayout;
        RelativeLayout expandit;
        public ViewHolder(View view) {
            super(view);
            tv_android = (TextView)view.findViewById(R.id.tv_android);
            contentLayout = (TextView) view.findViewById(R.id.content);
            expandit = (RelativeLayout)view.findViewById(R.id.expandit);
        }
    }
}

我认为不可能按位置更改 viewHolder 的内容。那么如何按位置隐藏所有其他项目的内容。我认为不需要其他代码,所以我没有包含它。

编辑:根据 Ashish 的建议编写代码:

  private void changeStateOfItemsInLayout(ListItem listItem) {
        for (int i = 0; i < listItems.size(); i++) {
            if (listItems.get(i) == listItem)
                listItem.setShouldBeExpanded(true);
            else
                listItem.setShouldBeExpanded(false);
        }
    }

    @Override
    public void onBindViewHolder(final ViewHolder holder, int i) {
        ListItem listItem = listItems.get(i);
        if (i%2==2)
            holder.itemView.setBackgroundColor(Color.parseColor(getRandomColor(0)));
        else if (i%2==1)
            holder.itemView.setBackgroundColor(Color.parseColor(getRandomColor(1)));
        else if (i%2==0)
            holder.itemView.setBackgroundColor(Color.parseColor(getRandomColor(2)));

        holder.tv_android.setText(listItem.getSubName());
        holder.contentLayout.setText(listItem.getContent());
        if(listItem.getShouldBeExpanded()){
            holder.contentLayout.setVisibility(View.VISIBLE);
            holder.contentLayout.startAnimation(animationDown);
        }else{
            holder.contentLayout.startAnimation(animationUp);
            CountDownTimer countDownTimerStatic = new CountDownTimer(COUNTDOWN_RUNNING_TIME, 16) {
                @Override
                public void onTick(long millisUntilFinished) {
                }

                @Override
                public void onFinish() {
                    holder.contentLayout.setVisibility(View.GONE);
                }
            };
            countDownTimerStatic.start();
        }

        holder.expandit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (holder.contentLayout.isShown()) {
                    holder.contentLayout.startAnimation(animationUp);
                    CountDownTimer countDownTimerStatic = new CountDownTimer(COUNTDOWN_RUNNING_TIME, 16) {
                        @Override
                        public void onTick(long millisUntilFinished) {
                        }

                        @Override
                        public void onFinish() {
                            holder.contentLayout.setVisibility(View.GONE);
                        }
                    };
                    countDownTimerStatic.start();
                } else {
                    holder.contentLayout.setVisibility(View.VISIBLE);
                    holder.contentLayout.startAnimation(animationDown);
                }
                listItems.get(holder.getLayoutPosition()).setShouldBeExpanded(true);
                changeStateOfItemsInLayout(listItems.get(holder.getLayoutPosition()));
                notifyDataSetChanged();
            }
        });
    }

虽然在onClick中,我还是有展开/折叠布局的代码,即使我把它去掉也不起作用。

如果需要,这是我的模态类:

public class ListItem {

    private String subName;
    private String content;
    private String param;
    private Boolean shouldBeExpanded=false;

    public Boolean getShouldBeExpanded() {
        return shouldBeExpanded;
    }

    public void setShouldBeExpanded(Boolean shouldBeExpanded) {
        this.shouldBeExpanded = shouldBeExpanded;
    }

    public ListItem(String subName, String content) {
        this.subName = subName;
        this.content = content;
        this.param = "Nothing";
    }

    public String getParam() {
        return param;
    }

    public ListItem(String subName, String content, String param) {

        this.subName = subName;
        this.content = content;
        this.param = param;
    }

    public String getSubName() {
        return subName;
    }

    public String getContent() {
        return content;
    }
}

编辑:根据要求,这里是animationUp文件和animationDown文件的代码:

animationUp.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true" >

    <scale
        android:duration="200"
        android:fromXScale="1.0"
        android:fromYScale="1.0"
        android:interpolator="@android:anim/linear_interpolator"
        android:toXScale="1.0"
        android:toYScale="0.0" />

</set>

animationDown.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true">

    <scale
        android:duration="200"
        android:fromXScale="1.0"
        android:fromYScale="0.0"
        android:interpolator="@android:anim/accelerate_interpolator"
        android:toXScale="1.0"
        android:toYScale="1.0" />

</set>

【问题讨论】:

    标签: java android


    【解决方案1】:

    感谢 Ashish,我用一个简单的逻辑解决了这个问题。这是我重新定义的 changeStateOfItemsInLayout 函数代码:

    private void changeStateOfItemsInLayout(ListItem listItem, int p) {
            for (int x = 0; x < listItems.size(); x++) {
                if (x == p) {
                    listItem.setShouldBeExpanded(true);
                    //Since this is the tapped item, we will skip
                    //the rest of loop for this item and set it expanded
                    continue;
                }
                listItems.get(x).setShouldBeExpanded(false);
            }
        }
    

    此功能负责折叠所有其他项目。它检查哪个选项被点击并展开它(如果已经展开,我们不会从 OnBindViewHolder 函数调用这个函数)并折叠所有其他选项。

    这是我的完整适配器代码:

    public class DataAdapter extends RecyclerView.Adapter<DataAdapter.ViewHolder> {
        private ArrayList<ListItem> android_versions;
        private List<ListItem> listItems;
        private LayoutInflater layoutInflater;
        private Animation animationUp, animationDown;
        private Context context;
        private final int COUNTDOWN_RUNNING_TIME = 300;
    
        public DataAdapter(Context context, java.util.List<ListItem> android_versions,
                           Animation animationUp, Animation animationDown) {
            this.context = context;
            this.listItems = android_versions;
            this.animationDown = animationDown;
            this.animationUp = animationUp;
        }
    
        @Override
        public DataAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
            View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.row_layout, viewGroup, false);
            return new ViewHolder(view);
        }
    
        public String getRandomColor(int a){
            String colors[] = {"#ef5350","#f44336","#ef5350"};
            return colors[a];
        }
    
        private void changeStateOfItemsInLayout(ListItem listItem, int p) {
            for (int x = 0; x < listItems.size(); x++) {
                if (x == p) {
                    listItem.setShouldBeExpanded(true);
                    //Since this is the tapped item, we will skip
                    //the rest of loop for this item and set it expanded
                    continue;
                }
                listItems.get(x).setShouldBeExpanded(false);
            }
        }
    
    
        @Override
        public void onBindViewHolder(final ViewHolder holder, int i) {
            ListItem listItem = listItems.get(i);
            if (i%2==2)
                holder.itemView.setBackgroundColor(Color.parseColor(getRandomColor(0)));
            else if (i%2==1)
                holder.itemView.setBackgroundColor(Color.parseColor(getRandomColor(1)));
            else if (i%2==0)
                holder.itemView.setBackgroundColor(Color.parseColor(getRandomColor(2)));
    
            holder.tv_android.setText(listItem.getSubName());
            holder.contentLayout.setText(listItem.getContent());
            if(listItem.getShouldBeExpanded()){
                holder.contentLayout.setVisibility(View.VISIBLE);
                holder.contentLayout.startAnimation(animationDown);
            }else{
                holder.contentLayout.startAnimation(animationUp);
                CountDownTimer countDownTimerStatic = new CountDownTimer(COUNTDOWN_RUNNING_TIME, 16) {
                    @Override
                    public void onTick(long millisUntilFinished) {}
                    @Override
                    public void onFinish() {
                        holder.contentLayout.setVisibility(View.GONE);
                    }
                };
                countDownTimerStatic.start();
            }
    
            holder.expandit.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if (holder.contentLayout.isShown()) {
                        listItems.get(holder.getLayoutPosition()).setShouldBeExpanded(false);
                    } else {
                        listItems.get(holder.getLayoutPosition()).setShouldBeExpanded(true);
                        changeStateOfItemsInLayout(listItems.get(holder.getLayoutPosition()),holder.getLayoutPosition());
                    }
                    notifyDataSetChanged();
                }
            });
        }
        @Override
        public int getItemCount() {
            return listItems.size();
        }
    
        public class ViewHolder extends RecyclerView.ViewHolder{
            TextView tv_android;
            private TextView contentLayout;
            RelativeLayout expandit;
            public ViewHolder(View view) {
                super(view);
                tv_android = (TextView)view.findViewById(R.id.tv_android);
                contentLayout = (TextView) view.findViewById(R.id.content);
                expandit = (RelativeLayout)view.findViewById(R.id.expandit);
            }
        }
    }
    

    【讨论】:

    • 能否提供animationUp和animationDown的代码?
    • @Fathimakm 我已经编辑了帖子以添加您的代码。请检查!
    【解决方案2】:

    在我假设是模型类的 ListItem 类中,添加一个新的布尔变量 shouldBeExpanded 并将其默认值设置为 false,然后编写它的 getter 和 setter。现在在您的适配器中,在 onBindViewHolder 中编写以下代码

    if(listItem.shouldBeExpanded()){
    //write your code to expand it
    }else{
    //write the code to collapse
    }
    

    现在在代码部分,在一些展开布局的 onClick 中,将此 lisItem 的此变量设置为 true,并调用一个函数,将 listItem 中的所有其他项目设置为 false 的 shouldBeExpanded..通过调用下面的函数changeStateOfItemsInLayout(listItem)。 现在称为 notifyDataSetChanged()。

    private void changeStateOfItemsInLayout(ListItem listItem){
    for(int i=0;i<listItems.size();i++){
    if(listItems.get(i)==listItem)
    listItem.get(i).setShouldBeExpanded(true);
    }else{
    listItem.get(i).setShouldBeExpanded(false);
    }
    }
    

    这应该可以解决您的目的。

    【讨论】:

    • 对我不起作用。当我点击一个项目时,它会扩展一小会儿,然后立即折叠,除了最后一个项目。
    • 出现问题。我一直在使用 listItem 作为最终版本。但删除了 final 关键字。问题仍然存在。
    • 我还是没看到
    • 就在onBindViewHolder函数上方
    • 在调用 notifyDataSetChanges() 后,您能否调试一下,看看 shouldBeExpanded 的值对于正确的列表项是否为 true,而对于其他列表项是否为 false。
    【解决方案3】:

    我花了几个小时摆弄 ExpandableRecyclerAdapter 代码。但这真的很简单。在您的活动中,您有展开/折叠事件的侦听器,当前父列表项位置正在展开/折叠。跟踪 currentExpandedPosition 并调用适配器 collapseParent 以折叠先前展开的项目。 5行代码,完美的手风琴效果。

    private currentExpandedPosition = -1;
    
            mAdapter.setExpandCollapseListener(new ExpandableRecyclerAdapter.ExpandCollapseListener() {
            @Override
            public void onListItemExpanded(int position) {
    
                if (currentExpandedPosition >= 0){
                    mAdapter.collapseParent(currentExpandedPosition);
                }
                currentExpandedPosition = position;
            }
    
            @Override
            public void onListItemCollapsed(int position) {
    
               currentExpandedPosition = -1;
            }
        });
    

    【讨论】:

      猜你喜欢
      • 2015-01-28
      • 1970-01-01
      • 1970-01-01
      • 2018-02-15
      • 1970-01-01
      • 2012-07-13
      • 2021-10-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多