Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/184.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 可扩展列表与RecyclerView?_Android_Android Recyclerview - Fatal编程技术网

Android 可扩展列表与RecyclerView?

Android 可扩展列表与RecyclerView?,android,android-recyclerview,Android,Android Recyclerview,可以将可扩展列表项与新的RecyclerView一起使用吗?像ExpandableListView一样?从 在ViewHolder的单击中设置值Animator @Override public void onClick(final View view) { if (mOriginalHeight == 0) { mOriginalHeight = view.getHeight(); } ValueAnimator valueAnimator; i

可以将可扩展列表项与新的RecyclerView一起使用吗?像ExpandableListView一样?

在ViewHolder的单击中设置值Animator

@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();

}
这是最后的代码

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();

    }
}

有人抱怨说,上述解决方案无法将listview用作可扩展内容。但是有一个简单的解决方案:创建一个listview并用您的行手动填充这个listview

懒惰者的解决方案:如果您不想对代码进行太多更改,有一个简单的解决方案。只需手动使用适配器创建视图并将其添加到
线性布局中

下面是一个例子:

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);
}
助手类:ExpandUtils

Kavin Varnan postet已经介绍了如何设置布局动画。。。 但是如果你想使用我的课程,请随意使用,我发布了一个要点:


此库实现了一个带有recyclerview的可扩展列表(请参阅“CardViewNative”-->“list、Grid和recyclerview”-->“可扩展卡”下的演示应用程序)。它还有许多其他很酷的卡片/列表组合

这对于stock LayoutManager很简单,这完全取决于您如何管理适配器

当您想要展开一个部分时,您只需在标题之后向适配器添加新项目。执行此操作时,请记住调用notifyItemRangeInserted。要折叠节,只需删除相关项,然后调用notifyItemRangeRemoved()。对于适当通知的任何数据更改,“回收器”视图将设置视图的动画。添加项目时,将创建一个要填充新项目的区域,新项目将淡入。移除则相反。除了适配器之外,您所需要做的就是设置视图的样式,以便将逻辑结构传达给用户


更新:Ryan Brooks现在已经写了一篇关于如何做到这一点的文章。

您可以使用类似平滑展开/折叠动画复选框的ExpandableLayout,因此您可以将其用作ListView和RecyclerView中的复选框


这是@TonicArtos提到的示例代码。要添加和删除项目,并在执行过程中对其进行动画制作,请参见和

1)在您的onCreateViewHolder()中添加侦听器以注册onClick

2)在适配器内创建自定义的OnClickListener

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)添加addItem()和deleteItem()

4)如果您的RecycleWebAdapter与Recycler视图不在同一活动中,请在创建时将RecycleWebView的实例传递给适配器

5)itemList是一个类型为mObject的数组列表,它有助于维护项的状态(打开/关闭)、名称、项的类型(子项/main项)以及基于值设置主题

public class mObject{
    private String label;
    private int type;
    private boolean checked;
} 

“像
ExpandableListView
”一样,这不起作用,因为在这种情况下,扩展内容本身就是一个列表,其中包含来自适配器的项。这是一个退化的解决方案,组中只允许有一个项作为子项。它也不适用于完全回收的视图。它不适用于回收列表中的视图,因为该视图可能会重复多次,因此当您展开一个项时,您会看到列表中的多个项被展开“懒惰解决方案”是一个非常糟糕的主意。将视图添加到可滚动视图中的线性布局是非常低效的。我认为它至少比可用性更好。在我测试过的所有设备上都能快速平滑地工作。顺便说一下,视图是在listview不可见时添加的。。。之后将只显示已填充的列表视图…这很好!谢谢Matthew提到的tonAs@Matthew,这真的不是个好主意。使用带有线性布局的单个大型可滚动视图无法很好地进行缩放。编写RecyclerView/ListView和其他类似视图的最大原因之一是优化具有未知大小的大型数据备份列表。构建一个包含一组添加视图的单一视图会抛出所有提供的优化。回收视图是一个巨大的好处,它可以提高应用程序的内存效率。除非项目数量很小,否则使用列表处理视图绑定可以节省大量工作。你说得很对,当然这并不完美,也不会优化任何东西。。。对于我的用例,我总是只有几个项目。。。所以这没问题。。。顺便说一句,在此期间,我找到了一种嵌套回收器视图的方法。。。只需使用固定高度的水平回收器视图(并非适用于所有用例,但仍然适用)作为嵌套的
recyclerview
,您可以展开/隐藏此嵌套视图,并使用
recyclerview
的所有优化。不知道为什么没有人对这个答案投赞成票!!我将在下一个版本中考虑将此作为一个示例添加到SuperSLiM中。Ryan Brooks现在已经写了一篇关于如何做到这一点的文章。很好的建议。为什么这个答案在页面上这么远,我必须向下滚动才能找到它?它应该显示在最上面,这样更多的人可以更容易地找到这个漂亮的答案。Ryan Brooks将他的库标记为不推荐。我想知道是不是因为他不再支持它,还是因为这种方法破坏了某些东西,或者造成了内存泄漏等等……这个可扩展的卡片列表不是RecyclerView的产物(它没有扩展RecyclerView,它只是扩展了ExpandableListVIew)你可以在android 6上的google source中看到android时钟。0@zys在哪里可以找到此android clock示例源代码?单击展开按钮时,可以使用不同的viewType加载不同的布局。android clock使用此解决方案:请参阅我的简单答案,了解两个级别:。对于三个或更多级别:。
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);
    }
}
public class mObject{
    private String label;
    private int type;
    private boolean checked;
}