- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我正在开发双指缩放 RecyclerView 并使双指缩放功能正常工作,但一旦放大,onItemClickListeners 就位于错误的位置。下面是修改后的 RecyclerView 的代码。我还做了一个 simple demo that is hosted on GitHub .在尝试演示时,当您单击一个项目时,您应该会看到一个 Toast,上面写着您单击的图标的编号。尝试不缩放,然后放大并重试以查看问题。我相信我需要通知 RecyclerView onItemClickListener 位置需要更新,但找不到正确的方法来覆盖。感谢您的帮助!
public class PinchRecyclerView extends RecyclerView {
private static final int INVALID_POINTER_ID = -1;
private int mActivePointerId = INVALID_POINTER_ID;
private ScaleGestureDetector mScaleDetector;
private float mScaleFactor = 1.f;
private float maxWidth = 0.0f;
private float maxHeight = 0.0f;
private float mLastTouchX;
private float mLastTouchY;
private float mPosX;
private float mPosY;
private float width;
private float height;
public PinchRecyclerView(Context context) {
super(context);
if (!isInEditMode())
mScaleDetector = new ScaleGestureDetector(getContext(), new ScaleListener());
}
public PinchRecyclerView(Context context, AttributeSet attrs) {
super(context, attrs);
if (!isInEditMode())
mScaleDetector = new ScaleGestureDetector(getContext(), new ScaleListener());
}
public PinchRecyclerView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
if (!isInEditMode())
mScaleDetector = new ScaleGestureDetector(getContext(), new ScaleListener());
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
width = View.MeasureSpec.getSize(widthMeasureSpec);
height = View.MeasureSpec.getSize(heightMeasureSpec);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
try {
return super.onInterceptTouchEvent(ev);
} catch (IllegalArgumentException ex) {
ex.printStackTrace();
}
return false;
}
@Override
public boolean onTouchEvent(@NonNull MotionEvent ev) {
super.onTouchEvent(ev);
final int action = ev.getAction();
mScaleDetector.onTouchEvent(ev);
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
final float x = ev.getX();
final float y = ev.getY();
mLastTouchX = x;
mLastTouchY = y;
mActivePointerId = ev.getPointerId(0);
break;
}
case MotionEvent.ACTION_MOVE: {
final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK)
>> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final float x = ev.getX(pointerIndex);
final float y = ev.getY(pointerIndex);
final float dx = x - mLastTouchX;
final float dy = y - mLastTouchY;
mPosX += dx;
mPosY += dy;
if (mPosX > 0.0f)
mPosX = 0.0f;
else if (mPosX < maxWidth)
mPosX = maxWidth;
if (mPosY > 0.0f)
mPosY = 0.0f;
else if (mPosY < maxHeight)
mPosY = maxHeight;
mLastTouchX = x;
mLastTouchY = y;
invalidate();
break;
}
case MotionEvent.ACTION_UP: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_CANCEL: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_POINTER_UP: {
final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int pointerId = ev.getPointerId(pointerIndex);
if (pointerId == mActivePointerId) {
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mLastTouchX = ev.getX(newPointerIndex);
mLastTouchY = ev.getY(newPointerIndex);
mActivePointerId = ev.getPointerId(newPointerIndex);
}
break;
}
}
return true;
}
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.translate(mPosX, mPosY);
canvas.scale(mScaleFactor, mScaleFactor);
canvas.restore();
}
@Override
protected void dispatchDraw(@NonNull Canvas canvas) {
canvas.save(Canvas.MATRIX_SAVE_FLAG);
if (mScaleFactor == 1.0f) {
mPosX = 0.0f;
mPosY = 0.0f;
}
canvas.translate(mPosX, mPosY);
canvas.scale(mScaleFactor, mScaleFactor);
super.dispatchDraw(canvas);
canvas.restore();
invalidate();
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScale(ScaleGestureDetector detector) {
mScaleFactor *= detector.getScaleFactor();
mScaleFactor = Math.max(1.0f, Math.min(mScaleFactor, 3.0f));
maxWidth = width - (width * mScaleFactor);
maxHeight = height - (height * mScaleFactor);
invalidate();
return true;
}
}
}
最佳答案
更新我认为最好将修改分散到您的几个类(class)中。 Here是指向 PinchRecyclerView.java
的链接,其中包含所有需要的更改。我将在下面留下整个项目的链接,以防它有其他用途。
您只是在更改 Canvas 上的显示,而不是像 azizbekian 在他的评论中所说的那样更改底层 View 。如果您不想使用自定义 GridLayoutManager
并继续使用您已经开始的方法,您将需要将屏幕触摸映射回您的底层 View 。
这是您的 updated project在做映射的 GitHub 上。以下是基本更改:
向 PinchRecyclerView
添加触摸监听器。
将 PinchRecyclerView
上的触摸坐标转换为底层布局中的相应位置。
通过搜索预期的项目 View 来识别并进行点击处理。
如果您尝试这个更新后的应用,并且正如您在视频中看到的那样,触摸监听器也会在捏合时触发,所以这是一个错误。
关于android - RecyclerView 调整大小后 onItemClickListeners 行为异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44435543/
类型new AdapterView.OnItemClickListener(){}必须实现继承的抽象方法AdapterView.OnItemClickListener.onItemClick(Adap
当我在以下位置输入此代码时,出现“OnItemClickListener 无法解析为类型”的错误: package com.funkystudios.android.facts; import and
我已经检查过解决方案 here , here , here和 here 。它们都不适合我。 我的问题如下:我有一个仅由复选框组成的 ListView。我想在单击复选框后立即将相关复选框的当前状态保存到
我在 Android Studio 中设置了一个 Listview,但需要帮助编写 OnItemClickListner。 我已经尝试过该代码,但似乎不起作用。 public class MainAc
啊,我在这里做错了什么我已经为 ListView 和 onClick 设置了 onItemClickListener将它带到不同的 Activity ,但它告诉我它必须使用 OnItemClickli
我有一个 fragment ,其中包含一个 recyclerview,它有一个交错的网格布局管理器,其中 View 持有者只有一个图像。我试图在选择菜单选项(删除图标)后为 recyclerView
DataAccess data = new DataAccess(db); List countries = data.getCountries(); setListAdapter(new Array
我正在寻求构建一个程序,让用户从文本列表中点击,这会将他们带到另一个 Activity 。 我知道 RecyclerView 没有点击监听器,就像 ListView 一样,但是经过几次尝试,我无法让它
我想要 OnitemClickListener 用于 listview 但它对我不起作用。它给 Logcat 错误。 您的内容必须有一个 ListView ,其 id 属性为 R.id.list 我的
我在 GridView 中有一个 ItemClickListener。但是我的 itemclicklistener 没有被调用。 gridview 的项目点击没有 Activity @Override
我有两个列表,一个是自定义适配器,另一个是数组适配器。所以我希望 onItemClickListener 与自定义适配器 ListView 一起使用,并且当我开始对数组适配器使用相同的 ListVie
我有一个药物列表,当用户点击其中一个药物时,它将转到下一个显示药物详细信息的 Activity .. 下面的代码是带有药物列表的 Activity ..我知道我必须使用onclicklistener.
我认为这个问题说明了一切:我想为 ListView 创建自定义 OnItemClickListener。我想添加和更改 OnItemClickListener 的参数,但我如何创建自己的参数以便在我单
我有一个列表 fragment 显示我的自定义列表项,它由包含图像和文本等的相对布局组成。
我在类中有两个 listview,我不想为每个 listview 实现 OnClickListener,而是希望类实现 OnClickListener 并在单个覆盖方法 OnClickListener
我想在此 ListView 中实现 OnItemClickListener ,但是当我为此添加代码时,即使没有错误,我的应用程序也无法运行。当我单击 Listview 项目时,它会自动关闭。请帮助我,
我正在申请。我想从网络上的 Json 文件中获取一些信息。这行得通。现在我想要一个 onItemClickListener 到带有内容的 ListView 的项目。 onItemClickListen
我在从 ListItems 中获取选定的字符串时遇到一个问题,例如:考虑我的 ListItem 有一些元素只是被认为是一个,两个,三个出现在我的 taskLit 中,现在如果我点击 ListItem
我为 AutoCompleteTextView 设置了 setOnItemClickListener,并在 onItemClick 中,我已经根据所选值实现了需要发生的情况。该程序通过查看所选项目的索
我是 Android 开发的新手,我正在尝试构建一个 ListView,它使用 gson 从 Web 服务获取数据。我有一个模型类、一个列表类、一个适配器类和一个 Activity 类。 该列表工作正
我是一名优秀的程序员,十分优秀!