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的.为 ...
随机推荐
- 《温故而知新》JAVA基础一
一:基本环境 种类 javaSE(核心语法)+javaME(移动设备)+Java EE(JSP/服务等) JVM(java虚拟机) abc.java(源文件)--编译器--abc.class 字节码文 ...
- layui框架
layui框架 Fly社区/分享一个layui风格的grid.greegrid
- java笔记 -- 数学函数与常量
Math类中, 包含了各种数学函数 不用在数学方法名和常量名前添加前缀Math., 只要在源文件的顶部加上这行代码: import static java.lang.Math.*; (静态导入) 例: ...
- 力扣(LeetCode) 821. 字符的最短距离
给定一个字符串 S 和一个字符 C.返回一个代表字符串 S 中每个字符到字符串 S 中的字符 C 的最短距离的数组. 示例 1: 输入: S = "loveleetcode", C ...
- ES6标准之箭头函数
语法 具有一个参数的简单函数 var single = a => a single('hello, world') // 'hello, world' 没有参数的需要用在箭头前加上小括号 var ...
- docker 安装mysql示例
docker pull mysql 错误的启动: [root@localhost ~]# docker run --name mysql01 -d mysql 42f09819908bb72dd99a ...
- Idea破解注册码
Idea破解注册码 ThisCrackLicenseId-{ "licenseId":"ThisCrackLicenseId", "licenseeN ...
- MVC实战之排球计分(八)——软件制作总结
此系列博客目的是制作一款排球计分程序.这系列博客将讲述此软件的 各个功能的设计与实现.到这篇博客,此系列博客就算是结束了. 在最后的这篇博客里 我们来做一些总结. 一,制作此程序,我们使用的是MVC框 ...
- centos7安装doxygen
编译 编译过程参考官网:https://www.stack.nl/~dimitri/doxygen/download.html 编译过程: git clone https://github.com/d ...
- webstorm激活教程
虽然webStorm,phpStorm以及jetbrains系列的很好用,但是每隔一段时间就需要激活一下,这样太费劲了,今天军哥给大家推荐一个永久激活的办法 此教程适用于jetbrains 的所有系列 ...