9

I am using a recyclerView inside my navigation drawer and I am using this library Twoway-view to get click and selection support.

It works perfectly and I can change the color of the text and the icons without problems inside OnClick method for each position:

itemClickSupport.setOnItemClickListener(new ItemClickSupport.OnItemClickListener() {
        @Override
        public void onItemClick(RecyclerView parent, View view, int position, long id) {
            TypedValue typedValue = new TypedValue();
            MainActivity.this.getTheme().resolveAttribute(R.attr.colorAccent, typedValue, true);
            final int color = typedValue.data;

            //TODO Icon and text colors

            for (int i = 0; i < drawerTitles.length; i++){
                if (i == position){
                    ImageView imageViewDrawerIcon = (ImageView) recyclerViewDrawer.getChildAt(i).findViewById(R.id.imageViewDrawerIcon);
                    TextView textViewDrawerTitle = (TextView) recyclerViewDrawer.getChildAt(i).findViewById(R.id.textViewDrawerItemTitle);
                    imageViewDrawerIcon.setColorFilter(color);
                    if(Build.VERSION.SDK_INT > 15){
                        imageViewDrawerIcon.setImageAlpha(255);
                    }else{
                        imageViewDrawerIcon.setAlpha(255);
                    }
                    textViewDrawerTitle.setTextColor(color);
                    RelativeLayout relativeLayoutDrawerItem = (RelativeLayout) recyclerViewDrawer.getChildAt(i).findViewById(R.id.relativeLayoutDrawerItem);
                    relativeLayoutDrawerItem.setFocusableInTouchMode(true);
                }else{
                    ImageView imageViewDrawerIcon = (ImageView) recyclerViewDrawer.getChildAt(i).findViewById(R.id.imageViewDrawerIcon);
                    TextView textViewDrawerTitle = (TextView) recyclerViewDrawer.getChildAt(i).findViewById(R.id.textViewDrawerItemTitle);
                    imageViewDrawerIcon.setColorFilter(getResources().getColor(R.color.md_text));
                    if(Build.VERSION.SDK_INT > 15){
                        imageViewDrawerIcon.setImageAlpha(138);
                    }else{
                        imageViewDrawerIcon.setAlpha(138);
                    }
                    textViewDrawerTitle.setTextColor(getResources().getColor(R.color.md_text));
                    RelativeLayout relativeLayoutDrawerItem = (RelativeLayout) recyclerViewDrawer.getChildAt(i).findViewById(R.id.relativeLayoutDrawerItem);
                    relativeLayoutDrawerItem.setFocusableInTouchMode(false);
                }
            }

            //TODO Fragments (closedrawers before setfragment)
            final Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    // Do something after some time

                }
            }, 250);
            mDrawerLayout.closeDrawers();
        }
    });

The problem is that I want to access to the first item like in that method, but before it (to set the first item selected, with different color, etc).

But I get a crash (null reference) when I try to get the first item outside OnClick method:

ImageView imageViewDrawerIcon = (ImageView) recyclerViewDrawer.getChildAt(0).findViewById(R.id.imageViewDrawerIcon);

All code:

// Setup RecyclerView inside drawer
    recyclerViewDrawer = (RecyclerView) findViewById(R.id.recyclerViewDrawer);
    recyclerViewDrawer.setHasFixedSize(true);
    recyclerViewDrawer.setLayoutManager(new LinearLayoutManager(MainActivity.this));

    ArrayList<DrawerItem> drawerItems = new ArrayList<>();
    final String[] drawerTitles = getResources().getStringArray(R.array.drawer);
    final TypedArray drawerIcons = getResources().obtainTypedArray(R.array.drawerIcons);
    for (int i = 0; i < drawerTitles.length; i++) {
        drawerItems.add(new DrawerItem(drawerTitles[i], drawerIcons.getDrawable(i)));
    }
    drawerIcons.recycle();
    adapterDrawer = new DrawerAdapter(drawerItems);
    recyclerViewDrawer.setAdapter(adapterDrawer);

    // Here is the problem
    ImageView imageViewDrawerIcon2 = (ImageView) recyclerViewDrawer.getChildAt(0).findViewById(R.id.imageViewDrawerIcon);

    // RecyclerView item listener.
    ItemClickSupport itemClickSupport = ItemClickSupport.addTo(recyclerViewDrawer);
    itemClickSupport.setOnItemClickListener(new ItemClickSupport.OnItemClickListener() {
        @Override
        public void onItemClick(RecyclerView parent, View view, int position, long id) {
            TypedValue typedValue = new TypedValue();
            MainActivity.this.getTheme().resolveAttribute(R.attr.colorAccent, typedValue, true);
            final int color = typedValue.data;

            //TODO Icon and text colors

            for (int i = 0; i < drawerTitles.length; i++){
                if (i == position){
                    ImageView imageViewDrawerIcon = (ImageView) recyclerViewDrawer.getChildAt(i).findViewById(R.id.imageViewDrawerIcon);
                    TextView textViewDrawerTitle = (TextView) recyclerViewDrawer.getChildAt(i).findViewById(R.id.textViewDrawerItemTitle);
                    imageViewDrawerIcon.setColorFilter(color);
                    if(Build.VERSION.SDK_INT > 15){
                        imageViewDrawerIcon.setImageAlpha(255);
                    }else{
                        imageViewDrawerIcon.setAlpha(255);
                    }
                    textViewDrawerTitle.setTextColor(color);
                    RelativeLayout relativeLayoutDrawerItem = (RelativeLayout) recyclerViewDrawer.getChildAt(i).findViewById(R.id.relativeLayoutDrawerItem);
                    relativeLayoutDrawerItem.setFocusableInTouchMode(true);
                }else{
                    ImageView imageViewDrawerIcon = (ImageView) recyclerViewDrawer.getChildAt(i).findViewById(R.id.imageViewDrawerIcon);
                    TextView textViewDrawerTitle = (TextView) recyclerViewDrawer.getChildAt(i).findViewById(R.id.textViewDrawerItemTitle);
                    imageViewDrawerIcon.setColorFilter(getResources().getColor(R.color.md_text));
                    if(Build.VERSION.SDK_INT > 15){
                        imageViewDrawerIcon.setImageAlpha(138);
                    }else{
                        imageViewDrawerIcon.setAlpha(138);
                    }
                    textViewDrawerTitle.setTextColor(getResources().getColor(R.color.md_text));
                    RelativeLayout relativeLayoutDrawerItem = (RelativeLayout) recyclerViewDrawer.getChildAt(i).findViewById(R.id.relativeLayoutDrawerItem);
                    relativeLayoutDrawerItem.setFocusableInTouchMode(false);
                }
            }

            //TODO Fragments (closedrawers before setfragment)
            final Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    // Do something after some time

                }
            }, 250);
            mDrawerLayout.closeDrawers();
        }
    });
Dave Schweisguth
  • 36,475
  • 10
  • 98
  • 121
JavierSegoviaCordoba
  • 6,531
  • 9
  • 37
  • 51
  • 1
    Possible duplicate of [RecyclerView - Get view at particular position](https://stackoverflow.com/questions/33784369/recyclerview-get-view-at-particular-position) – Kaibo Nov 01 '19 at 12:58

6 Answers6

20

In my case it,is work like a charm

View viewItem = recycleView.getLayoutManager().findViewByPosition(position);
    View icon = viewItem.findViewById(R.id.view);
Dmitriy
  • 346
  • 4
  • 8
  • Gives warning "Before Android 4.1, method int android.support.v7.widget.ListViewCompat.lookForSelectablePosition(int, boolean) would have incorrectly overridden the package-private method in android.widget.ListView" – Patriotic Jun 03 '18 at 18:01
  • 4
    it returns `null` – user25 Mar 17 '19 at 22:21
  • Seems it works only if item is visible right now, useless. Even if I call `layoutManager.scrollToPosition(position)` before calling `findViewByPosition(position)` it still doesn't work – user25 Mar 17 '19 at 22:22
9

I solved finally with this (source):

recyclerViewDrawer.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            ImageView imageViewDrawerIcon = (ImageView) recyclerViewDrawer.getChildAt(0).findViewById(R.id.imageViewDrawerIcon);
            TextView textViewDrawerTitle = (TextView) recyclerViewDrawer.getChildAt(0).findViewById(R.id.textViewDrawerItemTitle);
            imageViewDrawerIcon.setColorFilter(color);
            if (Build.VERSION.SDK_INT > 15) {
                imageViewDrawerIcon.setImageAlpha(255);
            } else {
                imageViewDrawerIcon.setAlpha(255);
            }
            textViewDrawerTitle.setTextColor(color);
            RelativeLayout relativeLayoutDrawerItem = (RelativeLayout) recyclerViewDrawer.getChildAt(0).findViewById(R.id.relativeLayoutDrawerItem);
            relativeLayoutDrawerItem.setFocusableInTouchMode(true);
            // unregister listener (this is important)
            recyclerViewDrawer.getViewTreeObserver().removeGlobalOnLayoutListener(this);
        }
    });

By the way, if someone have a better solution I would like to know it.

Community
  • 1
  • 1
JavierSegoviaCordoba
  • 6,531
  • 9
  • 37
  • 51
  • We're still getting some instances of `getChildViiew(0)` being null with this approach. I personally can't reproduce it. Using `setAdapter` triggers the child view inflation so ideally there would be a callback that is called when the child view is inflated and added to the RecyclerView – ono Jul 25 '16 at 18:18
8

This worked for me.

recyclerView.post(new Runnable() {
  @Override
  public void run() {
    View viewItem = recycleView.getLayoutManager().findViewByPosition(position);
    View icon = viewItem.findViewById(R.id.view);
  }
});
Hermandroid
  • 2,120
  • 4
  • 29
  • 35
  • Nice, this worked perfectly for getting the displayed children and viewholders using `getChildAt()` and `getChildViewHolder()` – Peterdk Apr 10 '19 at 11:42
  • Of note is that you can't manipulate many UI elements with this, since you're working from a different thread. You'll have to set up inter-thread communication. – Kilves May 08 '19 at 12:09
5

I would use findViewHolderForAdapterPosition() or findViewByPosition() instead to find the root view at that index. The way you ensure the data is loaded is up to you, however.

AllDayAmazing
  • 2,383
  • 1
  • 24
  • 25
1

findViewByPosition is a method of LayoutManager, which works with all LayoutManagers.

So you can use recycleView.getLayoutManager() and findViewByPosition(pos).

Also recyclerView.findViewHolderForAdapterPosition(pos) works too.

For more information, look at this RecyclerView - Get view at particular position

Kaibo
  • 111
  • 1
  • 4
0

You can get ItemView from recyclerView's holder using below code:

val holder = yourRecyclerView.findViewHolderForAdapterPosition(position)
if (holder != null) {
  val rootView = holder.itemView
  //do your code here
}
Anant Shah
  • 3,744
  • 1
  • 35
  • 48