recyclerview 中的手势检测器出现故障

Gesture detectors malfunctions in recyclerview

对于我的应用程序,我正在实现 recyclerview 以网格格式显示图像。
onlongPress 我需要删除多个项目。
onclick 我需要在新 activity 中显示点击的图像。

所以我用 SimpleOnGestureListener 来实现它。

首先我实现了 onLongPress 它工作 fine.But 如果我在 recyclerview 的其他地方长按而不是 image.I 通过放置条件 [=17 处理它,它返回 id 为 -1 =].
问题 1: 这是正确的做法还是我做错了什么?

接下来,我为点击实现了 onSingleTapUp。当我执行 onLongPress 时,也会调用 onSingleTapUp。我处理了它,我放置了一个标志来指示它的长按。
现在,如果我单击图像,onSingleTapUp 会被多次调用。例如:如果我第一次按 2 times.next 时间 6 并继续增加。
问题2:如何解决onSingleTapUponLongPress上被调用和onSingleTapUp被多次调用?

更新: MainActivity

`

 @Override
 public void onItemClicked(int position) {
    if (actionMode != null) {
        toggleSelection(position);
    }
}

private void toggleSelection(int position) {
    mAdapter.toggleSelection(position);
    int count = mAdapter.getSelectedItemCount();

    if (count == 0) {
        actionMode.finish();
    } else {
        actionMode.setTitle(String.valueOf(count));
        actionMode.invalidate();
    }
}

@Override
public boolean onItemLongClicked(int position) {
    if (actionMode == null) {
        actionMode = startSupportActionMode(actionModeCallback);
    }

    toggleSelection(position);

    return true;
}
private class ActionModeCallback implements ActionMode.Callback {
    @SuppressWarnings("unused")
    private final String TAG = ActionModeCallback.class.getSimpleName();

    @Override
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        mode.getMenuInflater().inflate (R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        return false;
    }

    @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
        switch (item.getItemId()) {
            case R.id.delete:
                // TODO: actually remove items
                Log.d(TAG, "Delete called");
                List<Integer> selectedItemPositions = mAdapter.getSelectedItems();
                int i;
                int currPos;
                for (i = (selectedItemPositions.size()) - 1; i >= 0; i--) {
                    currPos = selectedItemPositions.get(i);
                    mAdapter.removeData(currPos,filePath);
                }
                getDirectoryFiles();
                setUpRecyclerView();
                mode.finish();
                return true;

            default:
                return false;
        }
    }

    @Override
    public void onDestroyActionMode(ActionMode mode) {
        mAdapter.clearSelection();
        actionMode = null;

    }
}`

Adapter `

   public class GridAdapter  extends SelectableAdapter<GridAdapter.ViewHolder> {

List<images> mItems;
private ArrayList<String> filePath;
final Context mContext;

private ViewHolder.ClickListener clickListener;


public GridAdapter(Context context, ArrayList<String> fileName, ArrayList<String> filePath, ViewHolder.ClickListener clickListener) {
    super();
    this.clickListener = clickListener;
    this.filePath = filePath;
    mItems = new ArrayList<images>();
    this.mContext = context;
    for (int i = 0; i < fileName.size(); i++) {

        images img = new images();
        img.setName(fileName.get(i));
        img.setThumbnail(i);
        mItems.add(img);
    }
}

public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    View v = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.grid_item, parent, false);
   // View v = LayoutInflater.from(parent.getContext()).inflate(layout, parent, false);

    ViewHolder viewHolder = new ViewHolder(v,clickListener,mContext,filePath);
    return viewHolder;

}

@Override
public void onBindViewHolder(final ViewHolder viewHolder, int i) {

    // Decode the filepath with BitmapFactory followed by the position
    Bitmap bmp = null;
    try {
        bmp = decodeFile(new File(filePath.get(i)));
    } catch (IOException e) {
        e.printStackTrace();
    }
    //Picasso.with(mContext).load(new File(filePath.get(i))).into(viewHolder.imgThumbnail);
    // Set the decoded bitmap into ImageView
    viewHolder.imgThumbnail.setImageBitmap(bmp);

}

@Override
public int getItemCount() {
    return mItems.size();
}

public void removeData(int currPos, ArrayList<String> filePath) {

    File f=new File(filePath.get(currPos));
    f.delete();
}


public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener,
        View.OnLongClickListener {

    public ImageView imgThumbnail;

    private ClickListener listener;
    private Context mContext;
    private ArrayList<String> filePath;
    public int press_flag=0;

    public ViewHolder(View itemView, ClickListener listener,Context context,ArrayList<String> filePath) {
        super(itemView);
        imgThumbnail = (ImageView) itemView.findViewById(R.id.img_thumbnail);
        this.listener = listener;
        this.mContext=context;
        this.filePath=filePath;
        itemView.setOnClickListener(this);
        itemView.setOnLongClickListener(this);
      //  Log.v("method","viewholder constructor");
    }

    @Override
    public void onClick(View v) {
        if(press_flag==0) {
            Log.d("onclick", "Item clicked at position " + getPosition());
            int j = getPosition();
            Intent i = new Intent(mContext, image_preview.class);
            i.putExtra("j", j);
            i.putExtra("filepath", filePath.get(j));
            mContext.startActivity(i);
        }
        if (listener != null) {
            listener.onItemClicked(getPosition());
        }

    }

    @Override
    public boolean onLongClick(View v) {
        Log.d("Onlongclick", "Item long-clicked at position " + getPosition());

        if (listener != null) {
            return listener.onItemLongClicked(getPosition());
        }
        return false;
    }


    public interface ClickListener {
        public void onItemClicked(int position);

        public boolean onItemLongClicked(int position);
    }
}

}`

这个回答是关于OP遇到的第二个问题:从SimpleOnGestureListener切换到简单的OnClickListenerOnLongClickListener后,点击项目时,预览activity(应该在正常模式下显示)即使用户处于选择模式也会显示。


单击项目时实际上调用了两个位置。来自 ViewHolder(在适配器文件中):

    @Override
    public void onClick(View v) {
        if(press_flag==0) {
            Log.d("onclick", "Item clicked at position " + getPosition());
            int j = getPosition();
            Intent i = new Intent(mContext, image_preview.class);
            i.putExtra("j", j);
            i.putExtra("filepath", filePath.get(j));
            mContext.startActivity(i);
        }
        if (listener != null) {
            listener.onItemClicked(getPosition());
        }

    }

从听众那里,在这种情况下,您的 MainActivity:

@Override
public void onItemClicked(int position) {
    if (actionMode != null) {
        toggleSelection(position);
    }
}

那么,那里发生了什么?首先,您的 ViewHolder 的侦听器方法被调用。如果 press_flag 等于 0(我猜这是为了解决您的问题,并且始终如此),您将开始预览 activity。任何状况之下。然后,你通知MainActivity。这个MainActivity负责设置一个item是选中还是未选中,并且知道当前的选中状态。

这里有一个简单的解决方法:将预览起始代码移至 MainActivity。你的代码变成这样:

ViewHolder:

@Override
public void onClick(View v) {
    if (listener != null) {
        listener.onItemClicked(getPosition());
    }
}

MainActivity:

@Override
public void onItemClicked(int position) {
    // If we are already selecting something
    if (actionMode != null) {
        toggleSelection(position);
    } else { // Or if we're not
        Log.d("onclick", "Item clicked at position " + position);
        Intent i = new Intent(this, image_preview.class); // mContext is useless here as we already are in a Context
        i.putExtra("j", position);
        i.putExtra("filepath", mAdapter.getFilePath(position); // New method to create in the adapter
        startActivity(i); // Again, no need for an additional Context here
    }
}

Adater: 您需要一种从 MainActivity 获取文件路径的新方法,非常简单。您可能已经在 MainActivity

中获得了信息
public String getFilePath(int position) {
    return filePath.get(position); // You may need to check for position being valid (compare to 0 and filePath.size())
}