Java 在RecyclerView的单个接口中使用多个onClick方法

Java 在RecyclerView的单个接口中使用多个onClick方法,java,android,oop,android-recyclerview,onclicklistener,Java,Android,Oop,Android Recyclerview,Onclicklistener,上下文: public interface OnTaskListener { void onTaskClick(int position); // Interfaces are implicitly abstract void onTaskLongClick(int position); } public class itemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, V

上下文:

public interface OnTaskListener {
    void onTaskClick(int position); // Interfaces are implicitly abstract
    void onTaskLongClick(int position);
}
public class itemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {

    View itmView; // This is the general view
    TextView txtView; // This is the specific text view that shows up as a singular task in the list of to-do tasks
    OnTaskListener onTaskListener; // Create an OnTaskListener inside our view holder which allows the view holder to realize it's been clicked

    public itemViewHolder(@NonNull View itemView, OnTaskListener inputOnTaskListener) {
        super(itemView);
        itmView = itemView;
        txtView = itemView.findViewById(R.id.txtTask);
        this.onTaskListener = inputOnTaskListener; // Take an onTaskListener that is passed into the object and store it internally
        itemView.setOnClickListener(this); // passes the View.OnClickListener context to the itemView via "this"
    }

    @Override
    public void onClick(View view) {
        onTaskListener.onTaskClick(getAdapterPosition()); // This says that whenever we register a click event, we pass the logic onto the taskClick event
    }

    @Override
    public boolean onLongClick(View view) {
        onTaskListener.onTaskLongClick(getAdapterPosition()); // This says that whenever we register a longClick event, we pass the logic onto the taskClick event
        return true; // This means that we have successfully consumed the long click event. No other click events will be notified
    }
}
我在我的待办事项列表应用程序中实现了一个RecyclerView

我希望能够对RecyclerView中的项使用各种onClick方法,因此我创建了一个名为onTaskListener的接口

此接口有两个方法存根,一个用于onClick,另一个用于onLongClick。在我的ViewHolder中,我实现了onClick()和onLongClick()方法,它们只是将控制权传递给我的onTaskClickListener()

在适配器中,我创建了一个onTaskClickListener()。 然后,在我的主要活动中,我实现了onTaskClickListener()中的方法

我的问题是,虽然我的onTaskClick()工作得很好,但我的onTaskLongClick似乎根本不起作用。我设置RecyclerView/Adapter/ViewHolder/ViewModel模式的方式是否有问题

问题:如果我实现界面的方式不正确,我如何在一个界面中包含多种类型的点击事件

以下是每个文件的相关内容(我知道这是很多,我很抱歉代码墙):

onTaskClickListener.java:

public interface OnTaskListener {
    void onTaskClick(int position); // Interfaces are implicitly abstract
    void onTaskLongClick(int position);
}
public class itemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {

    View itmView; // This is the general view
    TextView txtView; // This is the specific text view that shows up as a singular task in the list of to-do tasks
    OnTaskListener onTaskListener; // Create an OnTaskListener inside our view holder which allows the view holder to realize it's been clicked

    public itemViewHolder(@NonNull View itemView, OnTaskListener inputOnTaskListener) {
        super(itemView);
        itmView = itemView;
        txtView = itemView.findViewById(R.id.txtTask);
        this.onTaskListener = inputOnTaskListener; // Take an onTaskListener that is passed into the object and store it internally
        itemView.setOnClickListener(this); // passes the View.OnClickListener context to the itemView via "this"
    }

    @Override
    public void onClick(View view) {
        onTaskListener.onTaskClick(getAdapterPosition()); // This says that whenever we register a click event, we pass the logic onto the taskClick event
    }

    @Override
    public boolean onLongClick(View view) {
        onTaskListener.onTaskLongClick(getAdapterPosition()); // This says that whenever we register a longClick event, we pass the logic onto the taskClick event
        return true; // This means that we have successfully consumed the long click event. No other click events will be notified
    }
}
itemViewHolder.java:

public interface OnTaskListener {
    void onTaskClick(int position); // Interfaces are implicitly abstract
    void onTaskLongClick(int position);
}
public class itemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {

    View itmView; // This is the general view
    TextView txtView; // This is the specific text view that shows up as a singular task in the list of to-do tasks
    OnTaskListener onTaskListener; // Create an OnTaskListener inside our view holder which allows the view holder to realize it's been clicked

    public itemViewHolder(@NonNull View itemView, OnTaskListener inputOnTaskListener) {
        super(itemView);
        itmView = itemView;
        txtView = itemView.findViewById(R.id.txtTask);
        this.onTaskListener = inputOnTaskListener; // Take an onTaskListener that is passed into the object and store it internally
        itemView.setOnClickListener(this); // passes the View.OnClickListener context to the itemView via "this"
    }

    @Override
    public void onClick(View view) {
        onTaskListener.onTaskClick(getAdapterPosition()); // This says that whenever we register a click event, we pass the logic onto the taskClick event
    }

    @Override
    public boolean onLongClick(View view) {
        onTaskListener.onTaskLongClick(getAdapterPosition()); // This says that whenever we register a longClick event, we pass the logic onto the taskClick event
        return true; // This means that we have successfully consumed the long click event. No other click events will be notified
    }
}
dataAdapter.java

public class dataAdapter extends RecyclerView.Adapter<itemViewHolder> {

    List<taskItem> taskItemList;
    private OnTaskListener onTaskListener;

    public dataAdapter(List<taskItem> inputTaskItemList, OnTaskListener inputOnTaskListener){
        this.taskItemList = inputTaskItemList;
        this.onTaskListener = inputOnTaskListener;
    }

    @NonNull
    @Override
    public itemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View localView = LayoutInflater.from(parent.getContext()).inflate(R.layout.taskholder, parent, false); //Don't even know what this line does, it's all so over my head
        return new itemViewHolder(localView, onTaskListener); // Return an instance of whatever we made directly above this line
    }

    @Override
    public void onBindViewHolder(@NonNull itemViewHolder holder, final int position) {
        holder.txtView.setText(taskItemList.get(position).taskTitle);
        // Look inside our ViewModel and get the text for this specific instance of the ViewModel, which corresponds to the current position
    }

    @Override
    public int getItemCount() {
        return taskItemList.size();
    }
}
public class MainActivity extends AppCompatActivity implements OnTaskListener{
    private RecyclerView taskList; // Creates a RecyclerView to hook up to our RecyclerView widget in the UI
    private dataAdapter localAdapter; // Instantiates our custom adapter class
    List<taskItem> myItems; // Stores the items in a list of taskItem's
    private RecyclerView.LayoutManager localLayoutManager; // God knows what this does :(

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        taskList = findViewById(R.id.taskList); // Connects our list from UI to recycler view code
        localLayoutManager = new LinearLayoutManager(this); // assigns our localLayoutManager to an actual Layout Manager
        taskList.setLayoutManager(localLayoutManager); // connecting our layout manager to our recycler view
        taskList.setHasFixedSize(true);

