package com.example.ImageView;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.*;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.FloatMath;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View; /**
* Created by Administrator on 2015/1/4.
* <p/>
* 实现图片缩小放大拖拉效果
*/
public class MImageView extends View {
private Paint mPaint;//画笔
private Drawable mDrawable;
private Rect mDrawableRect = new Rect();
private Rect mRect = new Rect();//原始图片位置大小
private Context mContext;
private float mRation_WH = 0;
private float mOldX = 0, mOldY = 0;
private boolean isFirst = true;
private int SINGALDOWN = 1;// 单点按下
private int mStatus = 0;
private int offsetWidth = 0;
private int offsetHeight = 0;
private GestureDetector tapDetector;//实现双击放大缩小功能
private float beforeLenght, afterLenght;// 两触点距离
private float scale_temp = 1;// 缩放比例
private MODE mode = MODE.NONE;
private OnMeasureListener onMeasureListener;
private boolean status = true; public MImageView(Context context) {
super(context);
Init(context); } public MImageView(Context context, AttributeSet attrs) {
super(context, attrs);
Init(context);
} public void setOnMeasureListener(OnMeasureListener onMeasureListener) {
this.onMeasureListener = onMeasureListener;
} @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (getMeasuredWidth() > 0 && getMeasuredHeight() > 0 && status) {
if (onMeasureListener != null) {
onMeasureListener.onMeasureSize(getMeasuredWidth(), getMeasuredHeight());
status = false;
}
}
} public interface OnMeasureListener {
public void onMeasureSize(int width, int height);
} private void Init(Context context) {//初始化控件属性
this.mContext = context;
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setTextSize(35.0f); tapDetector = new GestureDetector(getContext(), new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onDoubleTap(MotionEvent e) {
doScaleAnim();
return true;
}
});
} @SuppressLint("DrawAllocation")
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
try {
if (mDrawable == null || mDrawable.getIntrinsicHeight() == 0
|| mDrawable.getIntrinsicWidth() == 0) {
return;
}
setBounds();
mDrawable.draw(canvas);
} catch (Exception e) {
} } /**
* 模式 NONE:无 DRAG:拖拽. ZOOM:缩放
*
* @author zhangjia
*/
private enum MODE {
NONE, DRAG, ZOOM } @SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
if (!tapDetector.onTouchEvent(event)) {
switch (event.getAction() & event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
mStatus = SINGALDOWN;
mOldX = event.getX();
mOldY = event.getY();
mode = MODE.DRAG;
break;
case MotionEvent.ACTION_POINTER_DOWN:
mode = MODE.ZOOM;
beforeLenght = getDistance(event);// 获取两点的距离
break;
case MotionEvent.ACTION_POINTER_UP:
mOldX = event.getX();
mOldX = event.getY();
mode = MODE.NONE;
break;
case MotionEvent.ACTION_UP:
if (mDrawableRect.height() < mRect.height() && mDrawableRect.width() < mRect.width())
doScaleAnim();
else {
up();
invalidate();
}
getParent().requestDisallowInterceptTouchEvent(false);
mStatus = 0;
mode = MODE.NONE;
break;
case MotionEvent.ACTION_MOVE:
if (mode == MODE.DRAG) {//移动状态
if (getWidth() < mDrawableRect.width()) {
getParent().requestDisallowInterceptTouchEvent(true);
moveDrag(event);
} else {
getParent().requestDisallowInterceptTouchEvent(false);
return false;
}
}
if (mode == MODE.ZOOM) {//判断是否为缩放状态
getParent().requestDisallowInterceptTouchEvent(true);
moveZoom(event);
}
Log.i("wade", mDrawableRect.toString() + "width:" + getWidth() + "height:" + getHeight());
break;
default:
break;
}
} else {
return false;
}
return true;
} /**
* 获取两点的距离 *
*/ float getDistance(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return FloatMath.sqrt(x * x + y * y);
} /**
* 手指抬起的时候回弹边界*
*/
private void up() {
int left, right, top, bottom;
left = mDrawableRect.left;
right = mDrawableRect.right;
top = mDrawableRect.top;
bottom = mDrawableRect.bottom;
offsetWidth = 0;
offsetHeight = 0;
if (mDrawableRect.width() > getWidth() && mDrawableRect.left >= 0) {
offsetWidth = -mDrawableRect.left;
}
if (mDrawableRect.height() > getHeight() && mDrawableRect.top >= 0) {
offsetHeight = -mDrawableRect.top;
}
if (mDrawableRect.width() > getWidth() && mDrawableRect.right <= getWidth()) {
offsetWidth = getWidth() - mDrawableRect.right;
}
if (mDrawableRect.height() > getHeight() && mDrawableRect.bottom <= getHeight()) {
offsetHeight = getHeight() - mDrawableRect.bottom;
}
if (mDrawableRect.width() < getWidth()) {
left = (getWidth() - mDrawableRect.width()) / 2;
offsetWidth = 0;
mDrawableRect.set(left, top, left + mDrawableRect.width(), bottom);
}
if (mDrawableRect.height() < getHeight()) {
top = (getHeight() - mDrawableRect.height()) / 2;
offsetHeight = 0;
mDrawableRect.set(left, top, right, top + mDrawableRect.height());
}
mDrawableRect.offset(offsetWidth, offsetHeight);
} private void moveDrag(MotionEvent event) {
if (mStatus == SINGALDOWN) {
offsetWidth = (int) (event.getX() - mOldX);
offsetHeight = (int) (event.getY() - mOldY);
mOldX = event.getX();
mOldY = event.getY();
if (mDrawableRect.width() < getWidth()) {
offsetWidth = 0;
} if (mDrawableRect.height() < getHeight()) {
offsetHeight = 0;
} mDrawableRect.offset(offsetWidth, offsetHeight);
invalidate();
}
} private void moveZoom(MotionEvent event) {//用于缩放布局的方法
afterLenght = getDistance(event);// 获取两点的距离
float gapLenght = afterLenght - beforeLenght;// 变化的长度
if (Math.abs(gapLenght) > 5f) {
scale_temp = afterLenght / beforeLenght;// 求的缩放的比例
}
Log.i("wade", "gapLenght" + gapLenght + "");
int disX = (int) (mDrawableRect.width() * Math.abs(1 - scale_temp)) / 4;// 获取缩放水平距离
int disY = (int) (mDrawableRect.height() * Math.abs(1 - scale_temp)) / 4;// 获取缩放垂直距离
if (beforeLenght < afterLenght) {
if (scale_temp > 1 && mDrawableRect.width() < mContext.getResources()
.getDisplayMetrics().widthPixels * 3) {
mDrawableRect.set(mDrawableRect.left - disX,
mDrawableRect.top - disY,
mDrawableRect.right + disX,
mDrawableRect.bottom + disY);
invalidate();
}
} else {
if (scale_temp < 1 && mDrawableRect.width() > mContext.getResources()
.getDisplayMetrics().widthPixels / 2) {
mDrawableRect.set(mDrawableRect.left + disX,
mDrawableRect.top + disY,
mDrawableRect.right - disX,
mDrawableRect.bottom - disY);
invalidate();
}
}
beforeLenght = afterLenght;
scale_temp = 1;
} /**
* 设置mDrawable的位置*
*/
public void setBounds() {
if (isFirst) {
mRation_WH = (float) mDrawable.getIntrinsicWidth()
/ (float) mDrawable.getIntrinsicHeight();
int px_w = Math.min(getWidth(),
dip2px(mContext, mDrawable.getIntrinsicWidth()));
int px_h = (int) (px_w / mRation_WH);
int left = (getWidth() - px_w) / 2;
int top = (getHeight() - px_h) / 2;
int right = px_w + left;
int bottom = px_h + top;
mRect.set(left, top, right, bottom);
mDrawableRect.set(left, top, right, bottom);
isFirst = false;
}
mDrawable.setBounds(mDrawableRect);
} public Drawable getMDrawable() {
return mDrawable;
} public void setMDrawable(Drawable mDrawable) {
this.mDrawable = mDrawable;
postInvalidate();
} public void setImageBitmap(Bitmap mBitmap) {
if (mBitmap != null) {
setMDrawable(new BitmapDrawable(getResources(), mBitmap));
} } public void setMDrawable(Drawable mDrawable, Rect rect) {
this.mDrawable = mDrawable;
postInvalidate();//第一次post为了计算图片的大小和位置
if (rect != null) {
mDrawableRect.set(rect);
postInvalidate();
doScaleAnim();
}
} public void setImageBitmap(Bitmap mBitmap, Rect rect) {
if (mBitmap != null) {
setMDrawable(new BitmapDrawable(getResources(), mBitmap), rect);
} } public int dip2px(Context context, int value) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (value * scale + 0.5f);
} /**
* 缩放动画处理
*/
public void doScaleAnim() {
MyAsyncTask myAsyncTask = new MyAsyncTask();
myAsyncTask.execute();
} /**
* 回缩动画執行
*/
class MyAsyncTask extends AsyncTask<Void, Integer, Void> {
private int current_Width, current_Height, width; private int left, top, right, bottom; private float scale_WH;// 宽高的比例 private float STEP = 8f;// 步伐 private float step_H, step_V;// 水平步伐,垂直步伐 private int status;//1放大到MAX_W宽度,2缩小原始大小,3放大成原始大小
private boolean change = true;//用来检测是否还能缩放 public MyAsyncTask() { } @Override
protected Void doInBackground(Void... params) {
change = true;
current_Width = mDrawableRect.width();
current_Height = mDrawableRect.height();
scale_WH = (float) current_Height / current_Width;
step_H = STEP;
step_V = scale_WH * STEP;
left = mDrawableRect.left;
top = mDrawableRect.top;
right = mDrawableRect.right;
bottom = mDrawableRect.bottom;
if (mDrawableRect.height() == mRect.height() && mDrawableRect.width() == mRect.width()) {
status = 1;
width = mRect.width() * 2;
} else {
if (mDrawableRect.height() > mRect.height() && mDrawableRect.width() > mRect.width()) {
status = 2;
width = mRect.width();
} else {
if (mDrawableRect.height() < mRect.height() && mDrawableRect.width() < mRect.width()) {
status = 3;
width = mRect.width();
}
}
} while (change) {
switch (status) {
case 1:
left -= step_H;
top -= step_V;
right += step_H;
bottom += step_V;
current_Width += 2 * step_H;
if (current_Width >= width) change = false;
break;
case 2:
left += step_H;
top += step_V;
right -= step_H;
bottom -= step_V;
current_Width -= 2 * step_H;
if (current_Width <= width) {
left = mRect.left;
top = mRect.top;
right = mRect.right;
bottom = mRect.bottom;
change = false;
}
break;
case 3:
left -= step_H;
top -= step_V;
right += step_H;
bottom += step_V;
current_Width += 2 * step_H;
if (current_Width >= width) {
left = mRect.left;
top = mRect.top;
right = mRect.right;
bottom = mRect.bottom;
change = false;
}
break; }
mDrawableRect.set(left, top, right, bottom);
Message.obtain(handler, 1).sendToTarget();
try {
Thread.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
} @Override
protected void onProgressUpdate(final Integer... values) {
super.onProgressUpdate(values);
} @Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
up();
invalidate();
}
} Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 1:
invalidate();
break;
}
}
};
}

