Java 在不使用iamge缩放的图像上绘制
我正在开发一个android着色应用程序,用户可以在图像位图上填充颜色。我想在图像和图形上实现缩放功能。我所做的是,图像正在完美地缩放,但在它的基础上绘制而不是缩放 我想要的是:Java 在不使用iamge缩放的图像上绘制,java,android-studio,Java,Android Studio,我正在开发一个android着色应用程序,用户可以在图像位图上填充颜色。我想在图像和图形上实现缩放功能。我所做的是,图像正在完美地缩放,但在它的基础上绘制而不是缩放 我想要的是: 如果我缩放,图形和图像应该一起缩放 我想在右坐标缩放图像后绘制 下面是我的代码。提前谢谢 缩放和绘制活动代码: public class PinchZoomPan extends android.support.v7.widget.AppCompatImageView { //veriable for drawin
public class PinchZoomPan extends android.support.v7.widget.AppCompatImageView {
//veriable for drawing
public int widthd;
public int heightd;
boolean isEraser=false;
private Path drawPath;
private Paint drawPaint;
private Paint canvasPaint;
private Canvas drawCanvas;
private Bitmap canvasBitmap;
private int paintColor = Color.RED;
//////////////////////////
// veriable for zooming
Matrix matrix = new Matrix();
boolean zoomEnabled = true;
static final int NONE = 0;
static final int DRAG = 1;
static final int ZOOM = 2;
static final int CLICK = 3;
int mode = NONE;
PointF last = new PointF();
PointF start = new PointF();
float minScale = 1f;
float maxScale = 4f;
float[] m;
float redundantXSpace, redundantYSpace;
float width, height;
float saveScale = 1f;
float right, bottom, origWidth, origHeight, bmWidth, bmHeight;
ScaleGestureDetector mScaleDetector;
Context context;
public PinchZoomPan(Context context) {
super(context);
setupDrawing();
}
public PinchZoomPan(Context context, AttributeSet attr) {
super(context, attr);
super.setClickable(true);
this.context = context;
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
matrix.setTranslate(1f, 1f);
m = new float[9];
setImageMatrix(matrix);
setScaleType(ScaleType.MATRIX);
setupDrawing();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (zoomEnabled) {
mScaleDetector.onTouchEvent(event);
matrix.getValues(m);
float x = m[Matrix.MTRANS_X];
float y = m[Matrix.MTRANS_Y];
PointF curr = new PointF(event.getX(), event.getY());
switch (event.getAction()) {
//when one finger is touching
//set the mode to DRAG
case MotionEvent.ACTION_DOWN:
last.set(event.getX(), event.getY());
start.set(last);
mode = DRAG;
break;
//when two fingers are touching
//set the mode to ZOOM
case MotionEvent.ACTION_POINTER_DOWN:
last.set(event.getX(), event.getY());
start.set(last);
mode = ZOOM;
break;
//when a finger moves
//If mode is applicable move image
case MotionEvent.ACTION_MOVE:
//if the mode is ZOOM or
//if the mode is DRAG and already zoomed
if (mode == ZOOM || (mode == DRAG && saveScale > minScale)) {
float deltaX = curr.x - last.x;// x difference
float deltaY = curr.y - last.y;// y difference
float scaleWidth = Math.round(origWidth * saveScale);// width after applying current scale
float scaleHeight = Math.round(origHeight * saveScale);// height after applying current scale
//if scaleWidth is smaller than the views width
//in other words if the image width fits in the view
//limit left and right movement
if (scaleWidth < width) {
deltaX = 0;
if (y + deltaY > 0)
deltaY = -y;
else if (y + deltaY < -bottom)
deltaY = -(y + bottom);
}
//if scaleHeight is smaller than the views height
//in other words if the image height fits in the view
//limit up and down movement
else if (scaleHeight < height) {
deltaY = 0;
if (x + deltaX > 0)
deltaX = -x;
else if (x + deltaX < -right)
deltaX = -(x + right);
}
//if the image doesn't fit in the width or height
//limit both up and down and left and right
else {
if (x + deltaX > 0)
deltaX = -x;
else if (x + deltaX < -right)
deltaX = -(x + right);
if (y + deltaY > 0)
deltaY = -y;
else if (y + deltaY < -bottom)
deltaY = -(y + bottom);
}
//move the image with the matrix
matrix.postTranslate(deltaX, deltaY);
//set the last touch location to the current
last.set(curr.x, curr.y);
}
break;
//first finger is lifted
case MotionEvent.ACTION_UP:
mode = NONE;
int xDiff = (int) Math.abs(curr.x - start.x);
int yDiff = (int) Math.abs(curr.y - start.y);
if (xDiff < CLICK && yDiff < CLICK)
performClick();
break;
// second finger is lifted
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
break;
}
setImageMatrix(matrix);
invalidate();
return true;
} else {
float touchX = event.getX();
float touchY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
drawPath.moveTo(touchX, touchY);
break;
case MotionEvent.ACTION_MOVE:
if(isEraser) {
drawPath.lineTo(touchX, touchY);
drawCanvas.drawPath(drawPath, drawPaint);
drawPath.reset();
drawPath.moveTo(touchX, touchY);
} else {
drawPath.lineTo(touchX, touchY);
}
break;
case MotionEvent.ACTION_UP:
drawPath.lineTo(touchX, touchY);
drawCanvas.drawPath(drawPath, drawPaint);
drawPath = new Path();
break;
default:
return false;
}
invalidate();
return true;
}
}
public void setZoomEnabled(boolean b) {
this.zoomEnabled = b;
}
@Override
public void setImageBitmap(Bitmap bm) {
super.setImageBitmap(bm);
bmWidth = bm.getWidth();
bmHeight = bm.getHeight();
}
public void setMaxZoom(float x) {
maxScale = x;
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
mode = ZOOM;
return true;
}
@Override
public boolean onScale(ScaleGestureDetector detector) {
float mScaleFactor = detector.getScaleFactor();
float origScale = saveScale;
saveScale *= mScaleFactor;
if (saveScale > maxScale) {
saveScale = maxScale;
mScaleFactor = maxScale / origScale;
} else if (saveScale < minScale) {
saveScale = minScale;
mScaleFactor = minScale / origScale;
}
right = width * saveScale - width - (2 * redundantXSpace * saveScale);
bottom = height * saveScale - height - (2 * redundantYSpace * saveScale);
if (origWidth * saveScale <= width || origHeight * saveScale <= height) {
matrix.postScale(mScaleFactor, mScaleFactor, width / 2, height / 2);
if (mScaleFactor < 1) {
matrix.getValues(m);
float x = m[Matrix.MTRANS_X];
float y = m[Matrix.MTRANS_Y];
if (mScaleFactor < 1) {
if (Math.round(origWidth * saveScale) < width) {
if (y < -bottom)
matrix.postTranslate(0, -(y + bottom));
else if (y > 0)
matrix.postTranslate(0, -y);
} else {
if (x < -right)
matrix.postTranslate(-(x + right), 0);
else if (x > 0)
matrix.postTranslate(-x, 0);
}
}
}
} else {
matrix.postScale(mScaleFactor, mScaleFactor, detector.getFocusX(), detector.getFocusY());
matrix.getValues(m);
float x = m[Matrix.MTRANS_X];
float y = m[Matrix.MTRANS_Y];
if (mScaleFactor < 1) {
if (x < -right)
matrix.postTranslate(-(x + right), 0);
else if (x > 0)
matrix.postTranslate(-x, 0);
if (y < -bottom)
matrix.postTranslate(0, -(y + bottom));
else if (y > 0)
matrix.postTranslate(0, -y);
}
}
return true;
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = MeasureSpec.getSize(widthMeasureSpec);
height = MeasureSpec.getSize(heightMeasureSpec);
//Fit to screen.
float scale;
float scaleX = width / bmWidth;
float scaleY = height / bmHeight;
scale = Math.min(scaleX, scaleY);
matrix.setScale(scale, scale);
setImageMatrix(matrix);
saveScale = 1f;
// Center the image
redundantYSpace = height - (scale * bmHeight);
redundantXSpace = width - (scale * bmWidth);
redundantYSpace /= 2;
redundantXSpace /= 2;
matrix.postTranslate(redundantXSpace, redundantYSpace);
origWidth = width - 2 * redundantXSpace;
origHeight = height - 2 * redundantYSpace;
right = width * saveScale - width - (2 * redundantXSpace * saveScale);
bottom = height * saveScale - height - (2 * redundantYSpace * saveScale);
setImageMatrix(matrix);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
this.heightd = h;
this.widthd= w;
canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
drawCanvas = new Canvas(canvasBitmap);
}
private void setupDrawing() {
drawPath = new Path();
drawPaint = new Paint();
drawPaint.setColor(paintColor);
drawPaint.setAntiAlias(true);
drawPaint.setDither(true);
drawPaint.setStyle(Paint.Style.STROKE);
drawPaint.setStrokeJoin(Paint.Join.ROUND);
drawPaint.setStrokeCap(Paint.Cap.ROUND);
drawPaint.setStrokeWidth(15);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.save();
super.onDraw(canvas);
canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
canvas.drawPath(drawPath, drawPaint);
invalidate();
}
}
公共类PinchZoomPan扩展了android.support.v7.widget.AppCompatImageView{
//可供绘图的
公共int宽度;
公众内部高度;
布尔isEraser=false;
专用路径;
私人油漆;
私人油漆画布;
私人帆布;
私有位图画布位图;
私有int paintColor=Color.RED;
//////////////////////////
//可变焦的
矩阵=新矩阵();
布尔zoomEnabled=true;
静态最终int NONE=0;
静态最终整数阻力=1;
静态最终整数缩放=2;
静态最终int CLICK=3;
int模式=无;
PointF last=新的PointF();
PointF start=新的PointF();
浮动最小刻度=1f;
浮点最大刻度=4f;
浮动[]m;
浮点redundantXSpace,redundantYSpace;
浮动宽度、高度;
浮动存储比例=1f;
右浮动、底部、起始宽度、起始高度、bmWidth、bmHeight、bmHeight;
scalegestruedetector mScaleDetector;
语境;
公共PinchZoomPan(上下文){
超级(上下文);
设置绘图();
}
公共PinchZoomPan(上下文,属性集属性){
超级(上下文,attr);
super.setClickable(true);
this.context=上下文;
mScaleDetector=新的scalegestruedetector(上下文,新的ScaleListener());
矩阵.setTranslate(1f,1f);
m=新浮点数[9];
setImageMatrix(矩阵);
setScaleType(ScaleType.MATRIX);
设置绘图();
}
@凌驾
公共布尔onTouchEvent(运动事件){
如果(可缩放){
mScaleDetector.onTouchEvent(事件);
矩阵值(m);
float x=m[矩阵MTRANS_x];
浮点y=m[矩阵MTRANS_y];
PointF curr=新的PointF(event.getX(),event.getY());
开关(event.getAction()){
//当一个手指接触时
//将模式设置为拖动
case MotionEvent.ACTION\u DOWN:
set(event.getX(),event.getY());
开始。设置(最后);
模式=拖动;
打破
//当两个手指接触时
//将模式设置为缩放
case MotionEvent.ACTION\u指针\u向下:
set(event.getX(),event.getY());
开始。设置(最后);
模式=缩放;
打破
//当手指移动时
//如果模式适用,则移动图像
case MotionEvent.ACTION\u移动:
//如果模式为缩放或
//如果模式为“拖动”且已缩放
如果(模式==缩放| |(模式==拖动和保存比例>最小比例)){
浮动deltaX=curr.x-last.x;//x差
float deltaY=curr.y-last.y;//y差
float scaleWidth=Math.round(origWidth*saveScale);//应用当前比例后的宽度
float scaleHeight=Math.round(orighight*saveScale);//应用当前比例后的高度
//如果缩放宽度小于视图宽度
//换句话说,如果图像宽度适合视图
//限制左右移动
if(标度宽度<宽度){
deltaX=0;
如果(y+deltaY>0)
deltaY=-y;
否则如果(y+deltaY<-底部)
三角洲=-(y+底部);
}
//如果比例高度小于视图高度
//换句话说,如果图像高度与视图相符
//限制上下移动
else if(刻度高度<高度){
deltaY=0;
如果(x+deltaX>0)
deltaX=-x;
否则如果(x+deltaX<-右)
deltaX=-(x+右侧);
}
//如果图像的宽度或高度不合适
//限制上下左右
否则{
如果(x+deltaX>0)
deltaX=-x;
否则如果(x+deltaX<-右)
deltaX=-(x+右侧);
如果(y+deltaY>0)
deltaY=-y;
否则如果(y+deltaY<-底部)
三角洲=-(y+底部);
}
//使用矩阵移动图像
矩阵。后翻译(deltaX、deltaY);
//将最后一次触摸位置设置为当前位置
最后一组(当前x、当前y);
}
打破
//第一个手指被举起
case MotionEvent.ACTION\u UP:
模式=无;
intxdiff=(int)Math.abs(curr.x-start.x);
int yDiff=(int)Math.abs(curr.y-start.y);
if(xDiff public class MainActivity extends AppCompatActivity {
PinchZoomPan pinchZoomPan;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pinchZoomPan = new PinchZoomPan(this);
final Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStrokeWidth(10);
pinchZoomPan = findViewById(R.id.drawble_view);
Bitmap bmp = getBitmapFromVectorDrawable(this,R.drawable.ic_launcher_background);
Bitmap alteredBmp = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), bmp.getConfig());
final Canvas canvas = new Canvas(alteredBmp);
canvas.drawBitmap(bmp, 0, 0, paint);
pinchZoomPan.setImageBitmap(alteredBmp);
final Button paintBtn = findViewById(R.id.enable_zoom);
paintBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View button) {
if (paintBtn.getText().toString() =="disable zoom"){
pinchZoomPan.setZoomEnabled(false);
paintBtn.setText("enable zoom");
}
else {
pinchZoomPan.setZoomEnabled(true);
paintBtn.setText("disable zoom");
}
}
});
}
public static Bitmap getBitmapFromVectorDrawable(Context context, int drawableId) {
Drawable drawable = ContextCompat.getDrawable(context, drawableId);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
drawable = (DrawableCompat.wrap(drawable)).mutate();
}
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
}