使用RecyclerView和可扩展卡的奇怪故障[重复]

问题描述 投票:1回答:2

这个问题在这里已有答案:

我试图通过每个路线应用程序的小步行持续时间进入Android应用程序开发。 但是有一点小故障阻止我继续下去。 我尝试谷歌多次没有结果,这是事情:

我的RecyclerViewonClick-expand cards显示奇怪的行为,一旦我添加太多的项目重新加载整个列表。它也会以某种方式将整个列表移动一秒钟。作为参考,这是我的github项目:https://github.com/TheInsayn/velocity

这是它应该如何表现: Imgur

但是在我添加了第6个项目后,它的行为如下:

Imgur

这是我用于适配器的代码(特别是onBindViewHolderisExpanded): 我甚至使用了来自I / O 2016的Google的参考建议。(我真的不想使用第三方库)

class RecyclerAdapterWalks extends RecyclerView.Adapter<RecyclerAdapterWalks.WalkCardHolder> {
private List<Walk> mWalkList;
private RecyclerView mRecyclerView;
private int mExpandedPosition = -1;

class WalkCardHolder extends RecyclerView.ViewHolder {
    TextView mWalkRoute;
    TextView mWalkDuration;
    TextView mWalkDate;
    TextView mWalkWeekday;
    RelativeLayout mExpansion;
    TextView mAverageTime;

    WalkCardHolder(View view) {
        super(view);
        mWalkRoute = view.findViewById(R.id.txt_walk_route);
        mWalkDuration = view.findViewById(R.id.txt_walk_duration);
        mWalkDate = view.findViewById(R.id.txt_walk_date);
        mWalkWeekday = view.findViewById(R.id.txt_walk_weekday);
        mExpansion = view.findViewById(R.id.walk_card_expansion);
        mAverageTime = view.findViewById(R.id.txt_walk_average);
    }
}

RecyclerAdapterWalks(List<Walk> routes, RecyclerView rv) {
    mWalkList = routes;
    mRecyclerView = rv;
    setHasStableIds(true);
}

@Override
public WalkCardHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_walk, parent, false);
    return new WalkCardHolder(view);
}

@Override
public void onBindViewHolder(WalkCardHolder holder, int position) {
    Walk walk = mWalkList.get(position);
    holder.mWalkRoute.setText(walk.getRoute().getName());
    holder.mWalkDuration.setText(DateFormat.format("mm:ss", new Date(walk.getDuration())));
    holder.mWalkDate.setText(DateFormat.format("dd.MM.yyyy", walk.getDate()));
    holder.mWalkWeekday.setText(DateFormat.format("EEEE", walk.getDate()));
    //handle expansion in list
    final boolean isExpanded = position == mExpandedPosition;
    holder.mExpansion.setVisibility(isExpanded ? View.VISIBLE : View.GONE);
    holder.itemView.setActivated(isExpanded);
    holder.itemView.setOnClickListener(v -> {
        mExpandedPosition = isExpanded ? -1 : position;
        TransitionManager.beginDelayedTransition(mRecyclerView);
        notifyDataSetChanged();
    });
    if (isExpanded) {
        Date avg = new Date(walk.getRoute().getAverageWalkTime(mRecyclerView.getContext()));
        CharSequence min = DateFormat.format("m", avg);
        CharSequence sec = DateFormat.format("s", avg);
        String boldText = walk.getRoute().getName();
        String timeStr = "average walk duration for " + boldText + ": ";
        if (!min.equals("0")) timeStr += min + "m and ";
        timeStr += sec + "s";
        int idx = timeStr.indexOf(boldText);
        SpannableString str = new SpannableString(timeStr);
        str.setSpan(new StyleSpan(Typeface.BOLD), idx, idx + boldText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        holder.mAverageTime.setText(str);
    }
}

@Override
public int getItemCount() {
    return mWalkList.size();
}

我在RelativeLayout的FrameLayout中的CoordinatorLayout中的RecyclerView中有CardView ...

有没有人知道可能导致这种情况的原因? 对不起,很长的帖子,谢谢你的帮助。 :)

编辑:在Adapter的构造函数中使用setHasStableIds(true)似乎有点帮助。但现在转型远非顺利。 小清单(更糟): Imgur 更长的清单(更好): Imgur

java android android-recyclerview android-cardview
2个回答
0
投票

由于notifyDataSetChanged();线,它正在重新加载整个列表。这刷新了整个清单。如果你只添加了一个元素,我会建议使用notifyItemInserted(int position)或者如果你要更新单个项目,那么只需使用函数notifyItemChanged(int position)


0
投票

基于@napster的输入,我终于在一个老话题的帮助下解决了我的问题。 我非常信任来自I / O的Nick Butcher的例子。 引用:“这是一个可怕的解决方案” 通过使用https://stackoverflow.com/a/48092441/9165497的技术,一切都有所改善,我现在认为问题得到了解决。

现在我的代码看起来像这样,一切都更顺畅,没有问题:

final boolean isExpanded = position == mExpandedPosition;
holder.mExpansion.setVisibility(isExpanded ? View.VISIBLE : View.GONE);
holder.itemView.setActivated(isExpanded);
if (isExpanded) mPreviousExpandedPosition = holder.getAdapterPosition();
holder.itemView.setOnClickListener(v -> {
    mExpandedPosition = isExpanded ? -1 : holder.getAdapterPosition();
    notifyItemChanged(mPreviousExpandedPosition);
    notifyItemChanged(holder.getAdapterPosition());
});
© www.soinside.com 2019 - 2024. All rights reserved.