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 你可以看到一个工作示例。
好的,这是交易。我昨天浪费了 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 你可以看到一个工作示例。