RecyclerView SnapHelper - как изменить фон привязанных и не привязанных элементов?

Я использую recyclerview с горизонтальным LinearLayoutManager. Я хочу изменить цвет элемента recyclerview, когда элемент привязан к середине.

Итак, я использовал LinearSnapHelper.

На данный момент каждый элемент, который был ранее привязан, остается с привязанным цветом фона. Итак, что я сделал, я сделал глобальную переменную snappedPosition и установил ее в 0, поэтому первый элемент recyclerview будет привязан по умолчанию.

Затем я вызвал это snappedPosition в onBindViewHolder своего адаптера и изменил цвет элемента на значение по умолчанию для каждого элемента в recyclerview, кроме одного с той же позицией, что и положение привязанного элемента. Но в notifyItemChanged (position) я получил:

java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling android.support.v7.widget.RecyclerView

код внутри фрагмента:

val snapHelper: LinearSnapHelper = LinearSnapHelper()
var snappedPosition: Int = 0

        addressRecyclerView = view.findViewById<RecyclerView>(R.id.address_recycler_view).apply {

            setHasFixedSize(true)
            layoutManager = viewManager
            adapter = viewAdapter

        }

        snapHelper.attachToRecyclerView(addressRecyclerView)
        addressRecyclerView.onFlingListener = snapHelper
        itemOffsetDecoration = ItemOffsetDecoration(context, R.dimen.address_recyclerview_padding)
        addressRecyclerView.addItemDecoration(itemOffsetDecoration)

        addressRecyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
            override fun onScrollStateChanged(recyclerView: RecyclerView?, newState: Int) {
                if (newState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE) {
                    val centerView = snapHelper.findSnapView(viewManager)
                    if (centerView != null) {

                        snappedPosition = addressRecyclerView.getChildAdapterPosition(centerView)
                    }
                }
            }
        })

код внутри onBindViewHolder

addressList[position].let {


                if (position == fragment.snappedPosition){
                    holder.itemViewLayout.setBackgroundResource(R.drawable.payment_button_active)
                    notifyItemChanged(position)
                } else {
                    holder.itemViewLayout.setBackgroundResource(R.drawable.payment_button_inactive)
                    notifyItemChanged(position)
                }

            }

То, что я хочу достичь, похоже на этот пример изображения:

RecyclerView SnapHelper - как изменить фон привязанных и не привязанных элементов?

Обновление: пример кода для варианта изменения цвета (все еще не работает):

addressRecyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
            override fun onScrollStateChanged(recyclerView: RecyclerView?, newState: Int) {
                if (newState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE) {
                    val centerView = snapHelper.findSnapView(addressRecyclerView.layoutManager)
                    if (centerView != null) {
                        for(item in 0 until addressRecyclerView.layoutManager.childCount){
                            val holder: RecyclerView.ViewHolder = addressRecyclerView.findViewHolderForAdapterPosition(item)
                            holder.itemView.setBackgroundResource(R.drawable.payment_button_inactive)
                        }
                        centerView.setBackgroundResource(R.drawable.payment_button_active)

                    }
                }
            }
        })

Что произойдет, если вы просто не позвоните notifyItemChanged()?

Cheticamp 11.05.2018 14:46

Первый элемент recyclerview постоянно с привязанным фоном, а другие элементы - со значением по умолчанию.

martin1337 11.05.2018 14:54

Почему бы вам не изменить цвет в слушателе прокрутки? Вы знаете положение привязки и можете избежать изменения привязки держателя вида.

Cheticamp 11.05.2018 15:10

Пробовал это, но после второго элемента ive получил java.lang.IllegalStateException: addressRecyclerView.find… rForAdapterPosition (item) не должен быть нулевым - код указан выше

martin1337 11.05.2018 15:38

Вы не можете просто сделать centerView .setBackgroundResource(R.drawable.payment_button_active) в слушателе прокрутки? Это не работает?

Cheticamp 11.05.2018 15:42

это так работает. Но я должен установить ранее выбранный цвет фона по умолчанию. Если я просто сделаю centerView.setbackgroundResource (active), как вы сказали, он изменит цвет каждого recyclerviewItem, который будет привязан к центру экрана при прокрутке. Если вы прокрутите и пролистаете каждый из элементов recyclerview. весь recyclerview заканчивается выбранным фоном

martin1337 11.05.2018 15:51
1
6
1 784
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Попробуйте следующее, чтобы отследить текущий вид с привязкой, установить соответствующий фон и очистить его при перемещении RecyclerView. Это позволяет избежать модификации адаптера.

    mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
            if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                View view = mSnapHelper.findSnapView(recyclerView.getLayoutManager());
                view.setBackgroundColor(getResources().getColor(android.R.color.holo_green_light));
                mLastSnappedView = view;
            } else if (mLastSnappedView != null) {
                mLastSnappedView.setBackgroundColor(getResources().getColor(android.R.color.white));
                mLastSnappedView = null;
            }
        }

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        }
    });

Другие вопросы по теме