RecyclerView 使用一些按钮处理点击

RecyclerView handling clicks with some buttons

好的,这是交易。我昨天浪费了 13 个小时处理 ListView 上的点击处理,然后切换到 RecyclerView(感谢这里的成员)解决了我处理项目点击的原始问题。我是 android 编程新手,所以请多多包涵。

我设法使用此处的 RecyclerView\RecyclerItemClickListener 解决了我的问题:

RecyclerView onClick

现在,我已经添加了一些我想使用的按钮,这让事情变得复杂了。我希望能够单击按钮并执行各种操作,同时单击主要项目并执行其他操作。有什么方法可以扩展 RecyclerItemClickListener 以允许我检查单击是在按钮上还是在 Recycler 项目本身上。我发现RecyclerItemClickListener上有坐标。所以,我心想也许我可以使用这些来确定被点击的控件,但我记得设备有不同的屏幕尺寸。

我看到了一些处理 ViewHolder 级别点击的方法,但我想同时检查按钮和项目本身。我一直在一遍又一遍地搜索,我决定使用我的布局在布局标签上指定 onclick 元素,并在布局上的每个元素上将非按钮元素转发到项目(布局标签)方法,同时为按钮提供单独的方法.

我正在做的是黑客行为吗?你能给我指明正确的方向来完成我想要的吗?

您可以在 ViewHolder:

中执行如下操作
class MyViewHolder extends RecyclerView.ViewHolder {

    private Button myButton;

    public MyViewHolder(View itemView) {
        super(itemView);
        myButton = itemView.findViewById(R.id.my_button);

        itemView.setOnClickListener(mainViewClickListener);
        myButton.setOnClickListener(buttonClickListener);
    }

    private View.OnClickListener mainViewClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // Do main thing here.
        }
    };

    private View.OnClickListener buttonClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // Do button click handling here
        }
    };
}

您可以使用Facade 视图来处理这个问题。通过在 LinearLayout 和 LinearLayout 中创建,您可以选择处理什么点击。那么对于如何处理长点击setOnCreateContextMenuListener、短点击和点击视图中的项目

这是一个布局示例,请注意 focusable/clickable 参数。

布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:clickable="false"
    android:focusable="false"
    >

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/showClickable"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clickable="true"
        android:focusable="true"
        android:background="?android:attr/selectableItemBackground"
        >

        <TextView
            android:text="TextView"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:id="@+id/itemShowTitle"
            android:layout_weight="1"
            />

        <Button
            android:id="@+id/buttonWorthClicking"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="button worth clicking"/>
    </LinearLayout>
</LinearLayout>

然后我们需要ViewHolder来传递或根据需要处理点击

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

    public ShowsRecyclerViewAdapter(List<Show> shows) {
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        Context context = parent.getContext();
        LayoutInflater inflater = LayoutInflater.from(context);
        View view = inflater.inflate(R.layout.show_list_item, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.itemShowTitle.setText("" + position);
    }

    @Override
    public int getItemCount() {
        return 10;
    }

    static class ViewHolder extends RecyclerView.ViewHolder
            implements View.OnClickListener, View.OnCreateContextMenuListener {

        final TextView itemShowTitle;
        final Button buttonWorthClicking;

        ViewHolder(final View itemView) {
            super(itemView);
            itemView.setOnClickListener(this);
            itemShowTitle = (TextView) itemView.findViewById(R.id.itemShowTitle);
            buttonWorthClicking = (Button) itemView.findViewById(R.id.buttonWorthClicking);

            setViewFacade(itemView);

            itemView.setOnCreateContextMenuListener(this);
        }

        /**
         * Because the layout is nested to for the ripple we build a facade to pass along clicks
         */
        private void setViewFacade(final View itemView) {
            View facedForClicks = itemView.findViewById(R.id.showClickable);
            facedForClicks.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    // pass along the short click
                    ViewHolder.this.onClick(itemView);
                }
            });
            facedForClicks.setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() {
                @Override
                public void onCreateContextMenu(ContextMenu contextMenu, View view, ContextMenu.ContextMenuInfo contextMenuInfo) {
                    // no-op but passes up to the ViewHolder
                }
            });

            buttonWorthClicking.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Log.d("one-off", "the button was clicked");
                }
            });
        }

        @Override
        public void onClick(View v) {
            Log.d("one-off", "short click on item");
        }

        @Override
        public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo contextMenuInfo) {
            Log.d("one-off", "long click on item");
        }
    }
}

我在我的 Podcast Player 项目上创建了一个分支 github 你可以看到一个工作示例。

Class

XML

branch