Android 图片的放大缩小拖拉的更多相关文章

  1. Android 本地/网路下载图片实现放大缩小

     Android 本地加载/网路下载图片实现放大缩小拖拉效果,自定义控件. package com.example.ImageViewCustom; import android.app.Activi ...

  2. Android DIY之路 (一) 指定区域多图片合成 放大 缩小 镜像 旋转 等(转)

    惯例先看效果图 // 注意做类似这种模板功能时候 方位由后台数据提供,这里我们用假数据 4个点 或者xy 加区域来做示例 //一开始我们公司用的是透明盖住 操作图片 但发现 局限性较大.后来直接限定区 ...

  3. JS控制图片拖动 放大 缩小 旋转 支持滚轮放大缩小 IE有效

    <html> <head>     <title>图片拖动,放大,缩小,转向</title> <script type="text/ja ...

  4. JS中图片的放大缩小没反应

    这段代码无反应: 代码如下: <script type="text/javascript"> onload = function () { document.getEl ...

  5. jquery 实现点击图片居住放大缩小

    该功能是基于jquery实现的,所以 第一步则是引入jquery jquery下载地址:https://jquery.com/download/ 或者使用此时调试的版本(3版本) /*! jQuery ...

  6. Java界面程序实现图片的放大缩小

    Java界面程序实现图片的放大缩小.这个程序简单地实现了图片的打开.保存.放大一倍.缩小一倍和固定缩放尺寸,但是并没有过多的涵盖对图片的细节处理,只是简单地实现了图片大小的放缩. 思维导图如下: 效果 ...

  7. 用css3实现图片的放大缩小

    记录一个公用的css实现图片的放大缩小 @keyframes scaleDraw { /*定义关键帧.scaleDrew是需要绑定到选择器的关键帧名称*/ 0%{ transform: scale(1 ...

  8. Android多点触摸放大缩小图片

    1.Activity package com.fit.touchimage; import android.app.Activity; import android.graphics.Bitmap; ...

  9. Android多点触控技术,实现对图片的放大缩小平移,惯性滑动等功能

    首先推荐一下鸿洋大大的打造个性的图片预览与多点触控视频教程,这套教程教我们一步一步实现了多点触控实现对图片的平移和缩放的功能.这篇文章我将在鸿洋大大的基础之上做了一些扩展功能: 1.图片的惯性滑动 2 ...

随机推荐

  1. iOS 如何通过CocoaPods添加第三方框架

    一  先安装Ruby环境: http://ruby-china.org/wiki/install_ruby_guide 在安装的时候,若是出现: 1.You don't have write perm ...

  2. PHP第三方登录 -- 微博登录

    进化史 博客园 首页 新随笔 联系 管理 订阅 随笔- 9  文章- 0  评论- 0  php 实现qq第三方登录 学习之前,请大家先看一下oAuth协议. 首先呢,我们进入QQ互联的官方网站 ht ...

  3. 【iCore3 双核心板】例程十七:USB_MSC实验——读/写U盘(大容量存储器)

    实验指导书及代码包下载: http://pan.baidu.com/s/1qXt1L0o iCore3 购买链接: https://item.taobao.com/item.htm?id=524229 ...

  4. Run P4 without P4factory - A Simple Example In Tutorials. -2

    Reference:Github-Tutorial Exercise 2: Implementing TCP flowlet switching 实验准备: 参考之前的博客:Run P4 withou ...

  5. 问题解决(一)在ipad上通过safari浏览文档

    项目背景 针对用Sencha touch 1.1开发的一个用于通过ipad浏览的网站(其实是对PC端一个网站的映射)中的一个模块的开发,这个模块的主要功能就是用户浏览各种‘报告’,这些被阅览的‘报告’ ...

  6. Centos 6.5升级到Git2.1.2

    安装需求 # yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel# yum install gcc pe ...

  7. scala在linux以及在windows的安装,以及在IDEA中新建Scala项目

    一:linux下配资scala 1.上传 2.解压 3.配置环境 4.source一下 5.启动和简单使用 6.输出语句 二:scalac的使用 1.新建文件测试目录 2.新建程序 3.文件编译器书写 ...

  8. Visual Studio中编写C程序

    相信很多科班出身的程序猿和我一样,第一个接触到的编程语言是C语言,第一个写的程序是“Hello World!”. 对于一个.Net程序猿,VS肯定是个非常熟悉的工具,但是如何使用VS编写一个C语言程序 ...

  9. Codeigniter2.25部署Linux(php5.6)

    1).默认路由:修改system/core/Router.php 中第146行.如下图所示.ps:转换成小写我也是醉了...注释的代表是codeigniter作者写的,而上面的是我更改的 2).mod ...

  10. iOS沙盒目录

    出于安全考虑,iOS系统的沙盒机制规定每个应用都只能访问当前沙盒目录下面的文件(也有例外,比如系统通讯录能在用户授权的情况下被第三方应用访问),这个规则把iOS系统的封闭性展现的淋漓尽致. 一.沙盒中 ...