android ListView 可缩放,支持左右上下手势
public class ZoomListView extends ListView implements SwipeListener {
public static enum Action {
LeftToRight,
RightToLeft,
TopToBottom,
BottomToTop,
None
}
private List<SwipeListener> actionListeners = new ArrayList<SwipeListener>();
private boolean SwipeFlag = false;
private static final int HORIZONTAL_MIN_DISTANCE = 30; // The minimum
private static final int VERTICAL_MIN_DISTANCE = 80; // The minimum distance
private float downX, downY, upX, upY; // Coordinates
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 ZoomListView(Context context) {
super(context);
mScaleDetector = new ScaleGestureDetector(getContext(), new ScaleListener());
}
public ZoomListView(Context context, AttributeSet attrs) {
super(context, attrs);
mScaleDetector = new ScaleGestureDetector(getContext(), new ScaleListener());
}
public ZoomListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mScaleDetector = new ScaleGestureDetector(getContext(), new ScaleListener());
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
width = MeasureSpec.getSize(widthMeasureSpec);
height = MeasureSpec.getSize(heightMeasureSpec);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@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);
downX = ev.getX();
downY = ev.getY();
SwipeFlag = true;
break;
}
case MotionEvent.ACTION_MOVE: {
final int pointerIndex = ev.findPointerIndex(mActivePointerId);
final float x = ev.getX(pointerIndex);
final float y = ev.getY(pointerIndex);
final float dx = x - mLastTouchX;
final float dy = y - mLastTouchY;
float leftMargin = Math.abs(mPosX) / mScaleFactor;
float rightMargin = this.getMeasuredWidth() - Math.abs(mPosX) / mScaleFactor;
rightMargin -= this.getResources().getDisplayMetrics().widthPixels / mScaleFactor ;
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();
upX = ev.getX();
upY = ev.getY();
float deltaX = downX - upX;
float deltaY = downY - upY;
// horizontal swipe detection
if (Math.abs(deltaX) > HORIZONTAL_MIN_DISTANCE) {
// left or right
if (deltaX < 0 && SwipeFlag && leftMargin < 10) {
SwipeFlag = false;
OnAction(Action.LeftToRight);
break;
}
if (deltaX > 0 && SwipeFlag && rightMargin < 10) {
SwipeFlag = false;
OnAction(Action.RightToLeft);
break;
}
} else
{
// vertical swipe detection
if (Math.abs(deltaY) > VERTICAL_MIN_DISTANCE) {
// top or down
if (deltaY < 0 && SwipeFlag) {
SwipeFlag = false;
OnAction(Action.TopToBottom);
break;
}
if (deltaY > 0 && SwipeFlag) {
SwipeFlag = false;
OnAction(Action.BottomToTop);
break;
}
}
}
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;
}
}
@Override
public void OnAction(Action action) {
for(SwipeListener listener : actionListeners){
listener.OnAction(action);
}
}
public void addActionListener(SwipeListener listener)
{
actionListeners.add(listener);
}
}
public interface SwipeListener extends EventListener {
public void OnAction(Action action);
}
如果想ListView中显示图片且自适应,需要设置 android:adjustViewBounds="true"
android ListView 可缩放,支持左右上下手势的更多相关文章
- Android viewpager + 可缩放的imageview
http://files.cnblogs.com/files/liaolandemengxiang/PhotoWallFallsDemo.rar http://files.cnblogs.com/fi ...
- Android基础新手教程——3.8 Gestures(手势)
Android基础新手教程--3.8 Gesture(手势) 标签(空格分隔): Android基础新手教程 本节引言: 周六不歇息,刚剪完了个大平头回来.继续码字~ 好的,本节给大家带来点的是第三章 ...
- Android:让WebView支持<input type=”file”…>元素
最近在做一个活动页面:用户上传一张图片进行缩放.旋转后点击下一步填写内容后生成图片! 做好后经过各种测试是没有问题的,基本没有什么明显BUG,流程都能走通,但是嵌入到APP后,问题就来了! 在IOS上 ...
- android ListView 九大重要属性详细分析、
android ListView 九大重要属性详细分析. 1.android ListView 一些重要属性详解,兄弟朋友可以参考一下. 首先是stackFromBottom属性,这只该属性之后你做好 ...
- 【腾讯Bugly干货分享】Android ListView与RecyclerView对比浅析--缓存机制
本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/5811d3e3ab10c62013697408 作者:黄宁源 一,背景 Recy ...
- 【转】android ListView 几个重要属性
android ListView 几个重要属性 分类: Android2012-03-08 19:25 19324人阅读 评论(5) 收藏 举报 listviewandroid活动javalistnu ...
- Android listview viewpager解决冲突 滑动
Android listview viewpager滑动 跳动 冲突解决 ListView中嵌套ViewPage有或者滑动手势冲突解决 在listview 上使用 addHeaderView 在第 ...
- android listview中item通过viewpager实现《IT蓝豹》
android listview中item通过viewpager实现 android listview中item通过viewpager实现,每一个item都支持viewpager实现图片切换功能.本项 ...
- Android ListView滚动条配置完全解析
滚动条的相关显示效果 先来看下ListView的滚动条有哪些显示效果. 滚动条自身的外观 这点不用说,就是滚动条自身的颜色,形状等. Track的外观 默认的ListView是没有设置Track的.为 ...
随机推荐
- 拼接字符串,生成tree格式的JSON数组
之前做的执法文书的工作,现在需要从C#版本移植到网页版,从Thrift接口获取数据,加载到对应的控件中 之前用的easyui的Tree插件,通过<ul><li><span ...
- POJ 1088 滑雪(模板题 DFS+记忆化)
Description Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道 ...
- VSCode+python插件
1.打开VSCode 点击箭头所指地方 然后输入python 安装截图所示的插件 2.进行python路径设置 点击文件--首选项--设置 点击... 会弹出一个下拉框 选择打开setting.jso ...
- pta-3
一:实验代码 include <stdio.h> int main() { char ch; int income=0; int unhappy, sad, glad; unhappy = ...
- script利用src引用外部js文件,如果内部嵌套了js代码呢
<script src='test.js' defer async> var a = 5; </script> 这个时候 var a = 5;会被忽略.
- SQL SERVER 连接查询(join...on...)
SQL SERVER联结查询包含inner join,left join,right join,outer join (on)四种. [inner join]:行数为满足条件n*m,并且on的条件对两 ...
- CSS清除浮动的方法及优缺点
浮动是CSS布局里面用的比较多的属性.浮动的框向左或向右移动,直到它的外边缘碰到包含框或另一个浮动框的边框为止. 因为浮动会使当前元素产生向上浮的效果,所以浮动的元素会脱离正常的文档流,它包围的内容在 ...
- DataSet select 的使用
1) Select()——获取所有 System.Data.DataRow 对象的数组. 2) Select(string filterExpression)——按照主键顺序(如果没有主键,则按照添加 ...
- Loadrunner加密算法脚本与token作为get请求url上的参数处理
1.当字符串被封装好加密时(下例将算法封装在md5中),使用Loadrunner编写脚本,需要进行如下操作: 1)将md5.h文件添加到Extra Files 下,如图(Loadrunne ...
- python----操作文本文件
一.文本文件基本操作 1.1 打开文本文件,得到文件句柄并赋值给一个变量 f = open('test', 'r', encoding='utf-8') # 默认打开模式为r 文件路径:相对路径.绝对 ...