Android 图片的放大缩小拖拉

时间:2023-03-09 20:13:41
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;
}
}
};
}