java - 在 RecyclerView 的单个界面中使用多个 onClick 方法

标签 java android oop android-recyclerview onclicklistener

上下文:

我在我的待办事项列表应用中实现了 RecyclerView。

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

该接口(interface)有两种方法 stub ,一种用于 onClick,一种用于 onLongClick。在我的 ViewHolder 中,我实现了 onClick() 和 onLongClick() 方法,它们只是将控制传递给我的 onTaskClickListener()。

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

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

问题:如果我实现界面的方式错误,如何在单个界面中包含多种类型的点击事件?

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

onTaskClickListener.java:

public interface OnTaskListener {
    void onTaskClick(int position); // Interfaces are implicitly abstract
    void onTaskLongClick(int position);
}

itemViewHolder.java:

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();
    }
}

MainActivity.java

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
    }
}

最佳答案

你从来不打电话setOnLongClickListener() :

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"

    // Add this line
    itemView.setOnLongClickListener(this); // passes the View.OnLongClickListener context to the itemView via "this"
}

或者,您可以通过内联整个 OnLongClickListener(对于 OnClickListener 也类似)来完全避免执行 this:

itemView.setOnLongClickListener(new View.OnLongClickListener() {
    @Override
    public boolean onLongClick(View v) {
        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 类实现 OnLongClickListener 接口(interface),并且不会忘记调用 setOnLongClickListener()

关于java - 在 RecyclerView 的单个界面中使用多个 onClick 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64057723/

相关文章:

java - 多种 View ,一种形式,不同的验证

java - 以编程方式读取由 Java 在 Internet Explorer 中打开的网页

android - 如何从 Android 联系人中获取名字和姓氏?

oop - 单一职责原则(SRP)和我的服务等级

java - 如何删除列及其基础数据而不将其隐藏在jtable中

java - Eclipse 在 Ubuntu 上找不到 Java

android - 从 Firebase Cloud Functions 调用 Facebook 图形 API

带有多个按钮的 Android ListView 自定义行与 OnClickListener 有问题,它会影响多个列表项

language-agnostic - "program to an interface"是什么意思?

c++ - 初始化列表、局部变量与数据成员