1

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;
        }
    };

}
Zain
  • 37,492
  • 7
  • 60
  • 84
pratival
  • 111
  • 8

2 Answers2

1

You can register scroll listener to the RecyclerView, and when the scroll is over (i.e. 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
        }


    }
})
Zain
  • 37,492
  • 7
  • 60
  • 84
  • How can I use this in when user is scrolling the rv. Because when I put it in OnScrolled method it is not working. – BlackBlind May 02 '23 at 12:06
0

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;
...
medyas
  • 1,166
  • 13
  • 21
  • Application crashed when i used it generating null reference exception – pratival Feb 10 '19 at 11:45
  • So i tried centerView.setBackgroundColor(getResources().getColor(R.color.colorPrimaryDark)) instead of that its working fine and how to remove that background color when element is not at center? – pratival Feb 10 '19 at 12:07
  • you can set it's background to another color or transparent – medyas Feb 10 '19 at 12:09