java - RecyclerView 执行项目点击

标签 java android android-layout android-recyclerview android-viewholder

我有一个 RecyclerView包含可扩展项目。单击一个项目将其展开。问题是它还意外地扩展了其他一些卡。我检查了所有内容,但找不到发生这种情况的原因,但我确实设法发现单击的项目总是以某种方式与其他展开的项目具有相同的 id。只有当列表足够大时才会出现错误,所以我认为它与RecyclerView有关的功能。也使用 notifyDataSetChanged()有效,但它消除了动画,我希望布局动画......

this问题看起来讨论了我面临的同样问题......但我不知道如何解决它。

我不明白为什么会发生这种情况或如何解决这个问题......下面是一些图像和代码,可以帮助您更好地理解,也许看看问题是否出在代码中......

这是RecyclerView :

enter image description here

扩展的卡片项目如下所示:

enter image description here

这是我的适配器类:

public class ActiveGoalsAdapter extends RecyclerView.Adapter<ActiveGoalsAdapter.ActiveGoalsViewHolder> {

    private Context context;
    private Cursor cursor;
    private ArrayList<Goal> activeGoals;
    private static boolean[] openedFromParent = new boolean[]{false, true}, editing = new boolean[]{false};

    public ActiveGoalsAdapter(Context context, ArrayList<Goal> activeGoals, Cursor cursor) {
        this.context = context;
        this.activeGoals = activeGoals;
        this.cursor = cursor;
    }

    public class ActiveGoalsViewHolder extends RecyclerView.ViewHolder {

        public LinearLayout shrunkContainer, subGoalsTitleContainer;
        public RelativeLayout expandedContainer, subGoalsRecyclerViewContainer, btnDelete, btnCancel, btnSave;
        public ConstraintLayout editPanel;
        public CustomProgressBar shrunkProgressBar, expandedProgressBar;
        public ImageButton btnExpandShrink, btnEdit, btnBackToParent;
        public TextView title, description;
        public RecyclerView subGoalsRecyclerView;
        public ExtendedEditText nameET, descriptionET;

