2016-01-29 2 views
1

Я снова прихожу к идее мозга Android.Android Создайте круговое отверстие в центре. Обрезанное изображение.

Я хотел бы поместить отверстие для отверстия в круге в изображении, в котором растровое изображение масштабируется как centerCrop. Я знаю, где мне нужно положить отверстие для круга (в 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() вызывается дважды (возможно, это нужно), но это делает меня два отверстия, одно, что я могу изменить параметры, но другие все еще на том же месте! Контейнер MyImageView - это RelativeLayout.

Если у кого-то есть идея? @ крошечный солнечный свет?

+0

Я думаю, что вам лучше настроить пользовательский ImageView. –

+0

есть ли у вас пример, чтобы помочь мне начать решение? –

ответ

1

Это один раз для CenterCrop и не может справиться с scaleType.And этот код может иметь некоторые проблемы, потому что я не очень хорошо на холсте.

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); 
    } 
} 
+0

благодаря @ крошечному солнечному свету ваше решение работает, но я могу " t сохранить 'ScaleType'property моего' ImageView':/ –

+0

Я редактирую код для case scaleType = CenterCrop. –

+0

Я добавил свой код @ крошечный солнечный свет, потому что у меня есть отверстие, которое появляется само по себе –

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); 
     } 
    } 
} 
+0

Я не думаю, что это хорошая идея, мой drawable является hudge, поэтому вычисление результата, как это может занять более 10 секунд, слишком долго, чтобы позволить процессу пользовательского интерфейса делать oit –

Смежные вопросы