Android画布在放大时带边界滚动
我有一个画布,我可以缩小和滚动边界,代码在这里Android画布在放大时带边界滚动,android,android-canvas,Android,Android Canvas,我有一个画布,我可以缩小和滚动边界,代码在这里 package com.mypackage.ui.view; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import
package com.mypackage.ui.view;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.provider.SyncStateContract;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
/**
*
*/
public class MyDrawingView extends View {
private static final int INVALID_POINTER_ID = -1;
private int state = 0; //0 se dibuja - 1 se mueve
//drawing path
private Path drawPath;
//drawing and canvas paint
private Paint drawPaint, canvasPaint;
//canvas
private Canvas drawCanvas;
//canvas bitmap
private Bitmap bitmap;
protected String tool;
protected String color;
protected float brushSize;
//erase flag
private boolean erase=false;
public String getTool() {
return tool;
}
public void setTool(String tool) {
this.tool = tool;
}
public String getColor() {
return color;
}
public float getBrushSize() {
return brushSize;
}
public boolean isErase() {
return erase;
}
private String drawId;
// public OnSaveActionListener listener;
private float mPosX;
private float mPosY;
public float getMPosX() { return mPosX; }
public float getMPosY() { return mPosY; }
private float mLastTouchX;
private float mLastTouchY;
private int mActivePointerId = INVALID_POINTER_ID;
private ScaleGestureDetector mScaleDetector;
private float mScaleFactor = 1.f;
private float viewHeight;
private float viewWidth;
float canvasWidth, canvasHeight;
private float minScaleFactor;
private boolean panEnabled = true;
private boolean zoomEnabled = true;
public MyDrawingView(Context context) {
super(context);
setup();
}
public MyDrawingView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setup();
}
public MyDrawingView(Context context, AttributeSet attrs){
super(context, attrs);
setup();
}
//setup drawing
private void setup(){
mScaleDetector = new ScaleGestureDetector(getContext(), new ScaleListener());
//prepare for drawing and setup paint stroke properties
drawPath = new Path();
drawPaint = new Paint();
drawPaint.setStyle(Paint.Style.STROKE);
drawPaint.setStrokeJoin(Paint.Join.ROUND);
drawPaint.setStrokeCap(Paint.Cap.ROUND);
canvasPaint = new Paint(Paint.DITHER_FLAG);
}
public void setState(int state) {
this.state = state;
}
public void setImageBitmap(Bitmap bmp) {
bitmap = bmp;
resetZoom();
resetPan();
invalidate();
}
public void setImageDrawable(Drawable drawable) {
setImageBitmap(((BitmapDrawable) drawable).getBitmap());
}
public void setBitmap(Bitmap bmp) {
setImageBitmap(bmp);
}
public void resetZoom() {
mScaleFactor = 1.0f;
}
public void resetPan() {
mPosX = 0f;
mPosY = 0f;
}
public BitmapDrawable getImageDrawable() {
BitmapDrawable bd = new BitmapDrawable(getContext().getResources(), bitmap);
return bd;
}
public BitmapDrawable getDrawable() {
return getImageDrawable();
}
//size assigned to view
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
drawCanvas = new Canvas(bitmap);
}
//draw the view - will be called after touch event
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mScaleFactor = Math.max(mScaleFactor, minScaleFactor);
canvasHeight = canvas.getHeight();
canvasWidth = canvas.getWidth();
//Save the canvas without translating (panning) or scaling (zooming)
//After each change, restore to this state, instead of compounding
//changes upon changes
canvas.save();
int maxX, minX, maxY, minY;
//Regardless of the screen density (HDPI, MDPI) or the scale factor,
//The image always consists of bitmap width divided by 2 pixels. If an image
//is 200 pixels wide and you scroll right 100 pixels, you just scrolled the image
//off the screen to the left.
minX = (int) (((viewWidth / mScaleFactor) - bitmap.getWidth()) / 2);
maxX = 0;
//How far can we move the image vertically without having a gap between image and frame?
minY = (int) (((viewHeight / mScaleFactor) - bitmap.getHeight()) / 2);
maxY = 0;
//Do not go beyond the boundaries of the image
if (mPosX > maxX) {
mPosX = maxX;
}
if (mPosX < minX) {
mPosX = minX;
}
if (mPosY > maxY) {
mPosY = maxY;
}
if (mPosY < minY) {
mPosY = minY;
}
if (state == 0) {
} else if (state == 1) {
canvas.scale(this.mScaleFactor, this.mScaleFactor, this.mScaleDetector.getFocusX(), this.mScaleDetector.getFocusY());
}
canvas.translate(mPosX, mPosY);
canvas.drawBitmap(bitmap, 0, 0, canvasPaint);
canvas.drawPath(drawPath, drawPaint);
canvas.restore();
invalidate();
}
//register user touches as drawing action
@Override
public boolean onTouchEvent(MotionEvent event) {
mScaleDetector.onTouchEvent(event);
float touchX = event.getX();
float touchY = event.getY();
if(isErase()){
drawCanvas.drawPath(drawPath, drawPaint);
invalidate();
}
//respond to down, move and up events
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mLastTouchX = touchX;
mLastTouchY = touchY;
mActivePointerId = event.getPointerId(0);
break;
case MotionEvent.ACTION_MOVE:
if (state == 0) {
} else if (state == 1) {
final int pointerIndex = event.findPointerIndex(mActivePointerId);
final float x = event.getX(pointerIndex);
final float y = event.getY(pointerIndex);
// Only move if the ScaleGestureDetector isn't processing a gesture.
if (!mScaleDetector.isInProgress()) {
final float dx = x - mLastTouchX;
final float dy = y - mLastTouchY;
mPosX += dx;
mPosY += dy;
invalidate();
}
mLastTouchX = x;
mLastTouchY = y;
}
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 = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)
>> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int pointerId = event.getPointerId(pointerIndex);
if (pointerId == mActivePointerId) {
// This was our active pointer going up. Choose a new
// active pointer and adjust accordingly.
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mLastTouchX = event.getX(newPointerIndex);
mLastTouchY = event.getY(newPointerIndex);
mActivePointerId = event.getPointerId(newPointerIndex);
}
break;
default:
return false;
}
return true;
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScale(ScaleGestureDetector detector) {
mScaleFactor *= detector.getScaleFactor();
// Don't let the object get too small or too large.
mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));
invalidate();
return true;
}
}
}
package com.mypackage.ui.view;
导入android.content.Context;
导入android.graphics.Bitmap;
导入android.graphics.Canvas;
导入android.graphics.Color;
导入android.graphics.Paint;
导入android.graphics.Path;
导入android.graphics.PorterDuff;
导入android.graphics.PorterDuffXfermode;
导入android.graphics.Rect;
导入android.graphics.drawable.BitmapDrawable;
导入android.graphics.drawable.drawable;
导入android.provider.SyncStateContract;
导入android.util.AttributeSet;
导入android.util.Log;
导入android.util.TypedValue;
导入android.view.MenuItem;
导入android.view.MotionEvent;
导入android.view.scalegestruedetector;
导入android.view.view;
导入java.text.simpleDataFormat;
导入java.util.Date;
导入java.util.List;
导入java.util.Locale;
/**
*
*/
公共类MyDrawingView扩展视图{
私有静态final int无效\u指针\u ID=-1;
私有int state=0;//0 se dibuja-1 se mueve
//绘图路径
专用路径;
//绘画和油画
私人油漆拉丝漆、帆布漆;
//帆布
私人帆布;
//画布位图
私有位图;
保护管柱工具;
保护字符串颜色;
受保护的浮刷尺寸;
//擦除标志
私有布尔擦除=假;
公共字符串getTool(){
返回工具;
}
公共无效设置工具(字符串工具){
这个工具=工具;
}
公共字符串getColor(){
返回颜色;
}
公共浮点数getBrushSize(){
回刷尺寸;
}
公共布尔isErase(){
返回擦除;
}
私有字符串drawId;
//公众参与;听众参与;
私人浮动mPosX;
私家车;
公共浮点getMPosX(){return mPosX;}
公共浮点getMPosY(){return mPosY;}
私有浮动mLastTouchX;
私密的浮躁和敏感;
private int mActivePointerId=无效的\u指针\u ID;
专用scalegestruedetector mScaleDetector;
私人浮动mScaleFactor=1.f;
私家浮动高度;
私有浮动视宽;
浮动画布宽度、画布高度;
私人浮动因素;
private boolean panEnabled=true;
私有布尔zoomEnabled=true;
公共MyDrawingView(上下文){
超级(上下文);
设置();
}
公共MyDrawingView(上下文、属性集属性、int-defStyle){
超级(上下文、属性、定义样式);
设置();
}
公共MyDrawingView(上下文、属性集属性){
超级(上下文,attrs);
设置();
}
//安装图
私有无效设置(){
mScaleDetector=新的ScaleGetDetector(getContext(),new ScaleListener());
//准备绘制并设置绘制笔划特性
drawPath=新路径();
drawPaint=新油漆();
drawPaint.setStyle(Paint.Style.STROKE);
drawPaint.setStrokeJoin(绘制.连接.圆形);
drawPaint.setStrokeCap(油漆盖圆形);
画布绘制=新绘制(绘制抖动标志);
}
公共无效设置状态(int状态){
this.state=状态;
}
公共void setImageBitmap(位图bmp){
位图=bmp;
重置缩放();
resetPan();
使无效();
}
公共void setImageDrawable(可提取可提取){
setImageBitmap(((BitmapDrawable)drawable.getBitmap());
}
公共void setBitmap(位图bmp){
setImageBitmap(bmp);
}
公共void resetZoom(){
mScaleFactor=1.0f;
}
公共无效重置PAN(){
mPosX=0f;
mPosY=0f;
}
公共BitmapDrawable getImageDrawable(){
BitmapDrawable bd=新的BitmapDrawable(getContext().getResources(),位图);
返回bd;
}
公共BitmapDrawable getDrawable(){
返回getImageDrawable();
}
//指定给视图的大小
@凌驾
已更改尺寸的受保护空心(整数w、整数h、整数oldw、整数oldh){
super.onSizeChanged(w,h,oldw,oldh);
bitmap=bitmap.createBitmap(w,h,bitmap.Config.ARGB_8888);
drawCanvas=新画布(位图);
}
//绘制视图-将在触摸事件后调用
@凌驾
受保护的void onDraw(画布){
super.onDraw(帆布);
mScaleFactor=Math.max(mScaleFactor,minScaleFactor);
canvasHeight=canvas.getHeight();
canvasWidth=canvas.getWidth();
//保存画布而不平移(平移)或缩放(缩放)
//每次更改后,恢复到此状态,而不是复合
//变化无常
canvas.save();
int maxX,minX,maxY,minY;
//无论屏幕密度(HDPI、MDPI)或比例因子,
//图像总是由位图宽度除以2像素组成。如果图像
//是200像素宽,你向右滚动100像素,你只需滚动图像
//在屏幕左侧。
minX=(int)((viewWidth/mScaleFactor)-bitmap.getWidth())/2);
maxX=0;
//在图像和帧之间没有间隙的情况下,我们可以垂直移动图像多远?
minY=(int)((viewHeight/mScaleFactor)-bitmap.getHeight())/2);
maxY=0;
//不要超出图像的边界
如果(mPosX>maxX){
mPosX=maxX;
}
if(mPosX最大值){
mPosY=maxY;
}
if(mPosY