Android 刷卡使用 SwipeFlingAdapterView 库缩放图像视图
Posted
技术标签:
【中文标题】Android 刷卡使用 SwipeFlingAdapterView 库缩放图像视图【英文标题】:Android swipe card with pinch to zoom imageview using SwipeFlingAdapterView library 【发布时间】:2016-09-03 05:46:24 【问题描述】:我正在使用 this 库实现 swipe card
和 pinch to zoom
功能,当我只使用 image view
时它工作正常意味着滑动工作正常但我想要像库和 pinch to zoom
这样的滑动功能所以我添加了 TouchImageView
类,其中只有 pinch to zoom
工作但滑动功能不起作用。那么您能否帮我解决这个问题或建议我使用swipe card
和pinch to zoom
可能的任何替代库。
以下是我的活动
public class MainActivity extends AppCompatActivity
private SwipeFlingAdapterView flingContainer;
public static ArrayList<SwipModel> al;
public SwipViewAdapter swipViewAdapter;
private SwipModel swipModel;
private Uri uri;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getId();
setSwipeCard();
private void getId()
flingContainer = (SwipeFlingAdapterView) findViewById(R.id.frame);
private void setSwipeCard()
uri = Uri.parse("android.resource://" + getApplicationContext().getPackageName() + "/drawable/picture1");
swipModel = new SwipModel();
al = new ArrayList<>();
swipModel.setCardImageDrawable(uri);
al.add(swipModel);
swipViewAdapter = new SwipViewAdapter(getApplicationContext(), al);
flingContainer.setAdapter(swipViewAdapter);
flingContainer.setFlingListener(new SwipeFlingAdapterView.onFlingListener()
@Override
public void removeFirstObjectInAdapter()
// this is the simplest way to delete an object from the Adapter (/AdapterView)
Log.d("LIST", "removed object!");
// al.remove(0);
// swipViewAdapter.notifyDataSetChanged();
@Override
public void onLeftCardExit(Object dataObject)
//Do something on the left!
//You also have access to the original object.
//If you want to use it just cast it (String) dataObject
// makeToast(MainActivity.this, "Left!");
@Override
public void onRightCardExit(Object dataObject)
// makeToast(MainActivity.this, "Right!");
@Override
public void onAdapterAboutToEmpty(int itemsInAdapter)
// Ask for more data here
// al = new ArrayList<>();
// swipModel.setCardImageDrawable(uri);
// al.add(swipModel);
@Override
public void onScroll(float scrollProgressPercent)
View view = flingContainer.getSelectedView();
);
// Optionally add an OnItemClickListener.
flingContainer.setOnItemClickListener(new SwipeFlingAdapterView.OnItemClickListener()
@Override
public void onItemClicked(int itemPosition, Object dataObject)
);
这里是activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_
android:layout_
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context="com.example.android.swipecardtesting.MainActivity">
<com.lorentzos.flingswipe.SwipeFlingAdapterView
android:id="@+id/frame"
android:background="#ffeee9e2"
android:layout_
android:layout_
app:rotation_degrees="15.5"
tools:context=".MyActivity"
android:layout_centerInParent="true"
/>
</RelativeLayout>
这是我的Adapter
public class SwipViewAdapter extends BaseAdapter
public static ArrayList<SwipModel> list;
Context context;
private LayoutInflater l_Inflater;
public static ViewHolder holder;
public SwipViewAdapter(Context mContext, ArrayList<SwipModel> al)
this.context = mContext;
list = al;
l_Inflater = LayoutInflater.from(context);
@Override
public int getCount()
return list.size();
@Override
public Object getItem(int i)
return i;
@Override
public long getItemId(int i)
return i;
@Override
public View getView(int i, View view, ViewGroup viewGroup)
if (view == null)
holder = new ViewHolder();
l_Inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = l_Inflater.inflate(R.layout.swip_item, viewGroup, false);
holder.ivZoomable = (TouchImageView) view.findViewById(R.id.ivZoomable);
view.setTag(holder);
holder.ivZoomable.setImageURI(list.get(i).getCardImageDrawable());
return view;
public static class ViewHolder
public static TouchImageView ivZoomable;
还有我的TouchImageView
班级
public class TouchImageView extends ImageView
Matrix matrix;
// We can be in one of these 3 states
static final int NONE = 0;
static final int DRAG = 1;
static final int ZOOM = 2;
int mode = NONE;
// Remember some things for zooming
PointF last = new PointF();
PointF start = new PointF();
float minScale = 1f;
float maxScale = 3f;
float[] m;
int viewWidth, viewHeight;
static final int CLICK = 3;
public static float saveScale = 1f;
protected float origWidth, origHeight;
int oldMeasuredWidth, oldMeasuredHeight;
ScaleGestureDetector mScaleDetector;
Context context;
public TouchImageView(Context context)
super(context);
sharedConstructing(context);
public TouchImageView(Context context, AttributeSet attrs)
super(context, attrs);
sharedConstructing(context);
private void sharedConstructing(Context context)
super.setClickable(true);
this.context = context;
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
matrix = new Matrix();
m = new float[9];
setImageMatrix(matrix);
setScaleType(ScaleType.MATRIX);
setOnTouchListener(new OnTouchListener()
@Override
public boolean onTouch(View v, MotionEvent event)
mScaleDetector.onTouchEvent(event);
PointF curr = new PointF(event.getX(), event.getY());
switch (event.getAction())
case MotionEvent.ACTION_DOWN:
last.set(curr);
start.set(last);
mode = DRAG;
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG)
float deltaX = curr.x - last.x;
float deltaY = curr.y - last.y;
float fixTransX = getFixDragTrans(deltaX, viewWidth,
origWidth * saveScale);
float fixTransY = getFixDragTrans(deltaY, viewHeight,
origHeight * saveScale);
matrix.postTranslate(fixTransX, fixTransY);
fixTrans();
last.set(curr.x, curr.y);
break;
case MotionEvent.ACTION_UP:
mode = NONE;
int xDiff = (int) Math.abs(curr.x - start.x);
int yDiff = (int) Math.abs(curr.y - start.y);
if (xDiff < CLICK && yDiff < CLICK)
performClick();
break;
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
break;
setImageMatrix(matrix);
invalidate();
return true; // indicate event was handled
);
public void setMaxZoom(float x)
maxScale = x;
private class ScaleListener extends
ScaleGestureDetector.SimpleOnScaleGestureListener
@Override
public boolean onScaleBegin(ScaleGestureDetector detector)
mode = ZOOM;
return true;
@Override
public boolean onScale(ScaleGestureDetector detector)
float mScaleFactor = detector.getScaleFactor();
float origScale = saveScale;
saveScale *= mScaleFactor;
if(saveScale<1)
Log.e("saveScale is ","executing =====> "+saveScale);
SwipViewAdapter.ViewHolder.imageView.setVisibility(VISIBLE);
SwipViewAdapter.ViewHolder.ivZoomable.setVisibility(GONE);
else
Log.e("saveScale is ","executing =====> "+saveScale);
SwipViewAdapter.ViewHolder.imageView.setVisibility(GONE);
SwipViewAdapter.ViewHolder.ivZoomable.setVisibility(VISIBLE);
if (saveScale > maxScale)
saveScale = maxScale;
mScaleFactor = maxScale / origScale;
else if (saveScale < minScale)
saveScale = minScale;
mScaleFactor = minScale / origScale;
if (origWidth * saveScale <= viewWidth
|| origHeight * saveScale <= viewHeight)
matrix.postScale(mScaleFactor, mScaleFactor, viewWidth / 2,
viewHeight / 2);
else
matrix.postScale(mScaleFactor, mScaleFactor,
detector.getFocusX(), detector.getFocusY());
fixTrans();
return true;
void fixTrans()
matrix.getValues(m);
float transX = m[Matrix.MTRANS_X];
float transY = m[Matrix.MTRANS_Y];
float fixTransX = getFixTrans(transX, viewWidth, origWidth * saveScale);
float fixTransY = getFixTrans(transY, viewHeight, origHeight
* saveScale);
if (fixTransX != 0 || fixTransY != 0)
matrix.postTranslate(fixTransX, fixTransY);
float getFixTrans(float trans, float viewSize, float contentSize)
float minTrans, maxTrans;
if (contentSize <= viewSize)
minTrans = 0;
maxTrans = viewSize - contentSize;
else
minTrans = viewSize - contentSize;
maxTrans = 0;
if (trans < minTrans)
return -trans + minTrans;
if (trans > maxTrans)
return -trans + maxTrans;
return 0;
float getFixDragTrans(float delta, float viewSize, float contentSize)
if (contentSize <= viewSize)
return 0;
return delta;
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
viewWidth = MeasureSpec.getSize(widthMeasureSpec);
viewHeight = MeasureSpec.getSize(heightMeasureSpec);
//
// Rescales image on rotation
//
if (oldMeasuredHeight == viewWidth && oldMeasuredHeight == viewHeight
|| viewWidth == 0 || viewHeight == 0)
return;
oldMeasuredHeight = viewHeight;
oldMeasuredWidth = viewWidth;
if (saveScale == 1)
// Fit to screen.
float scale;
Drawable drawable = getDrawable();
if (drawable == null || drawable.getIntrinsicWidth() == 0
|| drawable.getIntrinsicHeight() == 0)
return;
int bmWidth = drawable.getIntrinsicWidth();
int bmHeight = drawable.getIntrinsicHeight();
Log.d("bmSize", "bmWidth: " + bmWidth + " bmHeight : " + bmHeight);
float scaleX = (float) viewWidth / (float) bmWidth;
float scaleY = (float) viewHeight / (float) bmHeight;
scale = Math.min(scaleX, scaleY);
matrix.setScale(scale, scale);
// Center the image
float redundantYSpace = (float) viewHeight
- (scale * (float) bmHeight);
float redundantXSpace = (float) viewWidth
- (scale * (float) bmWidth);
redundantYSpace /= (float) 2;
redundantXSpace /= (float) 2;
matrix.postTranslate(redundantXSpace, redundantYSpace);
origWidth = viewWidth - 2 * redundantXSpace;
origHeight = viewHeight - 2 * redundantYSpace;
setImageMatrix(matrix);
fixTrans();
【问题讨论】:
也许这可以帮助你:***.com/questions/11672210/… @Abbas 感谢您的回复。我按你说的试过了,还是不行。 尝试从onTouch
返回false
,如果saveScale != 1
,则应该传递触摸事件。
提示:你需要在 TouchImageView 中的 onTouchEvent 返回 false 才能让滑动生效。
【参考方案1】:
当只有一个指针向下时,在 TouchImageView
类中的 OnTouchListener.onTouch()
中返回 false
,如下所示:
@Override
public boolean onTouch(View v, MotionEvent event)
// Touch logic here
return event.getPointerCount() > 1;
这种方式捏到缩放只会在两个指针存在时消耗触摸事件(需要执行捏合)。
更新:
扩展SwipeFlingAdapterView
类并覆盖onInterceptTouchEvent()
方法,就像在这里完成的那样:Using onInterceptTouchEvent
然后你可以像这样拦截指向图像视图的触摸事件:
public void onInterceptTouchEvent(MotionEvent event)
if(event.getPointerCount() == 1)
onTouchEvent(event);
return false;
更多关于触摸拦截的文档:https://developer.android.com/training/gestures/viewgroup.html
希望对你有帮助!
【讨论】:
感谢您的帮助,我将您的代码放在了 TouchImageView 类的 onTouch 中,但滑动功能仍然不起作用,只有捏缩放可以工作,但实际上我还需要捏缩放和滑动功能。跨度>以上是关于Android 刷卡使用 SwipeFlingAdapterView 库缩放图像视图的主要内容,如果未能解决你的问题,请参考以下文章