简体   繁体   中英

How to change background color of center element using Snaphelper

I want to change the background color of the centered position element. I have used vertical snapHelper and my center element is also detected so I just want to add background color to the center element.

LinearSnapHelper snapHelper = new LinearSnapHelper() {

        @Override
        public int findTargetSnapPosition(RecyclerView.LayoutManager layoutManager, int velocityX, int velocityY) {
            View centerView = findSnapView(layoutManager);
            if (centerView == null)
                return RecyclerView.NO_POSITION;

            int position = layoutManager.getPosition(centerView);
            int targetPosition = -1;
            if (layoutManager.canScrollHorizontally()) {
                if (velocityX < 0) {
                    targetPosition = position - 1;

                } else {
                    targetPosition = position + 1;
                }
            }

            if (layoutManager.canScrollVertically()) {
                if (velocityY < 0) {
                    targetPosition = position - 1;
                } else {
                    targetPosition = position + 1;
                    centerView.getBackground().setColorFilter(Color.parseColor("#000000"), PorterDuff.Mode.DARKEN);
                }
            }

            final int firstItem = 0;
            final int lastItem = layoutManager.getItemCount() - 1;
            targetPosition = Math.min(lastItem, Math.max(targetPosition, firstItem));
            return targetPosition;
        }
    };

}

You can register scroll listener to the RecyclerView , and when the scroll is over (ie it's in SCROLL_STATE_IDLE state); the snapHelper.findSnapView() shouldn't return a null value; so you can set its color.

final LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
    @Override
    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);

        // Detect scroll end
        if (newState == RecyclerView.SCROLL_STATE_IDLE) {

            // Resetting all the loaded items to the default color 
            int firstVisibleItemPosition =
                    layoutManager.findFirstVisibleItemPosition();
            int lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition();
            for (int i = firstVisibleItemPosition; i <= lastVisibleItemPosition; i++) {
                RecyclerView.ViewHolder holder = recyclerView.findViewHolderForAdapterPosition(i);
                // Rest to the default color of other loaded items
                holder.itemView.setBackgroundColor(ResourcesCompat.getColor(getResources(), R.color.defaultColor, null));
            }

            // Changing the background of the snaphelper centered item
            View centerView = snapHelper.findSnapView(layoutManager);
            if (centerView != null)
                centerView.setBackgroundColor(ResourcesCompat.getColor(getResources(), R.color.centerColor, null));
        }

    }
});

Kotlin:

val layoutManager = recyclerView.layoutManager as LinearLayoutManager
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
    override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
        super.onScrollStateChanged(recyclerView, newState)
        
        // Detect scroll end
        if (newState == RecyclerView.SCROLL_STATE_IDLE) {
            val firstVisibleItemPosition =
                layoutManager.findFirstVisibleItemPosition()
            val lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition()
            for (i in firstVisibleItemPosition..lastVisibleItemPosition) {
                val holder =
                    recyclerView.findViewHolderForAdapterPosition(i) 

                // Resetting all the loaded items to the default color 
                 holder!!.itemView!!.setBackgroundColor(ResourcesCompat.getColor(resources, R.color.defaultColor, null))
            }

            // Changing the background of the snaphelper centered item
            val centerView: View? = snapHelper.findSnapView(layoutManager)
            centerView.setBackgroundColor(ResourcesCompat.getColor(resources, R.color.centerColor, null))

        }

    }
})

UPDATE:

There is a better approach than iterating over all the RV loaded items, to reset to the default color; by just saving the previous centeredView into a local field, and update its color instead of updating the entire loaded items:

View previousCenteredView;
final LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
    @Override
    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);

        // Detect scroll end
        if (newState == RecyclerView.SCROLL_STATE_IDLE) {

            // Changing the background of the snaphelper centered item
            View centerView = snapHelper.findSnapView(layoutManager);
            previousCenteredView = centerView;
            
            if (centerView != null)
                centerView.setBackgroundColor(ResourcesCompat.getColor(getResources(), R.color.centerColor, null));

        } else if (previousCenteredView != null){
            // Resetting previous centered view to the default color 
            previousCenteredView.setBackgroundColor(ResourcesCompat.getColor(getResources(), R.color.defaultColor, null));
            previousCenteredView = null;
        }

    }
});

Kotlin:

var previousCenteredView: View? = null
val layoutManager = recyclerView.layoutManager as LinearLayoutManager
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
    override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
        super.onScrollStateChanged(recyclerView, newState)
        
        // Detect scroll end
        if (newState == RecyclerView.SCROLL_STATE_IDLE) {

            // Changing the background of the snaphelper centered item
            val centerView: View? = snapHelper.findSnapView(layoutManager)
            previousCenteredView = centerView
            centerView.setBackgroundColor(ResourcesCompat.getColor(resources, R.color.centerColor, null))
            
        } else if (previousCenteredView != null){
            // Resetting previous centered view to the default color 
            previousCenteredView.setBackgroundColor(ResourcesCompat.getColor(resources, R.color.defaultColor, null))
            previousCenteredView = null
        }


    }
})

for setting background color of a view, you can use various methods check this

based on you code you are setting the background color of the view but only inside the if statement, so try extracting the line to be after the if .

...
if (layoutManager.canScrollVertically()) {
      if (velocityY < 0) {
            targetPosition = position - 1;
      } else {
            targetPosition = position + 1;
      }
}

centerView.getBackground().setColorFilter(Color.parseColor("#000000"), PorterDuff.Mode.DARKEN);

final int firstItem = 0;
final int lastItem = layoutManager.getItemCount() - 1;
targetPosition = Math.min(lastItem, Math.max(targetPosition, firstItem));
return targetPosition;
...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM