28

I am trying to get child view by position. I could get view when one item is clicked:

rvSellRecords.addOnItemTouchListener(new RecyclerItemClickListener(getActivity(), new RecyclerItemClickListener.OnItemClickListener() {
        @Override
        public void onItemClick(View view, int position) {
            ((MainActivity) getActivity()).showSellRecordFragment(position, view);
        }
    }));

Now I cannot get child view, without click - let's say by position for example:

rvSellRecords.someMagicalMethodWhichReturnsViewByPosition(5);

Question: How to get child view from RecyclerView?

EDIT FOR BOUNTY:

enter image description here

I have RecyclerView to show products list. When I click on it, I am adding new Fragment where I show product information. While opening I am updating toolbar with view from RecyclerView - this is working perfectly:

    rvSellRecords.addOnItemTouchListener(new RecyclerItemClickListener(getContext(), new RecyclerItemClickListener.OnItemClickListener() {
                    @Override
                    public void onItemClick(View view, int position) {
                        sellPresenter.onSellRecordSelected(position, view);
                    }
                }));

    When I click blue button with "+", I am incrementing quantity by 1.





    public void onIncrementButtonClicked(){
                sellRecord.setCount(sellRecord.getCount() + 1);
                showQuantity();
                bus.post(new SellRecordChangedEvent(sellRecord, sellRecordPosition));
                }

Then I am posting updated sellRecord to first fragment using EventBus. There I am updating list data. I supposed that updating value(sell) automatically updates adapter. Now I am getting view from adapter using custom method(getView) which was created by me(you can find it below).



 @Subscribe
public void onEvent(SellRecordChangedEvent event){
    sell.getSellRecords().set(event.getSellRecordPosition(), event.getSellRecord());
    sell.recalculate();
    int position = event.getSellRecordPosition();
    View view = adapter.getView(position);
    bus.post(new TransactionTitleChangedEvent(null, view));
}

This is my adapter class - I changed adapter little bit to collect view in list and added method which returns view for respective position:



public class SellRecordsAdapter extends RecyclerView.Adapter<SellRecordsAdapter.ViewHolder> {

    .....
    .....
    .....
    List<View> viewList;

    public SellRecordsAdapter(List<SellRecord> sellRecordList) {

        .....

        viewList = new ArrayList<>();
    }

    .....
    .....
    .....

    @Override
    public void onBindViewHolder(ViewHolder viewHolder, int i) {

        .....
        .....
        .....

        viewList.add(i, viewHolder.itemView);

    }


    public View getView(int position){
        return viewList.get(position);
    }

}

My problem: when I updating view in toolbar, I am getting old view. When quantity is 3, I am getting view with 2. When quantity 10 - view is with 9.

My question: how to get view from recycler view using position of item(without on click listener)?

enter image description here

V-rund Puro-hit
  • 5,518
  • 9
  • 31
  • 50
Joe Richard
  • 1,520
  • 7
  • 20
  • 31
  • why you minusing me? – Joe Richard Feb 16 '16 at 09:36
  • U want to get child view without clicking ?? – Manishika Feb 16 '16 at 09:39
  • yes, i want to get view without clicking - using position – Joe Richard Feb 16 '16 at 09:39
  • So the recyclerview and your product information are in 2 different fragments yes? You are expecting the recyclerview's views to update when they are not even in foreground? also you are changing adapter data item's data at position `event.getSellRecordPosition()` , but you are not notifying the adapter that its dataset changed, either by `adapter.notifyDataSetChanged()` or the other `notifyItemChanged(position)` methods – Bhargav Mar 01 '16 at 05:45
  • Possible repeat of this question: https://stackoverflow.com/questions/33784369/recyclerview-get-view-at-particular-position/38640656?noredirect=1#comment88164994_38640656 – SMBiggs May 31 '18 at 00:03

12 Answers12

40

Use recyclerView.findViewHolderForLayoutPosition(position) or reyclerView.findViewHolderForAdapterPosition(position) to get the viewholder for postion. Then you can access any child from your viewholder.

Checkout Recyclerview

Ravi Theja
  • 3,371
  • 1
  • 22
  • 34
9
RecyclerView.ViewHolder holder = recycleView.findViewHolderForAdapterPosition(position);
ImageView imageView = holder.itemView.findViewById(R.id.iv_product);

This is a supplement to @Ravi Teja's answer. You can get the viewHolder from the recyclerView using position of the particular item, then get a particular view from the viewHolder as shown above

mut tony
  • 357
  • 7
  • 9
8

You can use RecyclerView's LayoutManager for it.

View view = layoutManager.findViewByPosition(position)
Geralt_Encore
  • 3,721
  • 2
  • 31
  • 46
  • 1
    Thank you for your answer, unfortunately this method is returning null – Joe Richard Feb 16 '16 at 10:00
  • Are you sure that you are using same LayoutManager that you provided to your RecyclerView? – Geralt_Encore Feb 16 '16 at 10:06
  • Yes, I am sure because I tried twice in different places. For example: rvSellRecords.addOnItemTouchListener(new RecyclerItemClickListener(getActivity(), new RecyclerItemClickListener.OnItemClickListener() { @Override public void onItemClick(View view, int position) { View view2 = layoutManager.findViewByPosition(position); ((MainActivity) getActivity()).showSellRecordFragment(position, view2); } })); – Joe Richard Feb 16 '16 at 10:08
  • It might be returning null if the view is out of range. For example, if I scroll down the list so the first item is out of range, and I `findViewByPosition(0)`, it will return null. – matts1 Aug 23 '18 at 00:10
