android - 处理Adapter/ViewHolder中的点击事件

标签 android android-adapter android-viewholder android-popupwindow

目前: 我正在我的 Adapter 中实现点击事件onBindViewHolder里面,但我注意到这样做时适配器位置会变得困惑。我做了一些研究,发现this ,他说:

As for why it is better in the ViewHolder instead of in onBindViewHolder(), that is because onBindViewHolder() is called for each and every item and setting the click listener is an unnecessary option to repeat when you can call it once in your ViewHolder constructor.

他引用的示例如下所示:

public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnItemClickListener {
   public MyViewHolder(View view) {
      super(view);

      view.setOnClickListener(this);
   }

   @Override
   public void OnClick(View view) {
      // Get the item clicked
      // For this example, I'm assuming your data source is of type `List<MyObject>`
      MyObject myObject = mDataSource.get(getAdapterPosition());
      // Then you can do any actions on it, for example - 
      myObject.setChecked();
   }
}

这对我来说很有意义,但我的问题是我有一个 ImageButton在我的里面ViewHolder他的示例仅显示如何处理 ViewHolder 的点击事件本身。请先看看我的适配器当前的样子:

public class MyAdapter extends Adapter<MyAdapter.ViewHolder> {
    ArrayList<Bitmap> bitmapArrayList;
    Context context;
    LayoutInflater layoutInflater;
    View myLayoutView;
    ArrayList<PathModel> swingThumbPathList;
    ArrayList<PathModel> swingVideoPathList = new ArrayList();

    class ViewHolder extends android.support.v7.widget.RecyclerView.ViewHolder {
        TextView name;
        CircularImageView image;
        ImageButton viewholderOtions;

        ViewHolder(View itemView) {
            super(itemView);
        }
    }

    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        this.myLayoutView = LayoutInflater.from(this.context).inflate(R.layout.single_item, parent, false);
        return new ViewHolder(this.myLayoutView);
    }

    public void onBindViewHolder(ViewHolder myHolder, final int position) {
        final ViewHolder holder = myHolder;
        holder.viewholderOtions = (ImageButton) myLayoutView.findViewById(R.id.viewholderOptions);
        holder.name = (TextView) this.myLayoutView.findViewById(R.id.name);
        holder.image = (CircularImageView) this.myLayoutView.findViewById(R.id.image);
        holder.name.setText(Model.getPath());
        holder.image.setImageURI(Uri.parse(Model.getPath()));

        holder.viewholderOtions.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                Toast.makeText(holder.itemView.getContext(), "Options was clicked", Toast.LENGTH_LONG).show();

                showPopupMenu(holder.viewholderOtions, position);

            }
        });

        holder.itemView.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                String uri = holder.name.getText().toString();

                Toast.makeText(holder.itemView.getContext(), uri, Toast.LENGTH_LONG).show();
            }


        });

    }

    private void showPopupMenu(final View view, final int position) {
        // inflate menu
        PopupMenu popup = new PopupMenu(view.getContext(), view);
        MenuInflater inflater = popup.getMenuInflater();
        inflater.inflate(R.menu.popup_menu, popup.getMenu());
        popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {

            @Override
            public boolean onMenuItemClick(MenuItem item) {
                switch (item.getItemId()) {
                    case R.id.delete:
                        //The correct position is being toasted
                        Toast.makeText(view.getContext(), position + "Delete", Toast.LENGTH_LONG).show();

                        return true;
                    case R.id.rename:
                        Toast.makeText(view.getContext(), "Rename", Toast.LENGTH_LONG).show();

                        return true;

                    default:

                        return true;
                }
            }

        });

        popup.show();
    }

我的问题

如何处理 ViewHolder 的点击事件本身和 ImageButton ViewHolder里面?

最佳答案

我回顾这个问题时笑了,所以在大约两年后回答了我自己的问题。

使用问题中提供的相同逻辑,这就是您如何将点击事件设置为 View 本身以及 View 内、viewholder 内的元素,而不是 onBindViewHolder

public class MyAdapter extends Adapter<MyAdapter.ViewHolder> {
    ArrayList<Bitmap> bitmapArrayList;
    Context context;
    LayoutInflater layoutInflater;
    View myLayoutView;
    ArrayList<PathModel> swingThumbPathList;
    ArrayList<PathModel> swingVideoPathList = new ArrayList();

    class ViewHolder extends android.support.v7.widget.RecyclerView.ViewHolder {
        TextView name;
        CircularImageView image;
        ImageButton viewholderOtions;

        ViewHolder(View itemView) {
            super(itemView);
            viewholderOtions = itemView.findViewById(R.id.viewholderOptions);
            videoName = itemView.findViewById(R.id.FilePath);
            videoThumb = itemView.findViewById(R.id.VideoThumbnail);
            //set OnClickListener's for the views we want click events for 
            itemView.setOnClickListener(this);
            viewholderOtions.setOnClickListener(this);
            videoThumb.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            //get the tag that we have set in onBindViewHolder
            int position = (int) v.getTag();
            if (v == viewholderOtions) {
                //viewholderOtions was selected, we can use the position above to see what item, as shown below:
                Log.e("viewholderOtions at position =", String.valueOf(position);
            }
            if (v == itemView){
                //itemView was selected, we can use the position above to see what item, as shown below:
                Log.e("itemView at position =", String.valueOf(position);
            }
            if (v == videoThumbvideoThumb){
                //itemView was selected, we can use the position above to see what item, as shown below:
                Log.e("videoThumbvideoThumb at position =", String.valueOf(position);
            }
        }


    }

    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        this.myLayoutView = LayoutInflater.from(this.context).inflate(R.layout.single_item, parent, false);
        return new ViewHolder(this.myLayoutView);
    }

    public void onBindViewHolder(ViewHolder myHolder, final int position) {
        //set a tag so we can retrieve the position via the tag
        myHolder.viewholderOtions.setTag(position);

        //Set text to holder.name
        holder.name.setText(Model.getPath());
        //a better option to below is to use a library like picasso to handle the image loading
        holder.image.setImageURI(Uri.parse(Model.getPath()));       

    }

}

但说实话,我仍然在 onBindViewHolder 中设置了点击事件,然后我只是将以下内容设置到我的 Activity 中的 RecyclerView - recyclerView.setHasFixedSize(true);。通过这样做,位置不会变得困惑,正如我的问题中所述。

关于android - 处理Adapter/ViewHolder中的点击事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45546739/

相关文章:

android - 嵌套 RecyclerView 一次创建所有 ViewHolders

当用户停止移动相机时,Android google maps v2 执行异步任务

java - Kotlin - list 合并失败 : Attribute application@appComponentFactory

android - 在不重新填充的情况下更新 GridView/ListView

java - 在 View 持有者中使用if else禁用edittext android

Android recyclerView 重复滚动项目

android - 如何使用专用 ssid 和密码在 Android 中为 Wifi Direct 创建自主 GO?

java - 动态资源名称

android - 几秒钟后如何删除 ListView 项目?

java - 在 CustomAdapter 内调用 BaseAdapter 的 notificationDataSetChanged() 不刷新 ListView