RecyclerView - 获取 Position inside Activity 而不是 RecyclerView Adapter
RecyclerView - get Position inside Activity rather than RecyclerViewAdapter
这是我处理视图点击的第三天。我原来用的是ListView
,后来换成了RecyclerView
。我已将 android:onclick
元素添加到我的 row_layout
上的每个控件中,我在我的 MainActivity
中处理它们,如下所示:
public void MyMethod(View view) {}
在我的旧 ListView
实现中,我已经完成 setTag(position)
以便能够通过在其中执行此操作将其放入 MyMethod
中:
Integer.parseInt(view.getTag().toString())
这很好用,没有问题。虽然现在我正在处理 RecyclerView
并被迫使用 ViewHolder
,但它不提供 setTag
方法。找了2个小时,发现大家是这样用setTag
的:
holder.itemView.setTag(position)
这是可以接受的。虽然当我尝试使用以下行从 MyMethod
函数获取值时:
Integer.parseInt(view.getTag().toString())
应用程序崩溃。我已经阅读了适配器内部 onclick 处理的几个实现,但我必须使用 MainActivity
因为我使用的是 activity.
独有的东西
TL;DR 我想以简单的方式将点击行的位置发送到我的 MainActivity
。
编辑:由于我的主题不是很透彻,因此造成的混乱我深表歉意。我有一个 RecyclerView
和一个适配器。适配器 linked 到我的 row_layout
。这个row_layout
xml有一个根LinearLayout
。其中有一个 TextView
、另一个 LinearLayout
(其中有两个 TextViews
)和一个 Button
(为简单起见)。我不想像处理 ListView
那样处理 RecylerView
上的点击。因此,我决定为每个控件添加一个 android:onclick
,然后将 link TextView
和 LinearLayout
添加到一个方法中,然后 link Button
(以及未来的 Button
s)他们独特的方法。我缺少的是我希望能够在我的 MainActivity
上告诉每个接收方法的位置。如果我必须 link 来自适配器并进入 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>
您可以通过在适配器内部为 itemclicklistener
创建接口来实现此目的,然后您可以从 MainActivity
设置 onItemClickListener
。
在您 RecyclerViewAdapter
的某个地方,您需要以下内容:
private onRecyclerViewItemClickListener mItemClickListener;
public void setOnItemClickListener(onRecyclerViewItemClickListener mItemClickListener) {
this.mItemClickListener = mItemClickListener;
}
public interface onRecyclerViewItemClickListener {
void onItemClickListener(View view, int position);
}
然后在您的 ViewHolder
中(我已将其作为内部 class 添加到我的适配器中),您可以将侦听器应用于您希望用户单击的组件,例如所以:
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());
}
}
}
此示例显示 onClickListener
应用于 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)
}
});
要实现此代码,您将 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
}
}
});
您还需要更改 ViewHolder
中的内容。而不是将 OnClickListener
应用于 ImageView
,您需要像这样应用于整行:
RecyclerViewHolder(View view) {
super(view);
this.imageview = (ImageView) view
.findViewById(R.id.image);
view.setOnClickListener(this);
}
编辑 2
解释:
因此,每个 RecyclerView
。您需要三个组件,RecyclerView
、RecyclerViewAdapter
和 RecyclerViewHolder
。这些定义了用户看到的实际组件 (RecyclerView
) 和该视图中的项目。适配器是所有东西拼凑在一起并实现逻辑的地方。 Bill Phillips 在 Big Nerd Ranch 的文章 RecyclerView
Part 1: Fundamentals For ListView
Experts 中很好地解释了这些组件的来龙去脉。
但为了进一步解释点击事件背后的逻辑,它基本上是利用 interface 将信息从 RecyclerViewAdapter
传递到 RecyclerViewHolder
再到您的 MainActivity
。因此,如果您遵循 RecyclerView
适配器的生命周期,它就会有意义。
适配器在您的 MainActivity
中初始化,然后将使用传递的信息调用适配器的构造函数。然后组件将通过 OnCreateViewHolder
方法传递到适配器中。这本身告诉适配器,这就是您希望列表的样子。然后需要单独初始化该布局中的组件,这就是 ViewHolder
发挥作用的地方。正如您所看到的,就像您将在 Activities
中初始化的任何其他组件一样,您在 ViewHolder
中执行相同的操作,但是因为 RecyclerViewAdapter
使 ViewHolder
膨胀,您可以愉快地使用它们在您的适配器中,如 Zeeshan Shabbir 所示。但是,对于此示例,您希望多个组件对 MainActivity
class 中的每个组件应用不同的逻辑。
这就是我们将点击侦听器创建为全局变量的地方(因此它可以被 ViewHolder
和 Adapter
访问)适配器在这种情况下的工作是确保侦听器存在通过创建一个 Interface
你可以初始化监听器。
public interface onRecyclerViewItemClickListener {
void onItemClickListener(View view, int position);
}
在您定义了您希望界面保存的信息(例如组件及其位置)之后,您可以创建一个函数,适配器将调用该函数来应用您的 Activity
(与调用 View.OnClickListener
的方式相同)但通过创建 setOnItemClickListener
,您可以自定义它。
public void setOnItemClickListener(onRecyclerViewItemClickListener mItemClickListener) {
this.mItemClickListener = mItemClickListener;
}
此函数需要 onRecyclerViewItemClickListener
变量传递给它,如您的 MainActivity
所示。 new RecyclerViewAdapter.onRecyclerViewItemClickListener()
在这种情况下,它是您之前使用内部方法创建的接口,因此需要实现
@Override
public void onItemClickListener(View view, int position) {
}
被调用。
在这种情况下,ViewHolder
所做的就是将信息(组件本身和位置)传递到附加组件的 onItemClickListener
中(在 onClick
函数内)最终确定实际的点击功能。
如果您希望我更新说明,请告诉我。
我认为您无法处理 ReceylerView
上的多次点击,如果是这种情况,那么让我与您分享我项目中的代码片段。这就是我处理 RecyclerView
中的点击的方式
public class ExploreItemAdapter extends RecyclerView.Adapter<ExploreItemAdapter.ViewHolder> {
private WSResponseDTO<Data> wsResponseDTO;
public ExploreItemAdapter(WSResponseDTO<Data> wsResponseDTO) {
this.wsResponseDTO = wsResponseDTO;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.consumer_dashboard_item, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
holder.tvCompanyName.setText(wsResponseDTO.getData().getPosts().get(position).getStoreInfo().getStoreName());
holder.tvBranchName.setText("(" + wsResponseDTO.getData().getPosts().get(position).getStoreInfo().getBranchName() + ")");
holder.tvLikes.setText(wsResponseDTO.getData().getPosts().get(position).getPost().getFavoriteCount() + "");
holder.tvShares.setText(wsResponseDTO.getData().getPosts().get(position).getPost().getShareCount() + "");
holder.validity.setText(wsResponseDTO.getData().getPosts().get(position).getPost().getValidFrom() + "-" +
wsResponseDTO.getData().getPosts().get(position).getPost().getValidTo());
holder.sTime.setText(wsResponseDTO.getData().getPosts().get(position).getPost().getTime());
holder.tvTitle.setText(wsResponseDTO.getData().getPosts().get(position).getPost().getHeading());
holder.cardView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(view.getContext(), "card is touched", Toast.LENGTH_SHORT).show();
view.getContext().startActivity(new Intent(view.getContext(), ConsumerDetailOfferActivity.class).putExtra("post", wsResponseDTO.getData().getPosts().get(position)));
}
});
}
@Override
public int getItemCount() {
return wsResponseDTO.getData().getPosts().size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.card_explore)
CardView cardView;
@BindView(R.id.tv_company_name)
TextView tvCompanyName;
@BindView(R.id.tv_branch_name)
TextView tvBranchName;
@BindView(R.id.tv_title)
TextView tvTitle;
@BindView(R.id.tv_like_count)
TextView tvLikes;
@BindView(R.id.tv_share_count)
TextView tvShares;
@BindView(R.id.tv_validity)
TextView validity;
@BindView(R.id.tv_sTime)
TextView sTime;
public ViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
}
您可以像我为 cardView
所做的那样为 bindViewHolder() 中的任何项目设置点击侦听器,希望这会有所帮助。
这是我处理视图点击的第三天。我原来用的是ListView
,后来换成了RecyclerView
。我已将 android:onclick
元素添加到我的 row_layout
上的每个控件中,我在我的 MainActivity
中处理它们,如下所示:
public void MyMethod(View view) {}
在我的旧 ListView
实现中,我已经完成 setTag(position)
以便能够通过在其中执行此操作将其放入 MyMethod
中:
Integer.parseInt(view.getTag().toString())
这很好用,没有问题。虽然现在我正在处理 RecyclerView
并被迫使用 ViewHolder
,但它不提供 setTag
方法。找了2个小时,发现大家是这样用setTag
的:
holder.itemView.setTag(position)
这是可以接受的。虽然当我尝试使用以下行从 MyMethod
函数获取值时:
Integer.parseInt(view.getTag().toString())
应用程序崩溃。我已经阅读了适配器内部 onclick 处理的几个实现,但我必须使用 MainActivity
因为我使用的是 activity.
TL;DR 我想以简单的方式将点击行的位置发送到我的 MainActivity
。
编辑:由于我的主题不是很透彻,因此造成的混乱我深表歉意。我有一个 RecyclerView
和一个适配器。适配器 linked 到我的 row_layout
。这个row_layout
xml有一个根LinearLayout
。其中有一个 TextView
、另一个 LinearLayout
(其中有两个 TextViews
)和一个 Button
(为简单起见)。我不想像处理 ListView
那样处理 RecylerView
上的点击。因此,我决定为每个控件添加一个 android:onclick
,然后将 link TextView
和 LinearLayout
添加到一个方法中,然后 link Button
(以及未来的 Button
s)他们独特的方法。我缺少的是我希望能够在我的 MainActivity
上告诉每个接收方法的位置。如果我必须 link 来自适配器并进入 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>
您可以通过在适配器内部为 itemclicklistener
创建接口来实现此目的,然后您可以从 MainActivity
设置 onItemClickListener
。
在您 RecyclerViewAdapter
的某个地方,您需要以下内容:
private onRecyclerViewItemClickListener mItemClickListener;
public void setOnItemClickListener(onRecyclerViewItemClickListener mItemClickListener) {
this.mItemClickListener = mItemClickListener;
}
public interface onRecyclerViewItemClickListener {
void onItemClickListener(View view, int position);
}
然后在您的 ViewHolder
中(我已将其作为内部 class 添加到我的适配器中),您可以将侦听器应用于您希望用户单击的组件,例如所以:
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());
}
}
}
此示例显示 onClickListener
应用于 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)
}
});
要实现此代码,您将 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
}
}
});
您还需要更改 ViewHolder
中的内容。而不是将 OnClickListener
应用于 ImageView
,您需要像这样应用于整行:
RecyclerViewHolder(View view) {
super(view);
this.imageview = (ImageView) view
.findViewById(R.id.image);
view.setOnClickListener(this);
}
编辑 2
解释:
因此,每个 RecyclerView
。您需要三个组件,RecyclerView
、RecyclerViewAdapter
和 RecyclerViewHolder
。这些定义了用户看到的实际组件 (RecyclerView
) 和该视图中的项目。适配器是所有东西拼凑在一起并实现逻辑的地方。 Bill Phillips 在 Big Nerd Ranch 的文章 RecyclerView
Part 1: Fundamentals For ListView
Experts 中很好地解释了这些组件的来龙去脉。
但为了进一步解释点击事件背后的逻辑,它基本上是利用 interface 将信息从 RecyclerViewAdapter
传递到 RecyclerViewHolder
再到您的 MainActivity
。因此,如果您遵循 RecyclerView
适配器的生命周期,它就会有意义。
适配器在您的 MainActivity
中初始化,然后将使用传递的信息调用适配器的构造函数。然后组件将通过 OnCreateViewHolder
方法传递到适配器中。这本身告诉适配器,这就是您希望列表的样子。然后需要单独初始化该布局中的组件,这就是 ViewHolder
发挥作用的地方。正如您所看到的,就像您将在 Activities
中初始化的任何其他组件一样,您在 ViewHolder
中执行相同的操作,但是因为 RecyclerViewAdapter
使 ViewHolder
膨胀,您可以愉快地使用它们在您的适配器中,如 Zeeshan Shabbir 所示。但是,对于此示例,您希望多个组件对 MainActivity
class 中的每个组件应用不同的逻辑。
这就是我们将点击侦听器创建为全局变量的地方(因此它可以被 ViewHolder
和 Adapter
访问)适配器在这种情况下的工作是确保侦听器存在通过创建一个 Interface
你可以初始化监听器。
public interface onRecyclerViewItemClickListener {
void onItemClickListener(View view, int position);
}
在您定义了您希望界面保存的信息(例如组件及其位置)之后,您可以创建一个函数,适配器将调用该函数来应用您的 Activity
(与调用 View.OnClickListener
的方式相同)但通过创建 setOnItemClickListener
,您可以自定义它。
public void setOnItemClickListener(onRecyclerViewItemClickListener mItemClickListener) {
this.mItemClickListener = mItemClickListener;
}
此函数需要 onRecyclerViewItemClickListener
变量传递给它,如您的 MainActivity
所示。 new RecyclerViewAdapter.onRecyclerViewItemClickListener()
在这种情况下,它是您之前使用内部方法创建的接口,因此需要实现
@Override
public void onItemClickListener(View view, int position) {
}
被调用。
在这种情况下,ViewHolder
所做的就是将信息(组件本身和位置)传递到附加组件的 onItemClickListener
中(在 onClick
函数内)最终确定实际的点击功能。
如果您希望我更新说明,请告诉我。
我认为您无法处理 ReceylerView
上的多次点击,如果是这种情况,那么让我与您分享我项目中的代码片段。这就是我处理 RecyclerView
public class ExploreItemAdapter extends RecyclerView.Adapter<ExploreItemAdapter.ViewHolder> {
private WSResponseDTO<Data> wsResponseDTO;
public ExploreItemAdapter(WSResponseDTO<Data> wsResponseDTO) {
this.wsResponseDTO = wsResponseDTO;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.consumer_dashboard_item, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
holder.tvCompanyName.setText(wsResponseDTO.getData().getPosts().get(position).getStoreInfo().getStoreName());
holder.tvBranchName.setText("(" + wsResponseDTO.getData().getPosts().get(position).getStoreInfo().getBranchName() + ")");
holder.tvLikes.setText(wsResponseDTO.getData().getPosts().get(position).getPost().getFavoriteCount() + "");
holder.tvShares.setText(wsResponseDTO.getData().getPosts().get(position).getPost().getShareCount() + "");
holder.validity.setText(wsResponseDTO.getData().getPosts().get(position).getPost().getValidFrom() + "-" +
wsResponseDTO.getData().getPosts().get(position).getPost().getValidTo());
holder.sTime.setText(wsResponseDTO.getData().getPosts().get(position).getPost().getTime());
holder.tvTitle.setText(wsResponseDTO.getData().getPosts().get(position).getPost().getHeading());
holder.cardView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(view.getContext(), "card is touched", Toast.LENGTH_SHORT).show();
view.getContext().startActivity(new Intent(view.getContext(), ConsumerDetailOfferActivity.class).putExtra("post", wsResponseDTO.getData().getPosts().get(position)));
}
});
}
@Override
public int getItemCount() {
return wsResponseDTO.getData().getPosts().size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.card_explore)
CardView cardView;
@BindView(R.id.tv_company_name)
TextView tvCompanyName;
@BindView(R.id.tv_branch_name)
TextView tvBranchName;
@BindView(R.id.tv_title)
TextView tvTitle;
@BindView(R.id.tv_like_count)
TextView tvLikes;
@BindView(R.id.tv_share_count)
TextView tvShares;
@BindView(R.id.tv_validity)
TextView validity;
@BindView(R.id.tv_sTime)
TextView sTime;
public ViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
}
您可以像我为 cardView
所做的那样为 bindViewHolder() 中的任何项目设置点击侦听器,希望这会有所帮助。