在Android上的自定义ImageView中绘制一个框架

时间:2015-02-08 15:37:21

标签: android canvas bitmap android-imageview

我正在扩展ImageView类并重写onDraw方法。 这就是我想要实现的目标:

  • MyImageView有一个黑角(带有一些填充的框架);
  • 在此框架内绘制位图;
  • 框架必须是固定尺寸,内部位图可以使用ScaleGestureListener进行缩放;

我不想通过定义XML Shape并将其设置为背景来创建框架。应该在onDraw方法中创建框架。

根据我从文档中理解的内容,onDraw方法为您提供了一个画布,其中有一个附加位图附加到ImageView。我通过调用canvas对象上的draw ...()方法来绘制支持位图。

为了实现我的目标,我应该使用Paint对象绘制一个固定大小的矩形并调用drawRect()。这会创建框架并且可以正常工作。

鉴于我成功地能够在帧内缩放位图,我不明白如何使用填充绘制内部位图并缩放该位图。

我在考虑两个画布。我的onDraw方法应该怎么做?

public class ViewFinder extends ImageView {

    private Paint pnt;
    private Bitmap frameBmp;
    private ScaleGestureDetector mScaleDetector;
    private float mScaleFactor = 1.f;

    public ViewFinder(Context context) {
        this(context, null, 0);
    }

    public ViewFinder(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ViewFinder(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
        frameBmp = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
        pnt = new Paint();
        pnt.setColor(Color.BLACK);
        pnt.setStyle(Paint.Style.STROKE);
        pnt.setStrokeWidth(10.f);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        // Let the ScaleGestureDetector inspect all events.
        mScaleDetector.onTouchEvent(ev);
        return true;
    }

    @Override
    public void onDraw(Canvas canvas) {
        canvas.drawRect(0, 0, getWidth(), getHeight(), pnt);
        canvas.drawBitmap(frameBmp, 0, 0, null);
        canvas.scale(mScaleFactor, mScaleFactor);
        if(getDrawable() != null) {
            Bitmap bmp = ((BitmapDrawable)getDrawable()).getBitmap();
            canvas.drawBitmap(bmp, 0, 0, null);
        }
    }

    private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            System.out.println("scale!");
            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;
        }
    }
}

修改 我解决了这个问题,我会把它留在这里以防有人需要它。 当你在Canvas上绘制时,你基本上是在实际“打印”画布上的东西(一个圆圈,一个矩形,另一个位图)之前自定义绘制行为(由Android框架处理画布的支持位图)(画布是由onDraw给你的) 。画布是您在告诉它绘制内容之前自定义的界面。重点是,当您绘制时,您将填充支持位图区域。所以,如果你想围绕某个东西画一个框架,你基本上有两个选择:

  1. 您可以告诉画布您要剪切绘图区域:在这种情况下,您使用clipRect()。从现在开始,每个绘图都将应用于剪裁区域。
  2. 通过调用draw ...()方法之一打印您想要的任何内容。然后,如果你想应用框架,只需用drawRect“覆盖”它:所以调用顺序首先是drawBitmap(),然后是drawRect()。这样,您可以使用位图填充支持位图。然后通过调用drawRect()来绘制位图的边缘。
  3. 上面的代码不正确:我将使用第二个选项重写onDraw()方法:

    Bitmap bmp = ... //this is the bitmap we want to draw
    
    Paint paint = new Paint();
    paint.setStyle(Paint.Style.STROKE);
    paint.setStrokeWidth(10.f);
    
        @Override
        public void onDraw(Canvas canvas) {
            if (getDrawable() == null) {
                return;
            }
            /* canvas already has a backing bitmap. 
            We're going to save the state of the canvas as 
            it will be altered with translations, rotation, 
            other drawings or whatever. */
            canvas.save();
            // Let's draw another bitmap onto the backing bitmap.
            canvas.drawBitmap(bmp, 0, 0, null);
            ... apply other drawings or transformations ...
            // Now we need to restore our canvas. This will reset our customizations on the canvas.
            canvas.restore();
            // Finally, we draw our outer frame. 
            canvas.drawRect(0, 0, getWidth(), getHeight(), pnt);
    
        }
    

0 个答案:

没有答案