【问题标题】:RecyclerView handling clicks with some buttonsRecyclerView 使用一些按钮处理点击
【发布时间】:2016-12-07 22:35:19
【问题描述】:

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

我设法从这里使用 RecyclerView\RecyclerItemClickListener 解决了我的问题:

RecyclerView onClick

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

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

我正在做的事情是 hack 吗?你能给我指出正确的方向来完成我想要的吗?

【问题讨论】:

    标签: android android-recyclerview onitemclicklistener


    【解决方案1】:

    您可以在 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
            }
        };
    }
    

    【讨论】:

    • 感谢您的反馈,阿卜杜拉。非常感激。这实际上是我在 XML 上所做的程序化版本。尽管如此,这很有趣。
    • 您能否添加您的代码,以便我们更好地了解您尝试执行的操作。
    • 似乎没有更好的方法来完成我想要的。所以,我决定采用我原来的解决方案。我将其设置为答案,因为它提供了我正在做的事情的程序化版本。
    【解决方案2】:

    您可以使用外观视图来处理此问题。通过在和 LinearLayout 中创建 LinearLayout,您可以选择处理哪些点击。那么对于如何处理长点击setOnCreateContextMenuListener,短点击和点击视图内的项目。

    这是一个示例布局,注意可聚焦/可点击的参数。

    布局

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

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

    Class

    XML

    branch

    【讨论】:

    • 感谢胜利。我很感激。立面概念对我来说是新的。我会尝试理解和消化解决方案,然后再回来发表评论。
    • 这很有趣。您正在将布局标签上的任何内容重定向到项目单击方法。我想可以为额外的按钮添加额外的点击处理程序。但是,在我的情况下,两个 TextView 元素消耗了点击并阻止了重定向。在我的 XML 布局上,我有一个 TextView、LinearLayout(它有两个 TextView)和一个按钮(我删除了其余部分)。内部 TextView 使用选项卡,而主 TextView 不使用。我什至尝试为两个 Layout 元素添加一个 id,然后在 setViewFacade 中为内部元素添加一个额外的段。那也没用。
    猜你喜欢
    • 2020-12-29
    • 2019-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-26
    • 2017-06-18
    • 1970-01-01
    相关资源
    最近更新 更多