我有一个自定义视图,允许我在创建时在其上绘制位图,然后用户可以用手指在上面绘制。
我的问题是画布填充了我的布局中可用区域的整个宽度/高度,但我希望它简单地匹配绘制的位图的大小,以便用户只能在图片上绘制。这似乎需要在onSizeChanged中完成,因为我需要调整位图的大小,如果它们从纵向转到横向。等
我的代码:
class DrawingCameraPanel extends View implements OnTouchListener {
public Canvas mCanvas;
private Path mPath;
private Paint mPaint;
private ArrayList<Path> paths = new ArrayList<Path>();
private Bitmap background;
int width;
int height;
public Bitmap getOutputBitmap() {
Bitmap.Config config = Bitmap.Config.RGB_565;
Bitmap bitmap = Bitmap.createBitmap(width, height, config);
Canvas canvas = new Canvas(bitmap);
onDraw(canvas);
return bitmap;
}
public DrawingCameraPanel(Context context) {
super(context);
setFocusable(true);
setFocusableInTouchMode(true);
this.setOnTouchListener(this);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(6);
}
public DrawingCameraPanel(Context context, AttributeSet attrs) {
super(context, attrs);
setFocusable(true);
setFocusableInTouchMode(true);
this.setOnTouchListener(this);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(6);
}
public DrawingCameraPanel(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setFocusable(true);
setFocusableInTouchMode(true);
this.setOnTouchListener(this);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(6);
}
public void setPaintColor(int color) {
mPaint.setColor(color);
}
public void setBackgroundPic(Bitmap bitmap) {
this.background = bitmap;
mCanvas = new Canvas();
mPath = new Path();
paths.add(mPath);
mCanvas.save();
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
width = w;
height = h;
background = resizeImage(background, w, h);
}
@Override
protected void onDraw(Canvas canvas) {
if (background != null) {
canvas.drawBitmap(background, 0, 0, null);
}
for (Path p : paths) {
canvas.drawPath(p, mPaint);
}
}
public Bitmap resizeImage(Bitmap image, int maxWidth, int maxHeight) {
Bitmap resizedImage = null;
try {
int imageHeight = image.getHeight();
if (imageHeight > maxHeight)
imageHeight = maxHeight;
int imageWidth = (imageHeight * image.getWidth())
/ image.getHeight();
if (imageWidth > maxWidth) {
imageWidth = maxWidth;
imageHeight = (imageWidth * image.getHeight())
/ image.getWidth();
}
if (imageHeight > maxHeight)
imageHeight = maxHeight;
if (imageWidth > maxWidth)
imageWidth = maxWidth;
resizedImage = Bitmap.createScaledBitmap(image, imageWidth,
imageHeight, true);
} catch (OutOfMemoryError e) {
e.printStackTrace();
} catch (NullPointerException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return resizedImage;
}
public void clear() {
this.paths.clear();
mPath = new Path();
paths.add(mPath);
}
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
private void touch_start(float x, float y) {
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
}
private void touch_move(float x, float y) {
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
mY = y;
}
}
private void touch_up() {
mPath.lineTo(mX, mY);
// commit the path to our offscreen
mCanvas.drawPath(mPath, mPaint);
// kill this so we don't double draw
mPath = new Path();
paths.add(mPath);
}
@Override
public boolean onTouch(View arg0, MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touch_move(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up();
invalidate();
break;
}
return true;
}
答案 0 :(得分:1)
当然,如果Canvas
的宽度和高度(最有可能)设置为match_parent
或fill_parent
,为什么View
不占用布局中的所有空格? (嗯,技术上:ImageView
- 正在调整其边界的视图和画布只是“跟随”它们。)
我想你在这里重新发明轮子。我建议不要自己编写所有代码,而是建议:
View
代替setAdjustViewBounds(true)
。setBackgroundPic()
。这是重要的部分。这实际上会改变视图的边界以匹配包含的图像 - 它保留纵横比并确保图像适合布局提供的空间。ImageView.setImageBitmap()
只需拨打ImageView
,因为用户从{{1>}角度提取的背景是图像源。 OnTouchListener
实现。这里很酷的是您的自定义视图现在会自动调整大小。因此,您不必担心允许用户绘制的界限,因为它们将为您设置。