获取Android Canvas中的java.awt.Graphics2D行为

时间:2012-11-01 00:33:45

标签: android

以下是我的情景:

我有一个带有视图的布局,我可以在其onDraw()方法上调用并获取画布。现在,在一个事件上,比如onTouchEvent(),我想剪切画布的一部分并将这部分显示到另一个布局的另一个视图中。

我发现代码片段做类似的事情,但是它们基于Android API不支持的java.awt包,尤其是java.awt.Graphics2D等核心组件

我想在Android中使用canvas而不是Graphics2D来使用相似的算法将其内容绘制到另一个画布中。我们如何实现这一目标?

基本上,我希望获得与java.awt中的以下代码相同的结果:

protected void paint(Graphics2D g2) {
Ellipse2D ellipse = //create ellipse which is to be displayed in another surface
g2.fill(ellipse);  //how to achieve the same result in Android?
g2.draw(ellipse);  //how to achieve the same result in Android?
g2.clip(ellipse);  //how to achieve the same result in Android?
....
... 
//note: Afaik, in Android, the code like Drawable.draw(canvas, ....),
//will achieve result in the opposite way where the Drawable would be drawn into
//the Canvas whereas G2.fill(ellipse) would fill the ellipse with the G2's content
}

1 个答案:

答案 0 :(得分:0)

如果我理解你需要什么,你可以尝试如下代码。

这是活动的xml布局文件的样子:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <com.example.test.SourceImageView
        android:id="@+id/srcImage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:src="@drawable/landscape" /> <!-- landscape.png is the picture on resources -->

    <ImageView
        android:id="@+id/dstImage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/srcImage"
        android:layout_centerHorizontal="true" />

</RelativeLayout>

活动的源代码:

public class MainActivity extends Activity implements SourceImageView.OnCropListener {

    private SourceImageView srcImageView;
    private ImageView       dstImageView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        srcImageView = (SourceImageView) findViewById(R.id.srcImage);
        dstImageView = (ImageView) findViewById(R.id.dstImage);

        srcImageView.setOnCropListener(this);
    }

    @Override
    public void onCrop(Bitmap bitmap) {
        dstImageView.setImageBitmap(Bitmap.createScaledBitmap(bitmap, 50, 50, true));
    }
}

我称之为SourceImageView的自定义视图:

public class SourceImageView extends ImageView implements OnTouchListener {

    private float           x;
    private float           y;
    private Paint           paint;
    private Bitmap          bitmap;
    private OnCropListener  cropListener;

    public SourceImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        setOnTouchListener(this);
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setXfermode(new PorterDuffXfermode(Mode.CLEAR));
        bitmap = ((BitmapDrawable) getDrawable()).getBitmap();
    }

    @Override
    protected void onDetachedFromWindow() {
        bitmap.recycle();
        super.onDetachedFromWindow();
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {

        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            x = event.getX();
            y = event.getY();

            if (cropListener != null) {
                if (x + 20 > bitmap.getWidth() || y + 20 > bitmap.getHeight() || (y - 20) < 0 || (x - 20) < 0) {
                    return true;
                }
                Bitmap b = Bitmap.createBitmap(bitmap, (int) x - 20, (int) y - 20, 40, 40);
                Bitmap overlay = Bitmap.createBitmap(40, 40, Bitmap.Config.ARGB_8888);
                Canvas c = new Canvas(overlay);

                c.clipRect(0, 0, b.getWidth(), b.getHeight());

                Path path = new Path();
                path.addCircle(20, 20, 20, Path.Direction.CW);
                c.clipPath(path, Op.INTERSECT);
                c.drawBitmap(b, 0, 0, null);

                cropListener.onCrop(overlay);

                Bitmap overlay2 = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
                Canvas canvas = new Canvas(overlay2);
                canvas.drawBitmap(bitmap, 0, 0, null);
                canvas.drawCircle(x, y, 20, paint);
                bitmap = overlay2;
                setImageBitmap(bitmap);
            }
        }
        return true;
    }

    public void setOnCropListener(OnCropListener cropListener) {
        this.cropListener = cropListener;
    }

    static interface OnCropListener {
        public void onCrop(Bitmap bitmap);
    }

}

在处理位图时要小心,它们可能是一个昂贵的内存泄漏源,特别是如果你使用旧版本的android。我没有检查此代码中的泄漏。可能这可以改进(重构,优化)。

如果这不是您想要的,我希望这有助于为您提供想法并指出正确的方向。

<强> == EDIT ==

可能不太清楚所以我必须说我假设图像的裁剪部分是半径为20像素的圆的区域。