1

私はアンドロイド脳のアイデアのために再び来ます!

ビットマップがcenterCropとしてスケーリングされているimageViewに円の穴を入れたいと思います。円の穴 (左と下からの dp) と穴の半径を配置する必要がある場所を知っています。でも作り方がわからない!

Porterduff を使用して穴を開けられることはわかっていますが、何をすればよいでしょうか?

  • カスタム ビットマップ
  • カスタム ドローアブル/ビュー
  • カスタムコード

ありがとう

回答に続いて、穴のある私の CustomImage があります:

public class MyImageView extends ImageView {


private AttributeSet attrs;
private float y;
private float x;
private float r;
private Paint paint;
private Rect mSrcRect;
private Rect mDestRect;
private Bitmap mBitmap;
private int alreadycalled = 0;

public MyImageView(Context context, AttributeSet attrs) {
    super(context, attrs);
    this.attrs = attrs;
    initView();
}

public MyImageView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    this.attrs = attrs;
    initView();
}

public MyImageView(Context context, float x, float y, float radius) {
    super(context);
    this.x = x;
    this.y = y;
    this.r = radius;
    Log.d("parameters", String.format("left:%s , right:%s, radius:%s", String.valueOf(x), String.valueOf(y), String.valueOf(r)));
    initView();
}

private void initView() {
    paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    paint.setStyle(Paint.Style.FILL_AND_STROKE);
    paint.setStrokeWidth(10);
    paint.setColor(0xff000000);
}

@Override
protected void onDraw(Canvas canvas) {
    alreadycalled++;
    Log.d("alreadycalled", "called " + alreadycalled);
    Drawable mDrawable = getDrawable();
    if (mDrawable == null) {
        return; // couldn't resolve the URI
    }
    int dWidth = mDrawable.getIntrinsicWidth();
    int dHeight = mDrawable.getIntrinsicHeight();

    float scale = 1.0f;
    scale = Math.max(getWidth() * 1.0f / dWidth, getHeight()
            * 1.0f / dHeight);
    int nWidth = (int) (dWidth * scale);
    int nHeight = (int) (dHeight * scale);
    int offsetLeft = (nWidth - getWidth()) / 2;
    int offsetTop = (nHeight - getHeight()) / 2;
    mBitmap = ((BitmapDrawable) mDrawable).getBitmap();
    //custom mSrcRect mDestRect to achieve centerCrop
    mSrcRect = new Rect(0, 0, dWidth, dWidth);
    mDestRect = new Rect(-offsetLeft, -offsetTop, getWidth() + offsetLeft, getHeight() + offsetTop);
    Log.d("src", mSrcRect.toString());
    Log.d("dest", mDestRect.toString());
    int sc = canvas.saveLayer(0, 0, getWidth(), getHeight(), null,
            Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG
                    | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG
                    | Canvas.FULL_COLOR_LAYER_SAVE_FLAG
                    | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
    paint.setColor(0xffffffff);
    canvas.drawBitmap(mBitmap, mSrcRect, mDestRect, paint);
    paint.setColor(0xffff0000);
    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
    Log.d("position", String.format("%s , %s", String.valueOf(x), String.valueOf(y)));
    canvas.drawCircle(x, y, r, paint);
    paint.setXfermode(null);
    canvas.restoreToCount(sc);


}

これらの行を使用してプログラムで呼び出しました:

BitmapDrawable bd=(BitmapDrawable) getResources().getDrawable(R.drawable.triangle_bas_accueil2);
MyImageView customImView = new MyImageView(getApplicationContext(), mX, mY, mRadius);
customImView.setImageDrawable(bd);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
params.gravity = Gravity.BOTTOM;
customImView.setLayoutParams(params);
down_relative.addView(customImView);

しかし、onDraw()メソッドは2回呼び出されます(おそらく必要です)が、これにより2つの穴ができます。1つはパラメーターを変更できますが、もう1つは同じ場所にあります。のコンテナMyImageViewRelativeLayout.

誰かがアイデアを持っている場合は?@tiny-sunlight ?

4

2 に答える 2

2

これは CenterCrop 専用で、scaleType を処理できません。また、キャンバスが苦手なため、このコードには問題がある可能性があります。

public class MyImageView extends ImageView {


    private final AttributeSet attrs;
    private Paint paint;
    private Rect mSrcRect;
    private Rect mDestRect;
    private Bitmap mBitmap;
    public MyImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.attrs = attrs;
        initView();
    }

    public MyImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.attrs = attrs;
        initView();
    }

    private void initView() {
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setStyle(Paint.Style.FILL_AND_STROKE);
        paint.setStrokeWidth(10);
        paint.setColor(0xff000000);
    }

    @Override
    protected void onDraw(Canvas canvas) {
//        super.onDraw(canvas);
        //create the drawable.Maybe you can cache it.
        Drawable mDrawable = (BitmapDrawable) getResources().getDrawable(R.drawable.triangle_bas_accueil2);
        if (mDrawable == null) {
            return; // couldn't resolve the URI
        }
        int dWidth = mDrawable.getIntrinsicWidth();
        int dHeight = mDrawable.getIntrinsicHeight();

        float scale = 1.0f;
        scale = Math.max(getWidth() * 1.0f / dWidth, getHeight()
                * 1.0f / dHeight);
        int nWidth = (int) (dWidth*scale);
        int nHeight = (int) (dHeight*scale);
        int offsetLeft = (nWidth - getWidth())/2;
        int offsetTop = (nHeight - getHeight())/2;
        //cache mBitmap 
        mBitmap = mBitmap == null ? ((BitmapDrawable) mDrawable).getBitmap(): mBitmap;
        //custom mSrcRect mDestRect to achieve centerCrop
        mSrcRect = new Rect(0, 0, dWidth, dWidth);
        mDestRect = new Rect(-offsetLeft, -offsetTop,getWidth()+offsetLeft, getHeight()+offsetTop);
        int x = 250;int r = 100;
        int sc = canvas.saveLayer(0, 0, getWidth(), getHeight(), null,
                Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG
                        | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG
                        | Canvas.FULL_COLOR_LAYER_SAVE_FLAG
                        | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
        paint.setColor(0xffffffff);
        canvas.drawBitmap(mBitmap,mSrcRect,mDestRect,paint);
        paint.setColor(0xff000000);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
        canvas.drawCircle(x,x,r,paint);
        paint.setXfermode(null);
        canvas.restoreToCount(sc);
    }
}
于 2016-01-30T03:33:27.427 に答える
0

カスタムコード。各ピクセルをループして、アルファを変更します。ここにいくつかの擬似コードがあります:

for (int y = 0; y < imageHeight; y++) {
    for (int x = 0; x < imageWidth; x++) {
        // Check if the current pixel is within the circle
        if (dist(x, y, centerX, centerY) <= radius) {
            // Change the alpha
            image.setPixelAlpha(x, y, 0);
        }
    }
}
于 2016-01-29T14:50:21.010 に答える