java之RecyclerView 执行项目点击

insus 阅读:43 2025-02-15 21:57:57 评论:0

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

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

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

这是RecyclerView :



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



这是我的适配器类:

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
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

关注我们

一个IT知识分享的公众号