        public ActiveGoalsViewHolder(@NonNull View itemView) {
            super(itemView);

            shrunkContainer = itemView.findViewById(R.id.shrunk_active_goal_container);
            expandedContainer = itemView.findViewById(R.id.expanded_active_goal_container);
            editPanel = itemView.findViewById(R.id.edit_panel);
            btnExpandShrink = itemView.findViewById(R.id.active_goal_expand_shrink_btn);
            btnEdit = itemView.findViewById(R.id.active_goal_edit_btn);
            btnBackToParent = itemView.findViewById(R.id.active_goal_back_to_parent_btn);
            shrunkProgressBar = itemView.findViewById(R.id.shrunk_active_goal_progress_bar);
            shrunkProgressBar.enableDefaultGradient(true);
            title = itemView.findViewById(R.id.expanded_active_goal_title);
            expandedProgressBar = itemView.findViewById(R.id.expanded_active_goal_progress_bar);
            expandedProgressBar.enableDefaultGradient(true);
            description = itemView.findViewById(R.id.expanded_active_goal_description);
            subGoalsTitleContainer = itemView.findViewById(R.id.expanded_active_goal_sub_goals_title_container);
            subGoalsRecyclerViewContainer = itemView.findViewById(R.id.expanded_active_goal_sub_goals_container);
            subGoalsRecyclerView = itemView.findViewById(R.id.expanded_active_goal_sub_goals_recyclerview);
            nameET = itemView.findViewById(R.id.expanded_active_goal_edit_name_edit_text);
            descriptionET = itemView.findViewById(R.id.expanded_active_goal_edit_description_edit_text);
            btnDelete = itemView.findViewById(R.id.edit_delete_button);
            btnCancel = itemView.findViewById(R.id.edit_cancel_button);
            btnSave = itemView.findViewById(R.id.edit_save_button);

            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (expandedContainer.getVisibility() == View.VISIBLE) {
                        shrink();
                    } else {
                        expand();
                    }
                }
            });

        }

        private void expand(){
            TransitionManager.beginDelayedTransition((ViewGroup) itemView.getRootView(), new AutoTransition());
            expandedContainer.setVisibility(View.VISIBLE);
            shrunkProgressBar.setVisibility(View.INVISIBLE);

        }

        private void shrink(){
            TransitionManager.beginDelayedTransition((ViewGroup) itemView.getRootView(), new AutoTransition());
            expandedContainer.setVisibility(View.GONE);
            shrunkProgressBar.setVisibility(View.VISIBLE);
        }

    }

    @NonNull
    @Override
    public ActiveGoalsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(context);
        View view = inflater.inflate(R.layout.active_goal_card, parent, false);
        return new ActiveGoalsViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ActiveGoalsViewHolder holder, int position) {
        if (activeGoals.get(position) == null) {
            return;
        }
        GoalDBHelper db = new GoalDBHelper(context);

        Goal currentGoal = activeGoals.get(position);
        Cursor subGoalsCursor = db.getSubGoalsCursorOf(currentGoal);
        ArrayList<Goal> subGoalsArrayList = db.getSubGoalsArrayListOf(currentGoal);

        String name = currentGoal.getName(),
                description = currentGoal.getDescription(),
                parent = currentGoal.getParentGoal();
        int timeCounted = currentGoal.getTimeCounted(),
                timeEstimated = currentGoal.getTimeEstimated();

        for (Goal subGoal : activeGoals) {
            if (subGoal.getParentGoal().equals(name)) {
                subGoalsArrayList.add(subGoal);
            }
        }

        holder.shrunkProgressBar.setText(name);
        holder.shrunkProgressBar.setProgress((timeCounted * 100 / timeEstimated));
        holder.shrunkProgressBar.setRadius(300.0f);
        holder.expandedProgressBar.setText("");
        holder.expandedProgressBar.setProgress((timeCounted * 100 / timeEstimated));
        holder.expandedProgressBar.setRadius(300.0f);
        holder.title.setText(name);
        holder.description.setText(description);

        if (subGoalsArrayList.size() <= 0) {
            holder.subGoalsTitleContainer.setVisibility(View.GONE);
            holder.subGoalsRecyclerViewContainer.setVisibility(View.GONE);
        } else {
            holder.subGoalsTitleContainer.setVisibility(View.VISIBLE);
            holder.subGoalsRecyclerViewContainer.setVisibility(View.VISIBLE);
            initSubGoalsAdapter(holder.subGoalsRecyclerView, subGoalsArrayList, subGoalsCursor);
        }

        if (openedFromParent[0]) {
            holder.btnBackToParent.setVisibility(View.VISIBLE);
        } else {
            holder.btnBackToParent.setVisibility(View.GONE);
        }

    }

    public void initSubGoalsAdapter(RecyclerView subGoalsRecyclerView, ArrayList<Goal> subGoals, Cursor subGoalsCursor) {
        GoalsAdapter adapter = new GoalsAdapter(context, subGoals, subGoalsCursor);
        final CarouselLayoutManager layoutManager = new CarouselLayoutManager(CarouselLayoutManager.VERTICAL, false);
        layoutManager.setPostLayoutListener((CarouselLayoutManager.PostLayoutListener) new CarouselZoomPostLayoutListener());
        subGoalsRecyclerView.setLayoutManager(layoutManager);
        subGoalsRecyclerView.setHasFixedSize(true);
        subGoalsRecyclerView.setAdapter(adapter);
    }

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

    public void swapCursor(Cursor newCursor) {
        if (cursor != null) {
            cursor.close();
        }

        cursor = newCursor;

        if (newCursor != null) {
            notifyDataSetChanged();
        }
    }
}

问题出在哪里?我应该如何解决它?

帮助将不胜感激

最佳答案

问题是 RecyclerView 在滚动过程中重用了 ViewHolders。例如,在位置 10 上,它可以使用位置 2 的 ViewHolder(假设该项目已展开),如果您不为位置 10 上的 ViewHolder 绑定(bind)展开/折叠状态,它将具有展开状态。因此,要解决问题,您必须跟踪 ViewHolder 状态并在每次调用 onBindViewHolder 方法时更新 ViewHolder。

这是与 RecyclerView 中的选择相关的一个很好的答案,对于展开/折叠状态,您将拥有几乎相同的逻辑。

https://stackoverflow.com/a/28838834/9169701

关于java - RecyclerView 执行项目点击,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59988440/

相关文章:

java - 更改 Android 上的启动 Activity

java - Web 应用程序托管网页和查询网页的逻辑应使用哪些技术

Android Studio Gradle 构建失败 - 要求不存在的 sdk 版本

android - 如何更改android studio中的默认主题?

Android SearchView 设置默认展开

java - 如何使用 sharedpreferences 保存计时器时间并在另一个 Activity 中检索它

java - 解析数据 Spring MVC

Android - 部分布局未显示

android - 将我的 res/raw 包中的 mp3 添加到 Android 的铃声列表中

Android 支持 v4 SwipeRefreshLayout 空 View 问题