how to get the position of an Item of the recycler

2019-07-16 04:47发布

I have a recyclerView inside a DrawerLayout. Each row item has an ImageView , the icon and a Textbox , the text. I use addOnItemTouchListener to detect the position of the row item when clicked by the user , in order to open a new fragment. This is my code from addOnItemTouchListener:

mRecyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
        @Override
        public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
            View item = rv.findChildViewUnder(e.getX(),e.getY()); //finding the view that clicked , using coordinates X and Y
            int position = rv.getChildLayoutPosition(item); //getting the position of the item inside the list
            //Log.d("billy",String.valueOf(position));
            onListViewItemClick(position);
            mDrawer.closeDrawers(); // closing the navigation drawer
            return true;
        }

        @Override
        public void onTouchEvent(RecyclerView rv, MotionEvent e) {

        }

        @Override
        public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

        }
    });

And this is the method onListViewItemClick :

public void onListViewItemClick(int position) {
    DrawerItem data = mList.get(position); //Item of the recycler View at specific position
    Bundle lbundle = new Bundle();
    lFragmentManager = getFragmentManager();
    lFragment = lFragmentManager.findFragmentById(R.id.frame_container);
    lFragment = new FragmentHome();
    lbundle.putSerializable("Item", data); // sending to fragment the Item of the Recycler View , which pressed
    lFragment.setArguments(lbundle);
    //To the fragment
    lFragmentManager.beginTransaction().replace(R.id.frame_container ,lFragment ).commit();
}

The problem is that this implementation works only if the user clicks the imageView of the row item of the Navigation Drawer. If the user clicks in the TextView of the row Item then the variable position takes the value -1 . I thing that the method findChildViewUnder(e.getX(), e.getY()) to return only the imageView and not both. I want findChildViewUnder(e.getx(),e.getY()) returns the viewGroup.

This is the XML file that defines each row - Item of the Navigation Drawer:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:orientation="horizontal"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:background="?android:attr/selectableItemBackground">
<LinearLayout
    android:id="@+id/inner_layout"
    android:layout_width="40dp"
    android:layout_height="wrap_content"
    android:layout_alignBottom="@+id/nv_title"
    android:layout_alignTop="@+id/nv_title"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true">

    <ImageView
        android:layout_width="25dp"
        android:layout_height="25dp"
        android:id="@+id/nv_image"
        android:background="@android:color/transparent"
        android:scaleType="fitXY"
        android:layout_marginLeft="15dp"
        android:layout_gravity="center"/>

</LinearLayout>

<TextView
    android:id="@+id/nv_title"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingLeft="13dp"
    android:minHeight="?android:attr/listPreferredItemHeightSmall"
    android:textAppearance="?android:attr/textAppearanceListItemSmall"
    android:gravity="center_vertical"
    android:layout_centerVertical="true"
    android:layout_alignParentRight="true"
    android:layout_alignParentEnd="true"
    android:layout_toEndOf="@+id/inner_layout"
    android:layout_gravity="center"
    android:singleLine="true"
    android:ellipsize="end"
    android:layout_toRightOf="@+id/inner_layout" />

    </RelativeLayout>

Thank you for the Help!

3条回答
倾城 Initia
2楼-- · 2019-07-16 05:05

If you had registed ItemTouchListener you can get view position as following:

public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
    private static final String TAG = RecyclerItemClickListener.class.getSimpleName();

    public void setListener(OnItemClickListener mListener) {
        this.mListener = mListener;
    }

    private OnItemClickListener mListener;

    public RecyclerItemClickListener(Context context) {
        this(context, null);
    }


    GestureDetector mGestureDetector;

    public RecyclerItemClickListener(Context context, OnItemClickListener listener) {
        mListener = listener;
        mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
            @Override public boolean onSingleTapUp(MotionEvent e) {
                return true;
            }
        });
    }

    @Override public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {
        View childView = view.findChildViewUnder(e.getX(), e.getY());

        if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
            mListener.onItemClick(view, childView, view.getChildAdapterPosition(childView));
        }
        return false;
    }

    @Override public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) { }

    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

    }
}

Statement view.getChildAdapterPosition(childView) is method from RecyclerView and returns the position of touched view in the adapter.

查看更多
聊天终结者
3楼-- · 2019-07-16 05:14

You could extend the ViewHolder class to have a click listener on parts of your item that you need to click on (i.e. use the container to catch "item clicks"). When clicked you can do whatever you like with the event, and the accurate position will be getAdapterPosition() from the ViewHolder itself.

查看更多
乱世女痞
4楼-- · 2019-07-16 05:19

You can gain access to the position if you set your onClick listener on onBindViewHolder

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
//TODO: Use position here.
}
查看更多
登录 后发表回答