        myItems = new ArrayList<>(); // Now we FINALLY make our to-do list and populate it with actual tasks
        myItems.add(new taskItem("groceries"));
        myItems.add(new taskItem("practice bjj"));

        localAdapter = new dataAdapter(myItems, this); // Pass the to do list to the adapter so it can feed it to the recycler view
        taskList.setAdapter(localAdapter); // Lastly set the recycler view's adapter to the one we made above
        
    }

    @Override
    public void onTaskClick(int position) {
        taskItem currentTask = myItems.get(position);
        if(!(currentTask.taskTitle.startsWith("Done: "))){ // Logic that marks a task as done on tap
            currentTask.taskTitle = "Done: " + currentTask.taskTitle;
            //logic that moves the tapped item to bottom of list
            myItems.remove(position);
            myItems.add(myItems.size(), currentTask);
            localAdapter.notifyItemMoved(position, myItems.size());
        }
        else if(myItems.get(position).taskTitle.startsWith("Done: ")){ // Logic for if user taps a task already marked "done"
            currentTask.taskTitle = currentTask.taskTitle.replaceFirst("Done: ", "");
            myItems.set(position, currentTask); // Remove prefix
            localAdapter.notifyItemChanged(position);
            myItems.remove(position);
            myItems.add(0, currentTask);
        }
        localAdapter.notifyDataSetChanged(); // Let the activity know that the data has changed
    }

    @Override
    public void onTaskLongClick(int position) { // This branch deals with deleting tasks on long click
        myItems.remove(position);
        localAdapter.notifyItemRemoved(position); // Item has been deleted
    }
}
公共类dataAdapter扩展了RecyclerView.Adapter{
列表任务项列表;
私有OnTaskListener OnTaskListener;
公共数据适配器(列表inputaskitemlist、OnTaskListener inputOnTaskListener){
this.taskItemList=inputaskitemlist;
this.onTaskListener=inputOnTaskListener;
}
@非空
@凌驾
public itemViewHolder onCreateViewHolder(@NonNull ViewGroup父级,int viewType){
View localView=LayoutInflater.from(parent.getContext()).inflate(R.layout.taskholder,parent,false);//我甚至不知道这行是干什么的,我都想不通了
return new itemViewHolder(localView,onTaskListener);//返回我们在这一行上直接创建的任何内容的实例
}
@凌驾
public void onBindViewHolder(@NonNull itemViewHolder,final int位置){
holder.txtView.setText(taskItemList.get(position.taskTitle));
//查看ViewModel内部,获取ViewModel的此特定实例的文本,该实例对应于当前位置
}
@凌驾
public int getItemCount(){
返回taskItemList.size();
}
}
MainActivity.java

