如何在Android中处理recyclerView中的多个布局点击事件

10

在我们的应用程序中,我们有消息列表。我们正在切换到 RecyclerView。 我们的消息可以包含文本、图像。 示例消息可能如下所示。 enter image description here

使用这个类来处理点击:

public class RecyclerViewItemClickListener implement  RecyclerView.OnItemTouchListener {

    public static interface OnItemClickListener {
        public void onItemClick(View view, int position);
        public void onItemLongClick(View view, int position);
    }

    private OnItemClickListener mListener;
    private GestureDetector mGestureDetector;

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

            @Override
            public void onLongPress(MotionEvent e)
            {
                View childView = recyclerView.findChildViewUnder(e.getX(), e.getY());
                if(childView != null && mListener != null)
                {
                    mListener.onItemLongClick(childView, recyclerView.getChildAdapterPosition(childView));
                }
            }
        });
    }

    @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(childView, view.getChildAdapterPosition(childView));
        }
        return false;
    }

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

我们在活动中实现这些点击操作的方式如下:

chatView.setLongClickable(true);
        chatView.addOnItemTouchListener(
                new RecyclerViewItemClickListener(this, chatView, new RecyclerViewItemClickListener.OnItemClickListener() {
                    @Override public void onItemClick(View view, int position) {

                        //handleSingleClick(view, position);

                    }
                    @Override
                    public void onItemLongClick(View view, int position)
                    {
                        handleLongPress(position);
                    }
                })
        );

消息点击功能已经可以使用,现在我还想从同一个GestureDetection中处理userAvatar的点击。是否有可能从GestureDetector中检测到哪个列表项布局被点击了?

换句话说,我能否获取GestureDetector所点击的子元素。在我的情况下,点击设置为整个项目(头像、文本消息、图像)。我能否检测到点击了该项目内的哪个元素(例如,我想捕获头像的点击)。

5个回答

5

请按照以下示例在RecyclerView的适配器中处理点击事件:

private class BookmarkViewHolder extends RecyclerView.ViewHolder {

        protected ImageView thumbnailIcon;
        protected TextView postTitle;
        protected TextView postViewCount;

        public BookmarkViewHolder(View v) {
            super(v);

            thumbnailIcon = (ImageView) v.findViewById(R.id.thumbnailIcon);
            postTitle = (TextView) v.findViewById(R.id.postTitleTV);
            postViewCount = (TextView) v.findViewById(R.id.viewCountTV);

            v.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {                                                
                }
            });

            thumbnailIcon.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {                                                
                }
            });

            postTitle.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {                                                
                }
            });


        }
    }

当您尝试在onClick调用中获取listitem的位置时,如何使其工作...这将无法在viewHolder方法中工作... - Lion789
使用setTag()方法来设置项目的位置,就像这样: public void onBindViewHolder(PostViewHolder postViewHolder, int i) { //当点击一个项目时,将使用此标记... postViewHolder.postTitle.setTag(i); postViewHolder.postTitle.setTag("TITLE");
}
- user320676

0
你可以尝试这段代码:
GestureDetector detector;

然后:

detector = new GestureDetector(MainActivity.this, MainActivity.this);

    avatar.setOnTouchListener(new OnTouchListener() {
        public boolean onTouch(View view, MotionEvent e) {
            detector.onTouchEvent(e);
            return false;
        }
    });

0

我尝试了和 @user320676 一样的方法,但是我尝试着用一个监听器来完成:

interface MultipleClickListener {
        void onItemClickOne(int position, View v);
        void onItemClickTwo(int position, View v);
        void onItemClickThree(int position, View v);
}

然后您可以在活动或片段中使用监听器。这里是我的完整适配器:

public class MultipleClicksAdapter extends RecyclerView
        .Adapter<MultipleClicksAdapter
        .DataObjectHolder> {

    private ArrayList<MultipleClickData> mDataset;
    private static MultipleClickListener sClickListener;

    static class DataObjectHolder extends RecyclerView.ViewHolder {

        @BindView(R.id.multiple_clicks_one_textView)
        TextView mOne;
        @BindView(R.id.multiple_clicks_two_textView)
        TextView mTwo;
        @BindView(R.id.multiple_clicks_three_textView)
        TextView mThree;

        DataObjectHolder(View itemView) {
            super(itemView);

            ButterKnife.bind(this, itemView);

            mOne.setOnClickListener((View v) ->
                    sClickListener.onItemClickOne(getAdapterPosition(), mOne));

            mTwo.setOnClickListener((View v) ->
                    sClickListener.onItemClickTwo(getAdapterPosition(), mTwo));

            mThree.setOnClickListener((View v) ->
                    sClickListener.onItemClickThree(getAdapterPosition(), mThree));
        }

    }

    void setOnItemClickListener(MultipleClickListener myClickListener) {
        this.sClickListener = myClickListener;
    }

    MultipleClicksAdapter(ArrayList<MultipleClickData> myDataset) {
        mDataset = myDataset;
    }

    @Override
    public MultipleClicksAdapter.DataObjectHolder onCreateViewHolder(ViewGroup parent,
                                                                           int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.multiple_clicks_list_item, parent, false);

        MultipleClicksAdapter.DataObjectHolder dataObjectHolder = new MultipleClicksAdapter.DataObjectHolder(view);
        return dataObjectHolder;
    }

    @Override
    public void onBindViewHolder(MultipleClicksAdapter.DataObjectHolder holder, int position) {
        holder.mOne.setText(mDataset.get(position).getmTitle());
        holder.mTwo.setText(mDataset.get(position).getmSubTitle());
        holder.mThree.setText(mDataset.get(position).getmThirdTitle());
    }

    @Override
    public int getItemCount() {
        return mDataset.size();
    }

    interface MultipleClickListener {
        void onItemClickOne(int position, View v);
        void onItemClickTwo(int position, View v);
        void onItemClickThree(int position, View v);
    }

}

