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的.为 ...
随机推荐
- 在WPF中调用文件夹浏览/选择对话框
var dialog = new System.Windows.Forms.FolderBrowserDialog(); System.Windows.Forms.DialogResult resul ...
- python requests 上传文件
token="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjoiZWM2ZWFjZjFjM2UzYzEyOWU3ODA4YjgwNzkxNGI ...
- 新建node工程
之前各种node工程都是东抄抄,西抄抄的. 用ng的cli之后,发现非常舒服.所以把node新建工程的种种记录一下. node+babel, 直接按es6标准写就好了, 不需要一定写ts再转码了( ...
- 从多个角度来理解协方差(covariance)
起源:协方差自然是由方差衍生而来的,方差反应的是一个变量(一维)的离散程度,到二维了,我们可以对每个维度求其离散程度,但我们还想知道更多.我们想知道两个维度(变量)之间的关系,直观的举例就是身高和体重 ...
- Django+七牛上传+查看+下载文件相关函数,新整理未完全测试
M class File(models.Model): # 文档模型 name = models.CharField(max_length=255) staff = models.ForeignKey ...
- 机器学习之 XGBoost和LightGBM
目录 1.基本知识点简介 2.梯度提升树GBDT算法 2.1 思路和原理 2.2 梯度代替残差建立CART回归树 3.XGBoost提升树算法 3.1 XGBoost原理 3.2 XGBoost中损失 ...
- Sumo生成数据
1.生成input_net.net.xml文件 参数解释:http://www.sumo.dlr.de/userdoc/NETGENERATE.html#Grid_Network 1).生成grid ...
- django中的中间件
中间件介绍 什么是中间件? 官方的说法:中间件是一个用来处理Django的请求和响应的框架级别的钩子.它是一个轻量.低级别的插件系统,用于在全局范围内改变Django的输入和输出.每个中间件组件都负责 ...
- 一天一点Zynq(1)xilinx-arm-linux交叉编译链 安装总结以及资源更新
结束了对xilinx-arm-linux交叉编译链安装后,总结一下整个过程,方便后来的研究者们,少走点弯路. 关于xilinx-arm-linux交叉编译链的安装,网上一搜一大把,可是有的资料中的资源 ...
- JS-使用indexof来统计字符出现次数
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...