【问题标题】:RecyclerView SnapHelper - how to change background of snapped and unsnapped items?RecyclerView SnapHelper - 如何更改已捕捉和未捕捉项目的背景?
【发布时间】:2018-10-21 18:08:35
【问题描述】:

我正在使用带有水平 LinearLayoutManager 的 recyclerview。当项目在中间被捕捉时,我想更改 recyclerview 项目的颜色。

所以我使用了 LinearSnapHelper。

目前,之前捕捉的每个项目都保留捕捉的背景颜色。所以我做了什么,我创建了全局变量 snappedPosition 并将其设置为 0,所以 recyclerview 的第一项将默认被捕捉。

然后,我在适配器的 onBindViewHolder 中调用了 snappedPosition,并将 recyclerview 中的每个项目的项目颜色更改为默认值,除了与被捕捉项目位置相同的项目。但是在 notifyItemChanged(position) 我得到了:

java.lang.IllegalStateException: RecyclerView 正在计算布局或滚动时无法调用此方法 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)
                }

            }

我想要实现的类似于此图像示例:

更新:颜色变化变体的代码示例(仍然不起作用):

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()会怎样?
  • recyclerview 的第一个项目是永久的,带有捕捉的背景,其他项目是默认的。
  • 为什么不改变滚动监听器的颜色呢?您知道那里的捕捉位置,您可以避免在视图持有者绑定中进行更改。
  • 试过这个,但是在第二个项目之后我得到了 java.lang.IllegalStateException: addressRecyclerView.find...rForAdapterPosition(item) must not be null - 代码在上面
  • 你不能在滚动监听器中只做centerView .setBackgroundResource(R.drawable.payment_button_active) 吗?这不行吗?

标签: android android-recyclerview kotlin


【解决方案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) {
        }
    });

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多