简体   繁体   English

如何在Android中的recyclerView中处理多次布局点击

[英]How to handle multiple layout clicks in recyclerView in Android

In our app we have list of messages. 在我们的应用程序中,我们有消息列表。 We are switching to RecyclerView . 我们将切换到RecyclerView Our messages can consist from texts, images. 我们的信息可以包括文字,图像。 Sample message can look like this. 示例消息可能如下所示。 在此处输入图片说明

To handle clicks use this class: 要处理点击,请使用此类:

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) {
    }
}

and we implement this clicks in activity like this: 我们在以下活动中实现这种点击:

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);
                    }
                })
        );

Clicks for message is working, now I want also handle userAvatar clicks from same GestureDetection . 点击消息的工作正常,现在我也要处理来自同一GestureDetection userAvatar点击。 Is it possible to detect which list item layout was clicked from GestureDetector ? 是否可以检测到从GestureDetector单击了哪个列表项布局?

In other words, can I get GestureDetecter clicked child. 换句话说,我可以让GestureDetecter单击子级GestureDetecter In my case click is set to whole item(avatar, text message, image). 在我的情况下,点击设置为整个项目(头像,短信,图片)。 Can I detect which element inside this item was clicked(for example I want catch avatar click). 我可以检测一下该项目内的哪个元素被点击了(例如,我想捕捉头像点击)。

Handle the click in the adapter of your RecyclerView like below example: 处理您的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) {                                                
                }
            });


        }
    }

You may try this code : 您可以尝试以下代码:

GestureDetector detector;

then: 然后:

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

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

You can set listener into the adapter class. 您可以将侦听器设置为适配器类。 Here is the code : 这是代码:

ViewHolder class inside adapter : 适配器内的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());
            }
        }
    }
}

Set your imageView click in Adapter class onBindViewHolder : 设置您的imageView单击Adapter类onBindViewHolder:

@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
        }
    });
}

Creating interface inside Adapter class : 在Adapter类中创建接口:

//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;
}

Setting interface from Activity/Fragment : 从Activity / Fragment设置界面:

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

based on this post. 根据这篇文章。

//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) {
}

} }

I tried this same way like @user320676, But I tried to complete with a Listener: 我尝试了类似@ user320676的方式,但是尝试使用Listener来完成:

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

then you can use the listener in a activity or fragment. 那么您可以在活动或片段中使用侦听器。 Here you can see my full Adapter: 在这里,您可以看到我的完整适配器:

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);
    }

}

Also you can check the complete code in GitHub . 您也可以在GitHub中查看完整的代码

单击需要在RecyclerView的 Adapter中进行处理,请访问RecyclerView示例,类似于ListView的 onItemClickListener

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM