Проблемы с добавлением настраиваемого макета в каждое представление Recycler - PullRequest
1 голос
/ 20 июня 2020

Я создаю приложение, в котором издатели загружают вопросы в базу данных. Издатели могут добавлять столько вопросов, сколько захотят, поэтому для этого я использовал режим ресайклера. Когда издатель нажимает кнопку, чтобы добавить вопрос, новый макет раздувается, как указано в моем адаптере 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, которая должна добавлять другое представление под уже существующими, все дочерние представления внутри уже существующих представлений очищаются. Пожалуйста, как лучше решить эту проблему?

each question is a recycler view here

вопросы 1 и 2 являются взглядами переработчиков

1 Ответ

2 голосов
/ 20 июня 2020

Ваш адаптер выполняет большую работу в onBindViewHolder(): настраивает множество прослушивателей кликов, которые, в свою очередь, переключают пользовательский интерфейс, чтобы пользователи могли вводить детали своего вопроса, не беспокоясь о элементах пользовательского интерфейса, которые им не нужны.

НО вы, похоже, нигде не отслеживаете выбор, сделанный пользователями для каждого вопроса. И каждый раз, когда пользователь добавляет новый вопрос, вы выбрасываете существующий адаптер:

topicQuestionsAdapter = new TopicQuestionsAdapter («Адаптер», getContext (), topicQuestionsList); addTopicOfTheDayWhereDynamicLayoutsWillBeAdded.setAdapter (topicQuestionsAdapter);

Поскольку вы не предоставили мне достаточно кода для отладки вашего приложения и тестирования моего решения, я просто набросаю несколько идей:

Вместо используя новый адаптер каждый раз, когда создается новый вопрос, просто добавьте вопрос в список и затем позвоните (обратите внимание: topicQuestionsList.size () - 1 )

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

Один другая вещь, которую вам нужно сделать, это отслеживать состояния каждого элемента списка (которые видны Button s et c., каково содержимое EditText s, если они есть ...). Если список становится длиннее и пользователям необходимо прокручивать, onBindViewHolder() будет вызываться повторно, даже если вы продолжите работать с тем же адаптером.

Итак, вам нужен класс - назовем его ListEntry - с полями для отражения возможных состояний элемента списка. А внутри адаптера вы можете сохранить List<ListEntry> с одним ListEntry для каждого элемента вашего списка данных. Каждый раз, когда какой-то Button становится видимым, вы обновляете соответствующий ListEntry. В onBindViewHolder() вы оцениваете ListEntry для данной позиции и соответственно устанавливаете атрибуты дочерних View s из holder.itemView.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...