public class dataAdapter extends RecyclerView.Adapter<itemViewHolder> {

    List<taskItem> taskItemList;
    private OnTaskListener onTaskListener;

    public dataAdapter(List<taskItem> inputTaskItemList, OnTaskListener inputOnTaskListener){
        this.taskItemList = inputTaskItemList;
        this.onTaskListener = inputOnTaskListener;
    }

    @NonNull
    @Override
    public itemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View localView = LayoutInflater.from(parent.getContext()).inflate(R.layout.taskholder, parent, false); //Don't even know what this line does, it's all so over my head
        return new itemViewHolder(localView, onTaskListener); // Return an instance of whatever we made directly above this line
    }

    @Override
    public void onBindViewHolder(@NonNull itemViewHolder holder, final int position) {
        holder.txtView.setText(taskItemList.get(position).taskTitle);
        // Look inside our ViewModel and get the text for this specific instance of the ViewModel, which corresponds to the current position
    }

    @Override
    public int getItemCount() {
        return taskItemList.size();
    }
}
public class MainActivity extends AppCompatActivity implements OnTaskListener{
    private RecyclerView taskList; // Creates a RecyclerView to hook up to our RecyclerView widget in the UI
    private dataAdapter localAdapter; // Instantiates our custom adapter class
    List<taskItem> myItems; // Stores the items in a list of taskItem's
    private RecyclerView.LayoutManager localLayoutManager; // God knows what this does :(

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        taskList = findViewById(R.id.taskList); // Connects our list from UI to recycler view code
        localLayoutManager = new LinearLayoutManager(this); // assigns our localLayoutManager to an actual Layout Manager
        taskList.setLayoutManager(localLayoutManager); // connecting our layout manager to our recycler view
        taskList.setHasFixedSize(true);

        myItems = new ArrayList<>(); // Now we FINALLY make our to-do list and populate it with actual tasks
        myItems.add(new taskItem("groceries"));
        myItems.add(new taskItem("practice bjj"));