你也可以在 GitHub 上查看完整的代码


0

基于这篇文章。

//init listener
rVDevicesList.addOnItemTouchListener(new  RecyclerItemClickListener(getContext(),
            rVDevicesList,
            this, R.id.tv_wonderful_item_share,  R.id.tv_wonderful_item_delete));  




public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {

private OnItemClickListener mListener;
private int[] extraIds;
private Rect childRect = new Rect();

public interface OnItemClickListener {
    void onItemClick(View view, int position);

    void onLongItemClick(View view, int position);
}

private GestureDetector mGestureDetector;

/**
 * 
 * @param context
 * @param recyclerView
 * @param listener
 * @param ids: an alternative parameter
 */
public RecyclerItemClickListener(Context context,
                                 final RecyclerView recyclerView,
                                 OnItemClickListener listener, final int... ids) {
    mListener = listener;
    extraIds = ids;
    mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            return true;
        }

        @Override
        public void onLongPress(MotionEvent e) {
            View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
            if (child != null && mListener != null) {
                mListener.onLongItemClick(child, recyclerView.getChildAdapterPosition(child));
            }
        }
    });
}

@Override
public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {
    final float x = e.getX();
    final float y = e.getY();
    Log.d("onInterceptTouchEvent", "onInterceptTouchEvent: " + x + " " + y);
    View childView = view.findChildViewUnder(e.getX(), e.getY());
    if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
        final int position = view.getChildAdapterPosition(childView);
        View target = getViewBy(childView, x, y, extraIds);
        //if target is non-null,so you click the view. 
        mListener.onItemClick(target, position);
        return true;
    }
    return false;
}

/**
 * find the view ,which view_rect contains the {x,y} in the window.
 * @param view: this view is  item layout view,may be a viewGroup
 * @param x
 * @param y
 * @param ids
 * @return true: hit a view which id in ids.
 */
private View getViewBy(View view, float x, float y, int... ids) {
    if (ids == null || ids.length == 0 || !(view instanceof ViewGroup))
        return view;
    for (int i : ids) {
        View vChild = view.findViewById(i);
        if (vChild == null) {
            Log.d("onInterceptTouchEvent", "null");
        } else {
            int xy[] = new int[2];
            vChild.getLocationOnScreen(xy);
            childRect.left = xy[0];
            childRect.top = xy[1];
            childRect.right = xy[0] + vChild.getWidth();
            childRect.bottom = xy[1] + vChild.getHeight();
            boolean hit = childRect.contains((int) x, (int) y);
            Log.d("onInterceptTouchEvent", "find view: " + hit);
            if (hit)
                return vChild;
        }
    }
    return view;
}

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

}

@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}

}


2
你应该添加一些解释说明为什么这段代码可以工作 - 你也可以在代码本身中添加注释 - 在当前形式下,它没有提供任何解释,这可能有助于其他社区成员理解你是如何解决/回答问题的。 - ishmaelMakitla

0

您可以将监听器设置到适配器类中。以下是代码:

适配器内的ViewHolder类:

    public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    TextView textViewFirstName;
    ImageView imageViewProfile;

    public MyViewHolder(View view) {
        super(view);
        textViewFirstName = (TextView) view.findViewById(R.id.txtName);
        imageViewProfile = (ImageView) view.findViewById(R.id.imageViewProfile);

//setOnClick
        view.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
    //check if the image you want to click should not invoke listener from activity/fragment
        if (v.getId() != R.id.imageViewProfile) {
            if (mItemClickListener != null) {
                mItemClickListener.onItemClick(v, getPosition());
            }
        }
    }
}

在Adapter类的onBindViewHolder中设置您的imageView点击:

@Override
public void onBindViewHolder(MyViewHolder holder, final int position) {

    holder.textViewFirstName.setText(mArrayListTypeDetials.get(position).getFirstname());
    //set imageView click here
    holder.imageViewProfile.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
           //ImageView clicked
        }
    });
}

在适配器类中创建接口:
//interface for recyclerView item click
public interface OnItemClickListener {
    void onItemClick(View view, int position);
}

/*
method to set listener to the adapter ViewHolder item
 */
public void setOnItemClickListener(final OnItemClickListener mItemClickListener) {
    this.mItemClickListener = mItemClickListener;
}

从Activity/Fragment设置接口:

    mAdapter.setOnItemClickListener(new Adapter.OnItemClickListener() {
        @Override
        public void onItemClick(View view, int position) {
            Intent intent = new Intent(getActivity(), ABC.class);
            startActivity(intent);
        }
    });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接