RecyclerView - 在Activity中获取Position而不是RecyclerViewAdapter

Joh*_*son 3 android android-viewholder android-recyclerview

现在是我处理查看点击次数的第三天.我最初使用ListView,然后我切换到RecyclerView.我已经android:onclick为我的每个控件添加了元素row_layout,我在这样处理它们MainActivity:

public void MyMethod(View view) {}
Run Code Online (Sandbox Code Playgroud)

在我的旧ListView实现中,我已经完成setTag(position)了通过在其中MyMethod执行此操作来获取它:

Integer.parseInt(view.getTag().toString())
Run Code Online (Sandbox Code Playgroud)

这很好地没有问题.虽然现在我正在处理RecyclerView并被迫使用ViewHolder,但没有提供setTag方法.搜索了2个小时后,我发现人们使用setTag这样的:

holder.itemView.setTag(position)
Run Code Online (Sandbox Code Playgroud)

这是可以接受的.虽然当我尝试MyMethod使用该行从函数中获取值时:

Integer.parseInt(view.getTag().toString())
Run Code Online (Sandbox Code Playgroud)

应用程序崩溃.我已经阅读了适配器内部onclick处理的几个实现,但是我必须使用它,MainActivity因为我使用的是该活动所特有的东西.

TL; DR我想以MainActivity简单的方式将点击的行的位置发送给我.

编辑:我为这个混乱道歉,因为我的主题不是很彻底.我有一个RecyclerView适配器.适配器链接到我的row_layout.这个row_layoutxml有一个根LinearLayout.里面有一个TextView,另一个LinearLayout(有两个TextViews)和一个Button(为简单起见).我不想像处理点击RecylerView那样处理点击ListView.所以,我决定添加一个android:onclick用于每个控制,然后链接TextViewLinearLayout到一个单一的方法和链接Button(和将来ButtonS)其独特的方法.我缺少的是我希望能够在我的每个接收方法上说出立场MainActivity.如果我必须链接来自适配器的所有内容并进入MainActivity单个onclick处理程序,那就这样吧.虽然,我怎么知道哪个控件触发了点击?

编辑2:请求的布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:onClick="MyMethod"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:weightSum="1">
    <TextView
        android:id="@+id/letter"
        android:onClick="MyMethod"
        android:layout_width="60dp"
        android:layout_height="fill_parent"
        />
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:onClick="MyMethod"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:id="@+id/firstname"
            android:onClick="MyMethod"
            android:layout_width="fill_parent"
            android:layout_height="17dp" />
        <TextView
            android:id="@+id/longname"
            android:onClick="MyMethod"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content" />

    </LinearLayout>
    <Button
        android:text="Test"
        android:onClick="OtherMethod"
        android:layout_width="match_parent"
        android:layout_height="fill_parent"
        android:id="@+id/process"/>
</LinearLayout>
Run Code Online (Sandbox Code Playgroud)

BIW*_*BIW 11

您可以通过在适配器中创建一个接口来实现此目的itemclicklistener,然后您可以onItemClickListener从您的设置中进行设置MainActivity.

RecyclerViewAdapter你内心的某个地方需要以下内容:

private onRecyclerViewItemClickListener mItemClickListener;

 public void setOnItemClickListener(onRecyclerViewItemClickListener mItemClickListener) {
        this.mItemClickListener = mItemClickListener;
    }

    public interface onRecyclerViewItemClickListener {
        void onItemClickListener(View view, int position);
    }
Run Code Online (Sandbox Code Playgroud)

然后在你的内部ViewHolder(我作为内部类添加到我的适配器中),你将把监听器应用到你希望用户点击的组件,如下所示:

class RecyclerViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        public ImageView imageview;

        RecyclerViewHolder(View view) {
            super(view);
            this.imageview = (ImageView) view
                    .findViewById(R.id.image);
            imageview.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            if (mItemClickListener != null) {
                mItemClickListener.onItemClickListener(v, getAdapterPosition());
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

此示例显示onClickListener正在应用于a内的图像ViewHolder.

recyclerView.setAdapter(adapter);// set adapter on recyclerview
            adapter.notifyDataSetChanged();// Notify the adapter
            adapter.setOnItemClickListener(new RecyclerViewAdapter.onRecyclerViewItemClickListener() {
                @Override
                public void onItemClickListener(View view, int position) { 
//perform click logic here (position is passed)
                    }
                });
Run Code Online (Sandbox Code Playgroud)

要实现此代码,您可以setOnItemClickListener在内部使用适配器,MainActivity如上所示.

编辑

因为View正在传入OnItemClickListener,所以您可以switch在侦听器内执行语句,以确保正确的逻辑正在执行到正确的组件.您需要做的就是从MyMethod函数中获取逻辑并将其复制并粘贴到您希望应用它的组件中.

例:

recyclerView.setAdapter(adapter);// set adapter on recyclerview
                adapter.notifyDataSetChanged();// Notify the adapter
                adapter.setOnItemClickListener(new RecyclerViewAdapter.onRecyclerViewItemClickListener() {
                    @Override
                    public void onItemClickListener(View view, int position) { 
        Switch (view.getId()) {
            case R.id.letter:
               //logic for TextView with ID Letter here
            break;
            case R.id.firstname:
               //logic for TextView with ID firstname here
            break;
            ....
            //the same can be applied to other components in Row_Layout.xml
        }
                        }
                    });
Run Code Online (Sandbox Code Playgroud)

你还需要改变内部的东西ViewHolder.而不是应用OnClickListenerImageView,您将需要应用到整个行,像这样:

 RecyclerViewHolder(View view) {
                super(view);
                this.imageview = (ImageView) view
                        .findViewById(R.id.image);
                view.setOnClickListener(this);
            }
Run Code Online (Sandbox Code Playgroud)

编辑2

说明:

所以,每一个RecyclerView.你需要三个组成部分,将RecyclerView,RecyclerViewAdapterRecyclerViewHolder.这些是定义用户看到的实际组件(RecyclerView)和该视图中的项目的内容.适配器是将所有内容拼凑在一起并实现逻辑的地方.比尔菲利普斯在RecyclerView第一部分:ListView Big Nerd Ranch的专家基础知识中很好地解释了这些组件的细节.

但进一步解释单击事件背后的逻辑,它基本上使用的界面来传递从信息RecyclerViewAdapterRecyclerViewHolder你的MainActivity.因此,如果您遵循RecyclerView适配器的生命周期,它将是有道理的.

适配器在您MainActivity的内部初始化,然后将调用适配器的构造函数并传递信息.然后,组件将通过该OnCreateViewHolder方法传递到适配器中.这本身告诉适配器,这就是你希望列表的样子.然后需要单独初始化该布局中的组件,这就是ViewHolder它发挥作用的地方.正如你可以看到像你会在你的初始化任何其他组件Activities,你做同样的ViewHolder,但因为RecyclerViewAdapter膨胀的ViewHolder,你可以愉快地适配器中使用它们由Zeeshan Shabbir所示.但是,对于此示例,您希望多个组件将各种逻辑应用于类中的每个组件MainActivity.

这就是我们将click侦听器创建为全局变量的地方(因此它可以被ViewHolder和它访问Adapter)在这种情况下,适配器的作业是通过创建一个Interface可以初始化侦听器来确保侦听器存在.

 public interface onRecyclerViewItemClickListener {
    void onItemClickListener(View view, int position);
 }
Run Code Online (Sandbox Code Playgroud)

在定义了您希望接口保持的信息(EG组件及其位置)之后,您可以创建一个函数,适配器将调用该函数来应用您的逻辑Activity(与您调用的方式相同View.OnClickListener)但是创建一个setOnItemClickListener,你可以自定义它.

public void setOnItemClickListener(onRecyclerViewItemClickListener mItemClickListener) {
        this.mItemClickListener = mItemClickListener;
    }
Run Code Online (Sandbox Code Playgroud)

然后这个函数需要onRecyclerViewItemClickListener传递给它的变量,如你所见MainActivity.new RecyclerViewAdapter.onRecyclerViewItemClickListener()在这种情况下,它是您之前使用内部方法创建的接口,因此需要实现

@Override
                public void onItemClickListener(View view, int position) {
                }
Run Code Online (Sandbox Code Playgroud)

叫做.

ViewHolder在这种情况下,所有这些都是将信息(它自己的组件和位置)传递到onItemClickListener附加的组件(在onClick函数内)以完成实际的点击功能.

如果您希望我以任何方式更新说明,请告诉我.

  • 谢谢你的解释.起初没有意义.所以,我不得不休息一下所有的痛苦.我不敢相信我已经花了几天时间来处理界面问题.我希望我的其他控件没有任何类似的问题.这真是一个出色的解决方案.您正在使用MainActivity通过自定义单击方法的实例调用适配器.然后,您捕获ViewHolder级别的点击并将其重定向到单击自定义界面方法.再次感谢这个梦幻般的解决方案 (2认同)