Android 图片的放大缩小拖拉
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 图片的放大缩小拖拉的更多相关文章
- Android 本地/网路下载图片实现放大缩小
Android 本地加载/网路下载图片实现放大缩小拖拉效果,自定义控件. package com.example.ImageViewCustom; import android.app.Activi ...
- Android DIY之路 (一) 指定区域多图片合成 放大 缩小 镜像 旋转 等(转)
惯例先看效果图 // 注意做类似这种模板功能时候 方位由后台数据提供,这里我们用假数据 4个点 或者xy 加区域来做示例 //一开始我们公司用的是透明盖住 操作图片 但发现 局限性较大.后来直接限定区 ...
- JS控制图片拖动 放大 缩小 旋转 支持滚轮放大缩小 IE有效
<html> <head> <title>图片拖动,放大,缩小,转向</title> <script type="text/ja ...
- JS中图片的放大缩小没反应
这段代码无反应: 代码如下: <script type="text/javascript"> onload = function () { document.getEl ...
- jquery 实现点击图片居住放大缩小
该功能是基于jquery实现的,所以 第一步则是引入jquery jquery下载地址:https://jquery.com/download/ 或者使用此时调试的版本(3版本) /*! jQuery ...
- Java界面程序实现图片的放大缩小
Java界面程序实现图片的放大缩小.这个程序简单地实现了图片的打开.保存.放大一倍.缩小一倍和固定缩放尺寸,但是并没有过多的涵盖对图片的细节处理,只是简单地实现了图片大小的放缩. 思维导图如下: 效果 ...
- 用css3实现图片的放大缩小
记录一个公用的css实现图片的放大缩小 @keyframes scaleDraw { /*定义关键帧.scaleDrew是需要绑定到选择器的关键帧名称*/ 0%{ transform: scale(1 ...
- Android多点触摸放大缩小图片
1.Activity package com.fit.touchimage; import android.app.Activity; import android.graphics.Bitmap; ...
- Android多点触控技术,实现对图片的放大缩小平移,惯性滑动等功能
首先推荐一下鸿洋大大的打造个性的图片预览与多点触控视频教程,这套教程教我们一步一步实现了多点触控实现对图片的平移和缩放的功能.这篇文章我将在鸿洋大大的基础之上做了一些扩展功能: 1.图片的惯性滑动 2 ...
随机推荐
- HTML静态网页导航制作
普通导航栏制作 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www ...
- VC 解密OUTLOOK pop3保存注册表密码
原文连接:https://forum.90sec.org/forum.php?mod=viewthread&tid=8410 作者:Agile 用过OUTLOOK的人都知道,OUTLOOK的密 ...
- 词法分析器Antlr
一.我们都知道编程语言在执行之前需要先进行编译,这样就可以把代码转换成机器识别的语言,这个过程就是编译. 那么它是怎么编译的呢? Java在JVM虚拟机中进行编译,javascript在Js引擎中编译 ...
- js 获取中文的拼音
es6 + 模块化封装 "use strict"; module.exports = { //参数,中文字符串 //返回值:拼音首字母串数组 makePy (str) { if ( ...
- jquery 设置表格奇偶数的颜色和行被选中的颜色样式jquery 设置表格奇偶数的颜色和行被选中的颜色样式
query 代码 $(funtion(){ //设置偶数行和奇数行 $("tbody>tr:odd").addClass("ou"); //为奇数行设 ...
- graph | hungary
匈牙利算法,求二分图最大匹配. 若P是图G中一条连通两个未匹配顶点的路径,并且属于M的边和不属于M的边(即已匹配和待匹配的边)在P上交替出现,则称P为相对于M的一条增广路径.(M为一个匹配) 由增广路 ...
- 用session实现简单的购物
package cn.itcast.shopping; import java.io.IOException; import java.io.PrintWriter; import java.util ...
- array_diff的参数前后循序的区别
//如果两个参数之间有区别.array_diff会返回第二个参数的差值 $oldData = array(0=>'德国',1=>'deguo'); $newData = array(0=& ...
- HDFS的概念
1.数据块 每个磁盘都有默认的数据块大小,这是磁盘进行数据读/写的最小单位.构建于单个磁盘之上的文件系统通过磁盘块来管理该文件系统中的块,该文件系统块的大小可以是磁盘块的整数倍.文件系统快一半为几千字 ...
- 执行带参数的sql字符串
--要传入的参数 declare @Rv NVARCHAR(40) --要执行的带参数的sql字符串 declare @sql nvarchar(max) set @sql='select * fr ...