首页 > 解决方案 > 在每个 Recycler 视图中添加自定义布局的问题

问题描述

我正在构建一个应用程序,发布者将问题上传到数据库。发布者可以添加他们想要的任意数量的问题,所以我使用了回收站视图来处理这个问题。当发布者单击按钮添加问题时,新布局将按照我的 recyclerview 适配器中的指定进行膨胀。TopicQuestionsAdapter 是我的回收器视图适配器的名称

                             ...

RecyclerView addTopicOfTheDayWhereDynamicLayoutsWillBeAdded;
TopicQuestionsAdapter topicQuestionsAdapter;
ArrayList<TopicQuestions> topicQuestionsList;

addTopicOfTheDayWhereDynamicLayoutsWillBeAdded.setHasFixedSize(true);
addTopicOfTheDayWhereDynamicLayoutsWillBeAdded.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false));
topicQuestionsList = new ArrayList<>();

                              ...

addTopicOfTheDayAddQuiz.setOnClickListener(v29 -> {

                              ...

            // dynamically add questions layout on subsequent clicks
            // here with an x button in each layout to remove the
            // entire question layout

            topicQuestionsList.add(new TopicQuestions());
            topicQuestionsAdapter = new TopicQuestionsAdapter("Adapter", getContext(), topicQuestionsList);
            addTopicOfTheDayWhereDynamicLayoutsWillBeAdded.setAdapter(topicQuestionsAdapter);
            topicQuestionsAdapter.notifyItemInserted(topicQuestionsList.size());

        }
    });

现在回收站视图布局由四个 FAB 组成,用于添加不同类型的问题和选项,一个文本视图和一个图像按钮用于删除整个视图

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TopicQuestionsViewHolder {
//R.layout.add_question_layout is the layout
    val itemView = LayoutInflater.from(parent.context).inflate(R.layout.add_question_layout, parent, false)
    return TopicQuestionsViewHolder(itemView)
}

/*this is where my problem is i observed that whenever i
    add a new question, the layouts i had already added to previous
    views get cleared. Recycler view destroys states*/

 override fun onBindViewHolder(holder: TopicQuestionsViewHolder, position: Int) {
    
    // the textview to show this question number
    holder.questionNumber.text = "${position + 1}."

    // the image button to remove the whole view
    holder.removeQuestion.setOnClickListener {
        topicQuestions.removeAt(position)
        notifyItemRemoved(position)
        notifyItemRangeChanged(position, topicQuestions.size)
    }

    holder.addField.setOnClickListener {
        // need to fix this
        when (holder.theFields.visibility == View.GONE) {
            true -> {
                holder.theFields.visibility = View.VISIBLE
                holder.addField.setImageResource(R.drawable.close)
                Log.wtf(TAG, "true")
            }
            false -> {
                holder.theFields.visibility = View.GONE
                holder.addField.setImageResource(R.drawable.add)
                Log.wtf(TAG, "false")
            }
        }
    }

    // this button would add a question field to this view
    holder.addQuestionField.setOnClickListener {
        val lParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
        lParams.topMargin = 16
        val view = LayoutInflater.from(ctx).inflate(R.layout.add_question_field_to_question_layout, null)
        view.layoutParams = lParams
        holder.toAddViews.addView(view)
    }

    // this button would add an image question field to this view
    holder.addImageQuestionField.setOnClickListener {
        Log.wtf(TAG, "image question will be added here")
    }

    // this button would add toggle option to this view
    holder.addToggleOption.setOnClickListener {
        Log.wtf(TAG, "toggle option will be added here")
    }

    // this button would add check box option to this view
    holder.addCheckBoxOption.setOnClickListener {
        Log.wtf(TAG, "check box option will be added here")
    }
}

正如我之前在代码中所暗示的那样,每当我单击 addTopicOfTheDayAddQuiz 按钮时,该按钮应该在已经退出的视图下方添加另一个视图,现有视图中的所有子视图都将被清除。请问有什么更好的方法来解决这个问题?

每个问题都是这里的回收者视图

问题 1 和 2 是回收者的观点

标签: javaandroidkotlinandroid-recyclerview

解决方案


您的适配器在以下方面做了很多工作onBindViewHolder():设置大量点击侦听器,这些侦听器依次切换 UI,以便用户可以输入他们的问题详细信息,而不会被他们不需要的 UI 元素打扰。

但是您似乎没有跟踪用户为每个问题所做的选择。并且每次用户添加新问题时,您都会丢弃现有的适配器:

topicQuestionsAdapter = new TopicQuestionsAdapter("Adapter", getContext(), topicQuestionsList); addTopicOfTheDayWhereDynamicLayoutsWillBeAdded.setAdapter(topicQuestionsAdapter);

由于您没有为我共享足够的代码来调试您的应用程序和测试我的解决方案,我将简要介绍一些想法:

而不是每次创建新问题时都使用新适配器,只需将问题添加到列表中,然后调用(请注意:topicQuestionsList.size() - 1

topicQuestionsAdapter.notifyItemInserted(topicQuestionsList.size() - 1);

您需要做的另一件事是跟踪每个列表项的状态(哪些Buttons 等是可见的,如果有的话,s 的内容EditText是什么......)。如果列表变长并且用户需要滚动,onBindViewHolder()即使您继续使用同一个适配器,也会重复调用。

所以你需要一个类——让我们称之为ListEntry——带有反映列表项可能状态的字段。在适配器内部,您可以为数据列表的每个项目保留List<ListEntry>一个ListEntry。每次一些Button变得可见时,您都会更新相应的ListEntry. 在onBindViewHolder()您评估ListEntry给定位置的 s 并相应地设置 child Views 的属性holder.itemView


推荐阅读