使用RecyclerView的可扩展列表?

Dar*_*sin 92 android android-recyclerview

可以在新的RecyclerView中使用可扩展列表项吗?像ExpandableListView一样?

Ton*_*tos 119

这对布局管理器来说很简单,这完全取决于您管理适配器的方式.

如果要扩展某个部分,只需在标题后添加新项目到适配器.记得在执行此操作时调用notifyItemRangeInserted.要折叠部分,只需删除相关项,然后调用notifyItemRangeRemoved().对于适当通知的任何数据更改,回收器视图将为视图设置动画.添加项目时,将填充新项目的区域,新项目将逐渐淡入.删除项目正好相反.除了适配器之外,您需要做的就是设置视图样式以将逻辑结构传达给用户.

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

  • Ryan Brooks 将他的库标记为已弃用。我想知道是否只是他已经停止支持它,或者事实证明这种方法破坏了某些东西或造成内存泄漏或...... (2认同)

Kav*_*nan 7

这里获取示例代码实现

在ViewHolder的onClick中设置ValueAnimator

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

}
Run Code Online (Sandbox Code Playgroud)

这是最终的代码

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

    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这不像"ExpandableListView"那样工作,因为在这种情况下扩展的内容是一个列表本身,其中包含来自适配器的项目.这是一个简并解决方案,只允许1个项目作为组内的孩子. (10认同)

pro*_*m85 0

有人抱怨上述解决方案不能与列表视图一起用作可扩展内容。但有一个简单的解决方案:创建一个列表视图并用您的 rows 手动填充此列表视图

懒人的解决方案:如果您不想对代码进行太多更改,有一个简单的解决方案。只需手动使用适配器创建视图并将它们添加到LinearLayout.

这是例子:

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);
}
Run Code Online (Sandbox Code Playgroud)

辅助函数: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;
    }
}
Run Code Online (Sandbox Code Playgroud)

辅助类:ExpandUtils

Kavin Varnan 已经发布了如何对布局进行动画处理...但是如果您想使用我的课程,请随意这样做,我发布了一个要点:https://gist.github.com/MichaelFlisar/738dfa03a1579cc7338a

  • “懒惰解决方案”是一个非常糟糕的主意。将视图添加到可滚动视图内的线性布局效率非常低。 (9认同)