        localAdapter = new dataAdapter(myItems, this); // Pass the to do list to the adapter so it can feed it to the recycler view
        taskList.setAdapter(localAdapter); // Lastly set the recycler view's adapter to the one we made above
        
    }

    @Override
    public void onTaskClick(int position) {
        taskItem currentTask = myItems.get(position);
        if(!(currentTask.taskTitle.startsWith("Done: "))){ // Logic that marks a task as done on tap
            currentTask.taskTitle = "Done: " + currentTask.taskTitle;
            //logic that moves the tapped item to bottom of list
            myItems.remove(position);
            myItems.add(myItems.size(), currentTask);
            localAdapter.notifyItemMoved(position, myItems.size());
        }
        else if(myItems.get(position).taskTitle.startsWith("Done: ")){ // Logic for if user taps a task already marked "done"
            currentTask.taskTitle = currentTask.taskTitle.replaceFirst("Done: ", "");
            myItems.set(position, currentTask); // Remove prefix
            localAdapter.notifyItemChanged(position);
            myItems.remove(position);
            myItems.add(0, currentTask);
        }
        localAdapter.notifyDataSetChanged(); // Let the activity know that the data has changed
    }

    @Override
    public void onTaskLongClick(int position) { // This branch deals with deleting tasks on long click
        myItems.remove(position);
        localAdapter.notifyItemRemoved(position); // Item has been deleted
    }
}
public类MainActivity扩展了AppCompatActivity实现了OnTaskListener{
private RecyclerView taskList;//创建一个RecyclerView以连接到UI中的RecyclerView小部件
私有dataAdapter localAdapter;//实例化自定义适配器类
List myItems;//将项目存储在taskItem的
private RecyclerView.LayoutManager localLayoutManager;//天知道这是怎么回事:(
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
taskList=findviewbyd(R.id.taskList);//将列表从UI连接到回收器视图代码
localLayoutManager=new LinearLayoutManager(this);//将localLayoutManager分配给实际的布局管理器
taskList.setLayoutManager(localLayoutManager);//将布局管理器连接到回收器视图
taskList.setHasFixedSize(true);
myItems=new ArrayList();//现在我们终于创建了待办事项列表,并用实际任务填充它
添加(新任务项(“杂货”);
添加(新任务项(“实践bjj”);
localAdapter=newdataadapter(myItems,this);//将待办事项列表传递给适配器,以便它可以将其提供给回收器视图
taskList.setAdapter(localAdapter);//最后将回收器视图的适配器设置为我们上面制作的适配器
}
@凌驾
公共void onTaskClick(内部位置){
taskItem currentTask=myItems.get(位置);
if(!(currentTask.taskTitle.startsWith(“Done:”){//将任务标记为点击完成的逻辑
currentTask.taskTitle=“完成:”+currentTask.taskTitle;
//将点击项移动到列表底部的逻辑
myItems。移除(位置);
添加(myItems.size(),currentTask);
localAdapter.notifyItemMoved(位置,myItems.size());
}
else if(myItems.get(position.taskTitle.startsWith(“Done:”){//if用户点击已标记为“Done”的任务的逻辑
currentTask.taskTitle=currentTask.taskTitle.replaceFirst(“完成:,”);
myItems.set(位置,当前任务);//删除前缀
localAdapter.notifyItemChanged(位置);
myItems。移除(位置);
添加(0,当前任务);
}
localAdapter.notifyDataSetChanged();//让活动知道数据已更改
}
@凌驾
public void onTaskLongClick(int位置){//此分支处理长时间单击时删除任务
myItems。移除(位置);
localAdapter.notifyItemRemoved(位置);//项已被删除
}
}
您从未打过电话:

或者,您可以通过内联整个
OnLongClickListener
(同样,对于
OnClickListener
),完全避免使用


这样就避免了让您的
itemViewHolder
类实现
OnLongClickListener
接口,并且不可能忘记调用
setOnLongClickListener()

我真不敢相信我错过了这个。谢谢。如果发生这种情况,我有没有办法让Android Studio警告我?或者这只是一个小心的问题?将
OnClickListener
实现直接传递给
setOnClickListener()
方法,而不是传入
。这样,侦听器的设置和侦听器本身就不存在了