6

Hope this helps someone: I was getting null pointer exceptions with:

  • recyclerView.findViewHolderForAdapterPosition
  • recyclerView.findViewHolderForItemId
  • layoutManager.findViewByPosition.

The reason was that there is a slight delay for the viewholder to be created. I found the solution here: https://stackoverflow.com/a/33414430/7952427

S. Lopes
  • 148
  • 2
  • 10
3

I post an answer because which is really complex to findviews() from RecyclerView.

@Joe: After spending 4hours found one answer. Which gives me the proper view of the index.

mAdapter is adapter of RecyclerView        
View v = recyclerView.findViewHolderForItemId(mAdapter.getItemId(index/position)).itemView; 

Now just access your views by: v.findViewById(R.id.edittext) OR any id.

rdoubleui
  • 3,554
  • 4
  • 30
  • 51
Ajinkya
  • 1,029
  • 7
  • 15
1

it helped me, make a 100 ms delay before manipulate it, like this:

Handler handler = new Handler();        
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
// rcv is my recyclerview
rcvStatus.getChildAt(1).setBackground(getActivity().getResources().getDrawable(R.drawable.disabled));
// or:
rcvStatus.getChildAt(1).setClickable(false);
}
}, 100);
0

Write this method in adapter.

 public Object getItem(int position) {
        return yourArrayList.get(position);
    }

and you just need to call it like

yourAdapter.getItem(2);

pass your required position. Hope it solves your problem.

SudheeR Bolla
  • 171
  • 2
  • 12
0

just put this method in your code and you can call it as you likes

 void someMagicalMethodWhichReturnsViewByPosition(int position){
         //I assumes child views are CardView
         CardView c  = (CardView)rvSellRecords.getItem(int position);
         ///optional codes
         //////////
    }
Ansal Ali
  • 1,583
  • 1
  • 13
  • 30
0

now I understand your problem. you need to use interface for join recyclerview item and activity. you must define an interface class like below:

public interface IViewClick {
    public void onClickButtonAdd();
}

add this parameter to your adapter class:

private IViewClick mListener;

and initialize it in constructor with value that get from inputs. when user click on PLUS button, you send event to activity by this line:

 mListener.onClickButtonAdd();

in your activity class you must implements IViewClick interface and add your code there, like this:

@Override
    public void onClickButtonAdd() {
         ///  TODO every thing that you want.
         /// change your toolbar values.
    }

it is not good solution for you.

RecyclerView.ViewHolder holder = mRecyclerView.findViewHolderForItemId(mAdapter.getItemId(i));

Haniyeh Khaksar
  • 774
  • 4
  • 20
  • Thank you for suggestion, but this issue still remaining: when I updating view in toolbar, I am getting old view. When quantity is 3, I am getting view with 2. When quantity 10 - view is with 9. – Joe Richard Feb 24 '16 at 08:08
0

I wouldn't recommend tracking the view list yourself. It could lead to weird issues with item updates, position updates, etc.

Instead on your SellRecordChangedEvent, use findViewHolderForAdapterPosition() instead of adapter.getView().

@Subscribe
public void onEvent(SellRecordChangedEvent event){
    sell.getSellRecords().set(event.getSellRecordPosition(), event.getSellRecord());
    sell.recalculate();
    int position = event.getSellRecordPosition();
    View view = yourrecyclerview.findViewHolderForAdapterPosition(position);
    bus.post(new TransactionTitleChangedEvent(null, view));
}

http://developer.android.com/reference/android/support/v7/widget/RecyclerView.html#findViewHolderForAdapterPosition(int)

And as a side note, it's better to implement an actual item click listener to the itemView on the ViewHolder instead of using touch listener. There's lots of examples of this online.

Pirdad Sakhizada
  • 608
  • 7
  • 12
0

So the recyclerview and your product information are in 2 different fragments yes? You are expecting the recyclerview's views to update when they are not even in foreground? also you are changing adapter data item's data at position event.getSellRecordPosition() , but you are not notifying the adapter that its dataset changed, either by adapter.notifyDataSetChanged() or the other notifyItemChanged(position) methods.

I'd modify your onEvent() like so:

@Subscribe
public void onEvent(SellRecordChangedEvent event){
    sell.getSellRecords().set(event.getSellRecordPosition(), event.getSellRecord());
    sell.recalculate();
    int position = event.getSellRecordPosition();
    MyViewHolder holder = adapter.onCreateViewHolder(yourRecyclerView, 0);
    adapter.onBindViewHolder(holder,position);
    View view = adapter.getView(position);
    bus.post(new TransactionTitleChangedEvent(null, view));
}

Calling on createViewHolder and next BindViewHolder on your adapter will definitely update the views for that position, then your adapter.getView(position) should return you the latest view.

Here MyViewHolder is your viewholder class and yourRecyclerview, is the reference to your recycler view

Bhargav
  • 8,118
  • 6
  • 40
  • 63
0
for (int i = 0; i < recycler_view.getAdapter().getItemCount(); i++) {
    View viewTelefone = recycler_view.getChildAt(i);
}

If you want to replace text on a particular edit text for same position:

for (int i = 0; i < recycler_view.getAdapter().getItemCount(); i++) {
    if(adpterPostion==i)
    {
        View viewTelefone = recycler_view.getChildAt(i);
        EditText et_mobile = (EditText) viewTelefone.findViewById(R.id.et_mobile);
        et_mobile.setText("1111111");
    }
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
priti
  • 892
  • 9
  • 9