0

I have a RecyclerView and clicking its item takes to a new Activity. There is a ViewPager with multiple items. On pressing back, I am saving the current item position. What I want to do is when a user presses back while standing on any item in a ViewPager, that item should be highlighted in RecyclerView.

PROBLEM

When item's position is visible, there's no problem. I change background by using following

view = layoutManager.findViewByPosition(Utils.ayat);
if(view != null) {
    LinearLayout parent = (LinearLayout) view.findViewById(R.id.parent);
    parent.setBackgroundColor(Color.GRAY);
}

But if item is not visible, nothing happened and I am not able to change background.

WHAT I'VE DONE SO FAR

  1. Tried to scroll to a position and then change background. RecyclerView is scrolling correctly but findViewByPosition returns null.
  2. I believe from my observations (may be it's wrong) that on programmatically scrolling RecyclerView, the position to which it's been scrolled will be it's last visible item. I tried to do that but with no luck.
  3. As suggested by many, put Thread.sleep(100) and then tried to get position. This didn't work too.

NOTE: I can't do this onBindViewHolder because items to be highlighted are not pre-defined.

Waqas Ahmed Ansari
  • 1,590
  • 13
  • 28

3 Answers3

1

Instead of changing the background color imperatively when returning to the list, you should store a list of highlighted item (indices) and in onBindViewHolder(...) check if the item is highlighted or not, and update its background accordingly (remember to also clear the background when item not highlighted).

This is generally how you should always do with RecyclerView.

etan
  • 473
  • 4
  • 14
  • Indices are not pre-defined, I can't do this. – Waqas Ahmed Ansari Apr 04 '17 at 12:21
  • There's always some reason why you're highlighting a particular row. Highlighting that row, either by index or some data property, is row modification. As said in ©Palanivelraghul's solution, use `notifyItemChanged()` for your item once you want to highlight it. Best to never assume anything else on the internal layout of RecyclerView, there's no guarantee for child positions matching what you see etc. – etan Apr 04 '17 at 13:58
  • The problem is when I try to get a `View` which is not currently visible, it returns `null`. So, when do I call `notifyItemChanged()`? – Waqas Ahmed Ansari Apr 05 '17 at 04:05
  • You shouldn't try to get a view - simply call `notifyItemChanged()` during `onActivityResult()`. Instead of thinking that you need to modify views, you need to modify data that is being displayed, and let `RecyclerView` do the work for you. – etan Apr 05 '17 at 08:04
  • Sorry brother, I can't understand what you are trying to say. I don't need to modify data, I need to modify view. Let's imagine, if I get data at particular position of `RecyclerView`, what will I do with that? I need to change background, not value – Waqas Ahmed Ansari Apr 05 '17 at 08:45
  • Some item being highlighted is application state, so regardless of how you want to store this (e.g. `int highlightedItemIndex`), or item property, it's still stored as a state. Then you use this state when you update an item, to set its background accordingly. I recommend thinking all the logic you have as display state changes instead of view modifications. – etan Apr 05 '17 at 08:59
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/139942/discussion-between-waqas-ahmed-ansari-and-etan). – Waqas Ahmed Ansari Apr 05 '17 at 09:05
0

Have you tried notifyItemChanged(int position)? You can send the highlighted item position to the adapter through a method and call notifyItemChanged(int position). For example,

int highlightPosition = -1;

    public updateHighlightPosition(int position){
      highlightPosition = position;
      notifyItemChanged(position)
    }

    @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
      if(position == highlightPosition ){
         // You can change the background here
      }else{
        // Set default background
      }
  }
CodeCameo
  • 3,208
  • 4
  • 18
  • 24
  • you cannot call updatehighlights method while RecyclerView is computing a layout or scrolling also it should be void, and update it inside if else block. so many wrong things here – Ege Kuzubasioglu Feb 20 '18 at 09:15
0

Try to use RecyclerView.AdapterDataObserver class by calling method of notifyItemChanged(position);

Whenever you are calling notifyItemChanged() method with certain position, it will call AdapterDataObserver class. So, First you need to paste my code what i given below inside to your adapter class. check my example, you will get some idea to achieve your requirement.

RecyclerView.AdapterDataObserver adapterDataObserver = new RecyclerView.AdapterDataObserver() {
    @Override
    public void onItemRangeChanged(int positionStart, int itemCount) {
        super.onItemRangeChanged(positionStart, itemCount);
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                LinearLayoutManager manager = (LinearLayoutManager) recyclerView.getLayoutManager();
                manager.scrollToPositionWithOffset(positionStart, 0);
                RecyclerView.ViewHolder rebindViewHolder = recyclerView.findViewHolderForLayoutPosition(positionStart);
                if (rebindViewHolder != null) {
                    onBindViewHolder((ViewHolder) rebindViewHolder, positionStart);
                }
            }
        }, 1000);
    }
};

afterdoing this, in onBindViewHolder method change the background using position. I think this will helps you.

Palanivelraghul
  • 1,941
  • 2
  • 12
  • 21
  • It's written in the question that indices are not pre-defined, it can't be done inside `onBindViewHolder` – Waqas Ahmed Ansari Apr 04 '17 at 12:48
  • @WaqasAhmedAnsari sorry dude. I am not understood "But if item is not visible, nothing happened and I am not able to change background." – Palanivelraghul Apr 05 '17 at 06:13
  • @WaqasAhmedAnsari you said that you already stored that position. so while coming back use that position and refresh the recyclerview using notifyItemChanged(viewedItemPosition). – Palanivelraghul Apr 05 '17 at 06:14
  • When I tap on item, it takes me to other `Activity` which has `ViewPager` with multiple items (which are actually in `RecyclerView`). I start reading in new activity and reach to another page and press back. Now I have new `position` which is not visible in `RecyclerView`. This is the case – Waqas Ahmed Ansari Apr 05 '17 at 06:45
  • @WaqasAhmedAnsari you want to use post delay to scroll to that position. then by call onBindViewHolder you can change the background for particular item in recyclerview – Palanivelraghul Apr 05 '17 at 10:50