2015-12-03 14 views
6

私はこのカスタムDrawableを作って、Drawableを円で切り取る必要があります。しかし私の実装では、引出し可能なものは円形ではなく元の形式で出力されています。Android:Circular Drawable

public class CircularDrawable extends Drawable { 
    Paint mPaint,xfermodePaint; 
    Drawable mDrawable; 
    int[] vinylCenter = new int[2]; 
    int radius; 
    Bitmap src; 
    PorterDuffXfermode xfermode; 
    Rect rect; 
    Canvas testCanvas; 
    public CircularDrawable(Drawable drawable) { 
     mDrawable = drawable; 
     mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 
     mPaint.setColor(0xffffffff); 
     mPaint.setStyle(Paint.Style.FILL); 
     xfermodePaint = new Paint(Paint.ANTI_ALIAS_FLAG); 
     xfermode=new PorterDuffXfermode(PorterDuff.Mode.SRC_IN); 
     xfermodePaint.setXfermode(xfermode); 
     testCanvas=new Canvas(); 
    } 

    @Override 
    public void setBounds(Rect bounds) { 
     super.setBounds(bounds); 
     mDrawable.setBounds(bounds); 
    } 

    @Override 
    public void setBounds(int left, int top, int right, int bottom) { 
     super.setBounds(left, top, right, bottom); 
     mDrawable.setBounds(left, top, right, bottom); 
    } 

    @Override 
    protected void onBoundsChange(Rect bounds) { 
     super.onBoundsChange(bounds); 
     vinylCenter[0] = bounds.width()/2; 
     vinylCenter[1] = bounds.height()/2; 
     radius = (bounds.right - bounds.left)/2; 
     src = Bitmap.createBitmap(bounds.width(), bounds.height(), Bitmap.Config.ARGB_8888); 
     testCanvas.setBitmap(src); 
    } 


    @Override 
    public void draw(Canvas canvas) { 
     canvas.save(); 
     canvas.drawARGB(0, 0, 0, 0); 
     canvas.drawCircle(vinylCenter[0],vinylCenter[1],radius,mPaint); 
     mDrawable.draw(testCanvas); 
     canvas.drawBitmap(src,0f,0f,xfermodePaint); 
    } 



    @Override 
    public void setAlpha(int alpha) {/*ignored*/} 

    @Override 
    public void setColorFilter(ColorFilter colorFilter) {/*ignored*/} 

    @Override 
    public int getOpacity() { 
     /*ignored*/ 
     return 0; 
    } 
} 

私の間違いは何ですか?

また、私はsquareImageviewを使用して、このdrawableを表示して、onMeasureのビューを四角形にするだけです。 この質問はCircular imageviewのためのものではありません。

+2

が見[この](http://androidxref.com/6.0.0_r1/xref/frameworks/support/v4/donut/android/support/v4/graphics/drawable/RoundedBitmapDrawable.java)を参考にしてください。 – pskink

+0

@pskinkしかしこれは他の実装です。私はPorter/Duff実装での私の間違いを知りたい。 –

+0

正方形であれば、 '' DST ''全体の領域を描画していることを意味します。 – pskink

答えて

3

Porter/Duff xfermodeモードを使用すると、キャンバスにデフォルトでアルファチャンネルが表示されません。これが画像全体(src)が出力される理由です。 Porter/Duff xfermodeはアルファチャンネルに基づいて動作します。

Circular Drawable 2キャンバスの多くの実装では、1つにRGBイメージビットマップが与えられ、その他に円形マスクを持つアルファチャネルビットマップのみが与えられます。 Porter/Duff xfermodeisが適用され、結果がメインキャンバスに描画されます。

私の間違いは、xfermodeのキャンバス上のレイヤーを使用してアルファチャンネルを考慮する描画関数のキャンバスを指定していないことです。

描画機能は

@Override 
public void draw(Canvas canvas) { 
    int sc = canvas.saveLayer(null, null, 
        Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | 
        ); 
    canvas.drawCircle(vinylCenter[0],vinylCenter[1],radius,mPaint); 
    mDrawable.draw(testCanvas); 
    canvas.drawBitmap(src,0f,0f,xfermodePaint); 
    canvas.restoreToCount(sc); 
} 

フラグとアルファチャンネルを示すために、レイヤを保存した後xfermodeを用いてなるであろう。最後に、それを保存カウントに戻します。

3

だから基本的に私は、丸みを帯びたコーナー画像

public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, int pixels) { 
    Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); 
    Canvas canvas = new Canvas(output); 

    final int color = 0xff424242; 
    final Paint paint = new Paint(); 
    final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); 
    final RectF rectF = new RectF(rect); 
    final float roundPx = pixels; 

    paint.setAntiAlias(true); 
    canvas.drawARGB(0, 0, 0, 0); 
    paint.setColor(color); 
    canvas.drawRoundRect(rectF, roundPx, roundPx, paint); 

    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); 
    canvas.drawBitmap(bitmap, rect, rect, paint); 

    return output; 

を取得するには、このメソッドを使用しますが、ご指摘のように、時にはそれがうまく、それは作業を行いますが、どのような時間のほとんどを起こることは、あなたのImageViewのが持つかもしれないで、動作しません。そのscaletypeはcenterCropと他のタイプに設定されていますが、まず画像の高さを画像ビューと同じ高さと幅に圧縮するので、画像全体が画像ビューに収まるようになり、スケーリングは行われません。高さに基づいてこの関数を使用して角を作る角の高さの数

private int calculatePercentage(int percentage, int target) 
{ 
    int k = (int)(target*(percentage/100.0f)); 
    return k; 

} 

ので、私は同じように私のコードを使用します。これは私のすべての画像に同じ曲線を与える画像の高さのnew Bitmap(getRoundedCornerBitmap(bmp, calculatePercentage(5, bmp.getHeight()))); where 5 is 5は、一部の画像が他の人あなたは既に円形描画可能なため、実装を最適化した `

+0

もう1つの回避方法は尋ねられていません。あなたがscaletypeについて行った仮定は間違っています。デフォルトのscaletypeはfitCenterです。 –

+0

@Paritosh Tonkあなたは私の助けを借りることができますかどちらかの方法で私の仕事は完全に –

+0

あなたの助けに感謝します。思考は働くことではありません。そのコンセプトとその理由 –

2
For rounded imageview you can use this code 

    public class RoundedImageView extends ImageView { 

    public RoundedImageView(Context context) { 
     super(context); 
     // TODO Auto-generated constructor stub 
    } 

    public RoundedImageView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    public RoundedImageView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 

     Drawable drawable = getDrawable(); 

     if (drawable == null) { 
      return; 
     } 

     if (getWidth() == 0 || getHeight() == 0) { 
      return; 
     } 
     Bitmap b = ((BitmapDrawable) drawable).getBitmap(); 
     Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true); 

     int w = getWidth();//, h = getHeight(); 

     Bitmap roundBitmap = getCroppedBitmap(bitmap, w); 
     canvas.drawBitmap(roundBitmap, 0, 0, null); 

    } 

    public static Bitmap getCroppedBitmap(Bitmap bmp, int radius) 
    { 
     Bitmap sbmp; 
     if (bmp.getWidth() != radius || bmp.getHeight() != radius) 
      sbmp = Bitmap.createScaledBitmap(bmp, radius, radius, false); 
     else 
      sbmp = bmp; 
     Bitmap output = Bitmap.createBitmap(sbmp.getWidth(), sbmp.getHeight(),Config.ARGB_8888); 
     Canvas canvas = new Canvas(output); 

//  final int color = 0xffa19774; 
     final Paint paint = new Paint(); 
     final Rect rect = new Rect(0, 0, sbmp.getWidth(), sbmp.getHeight()); 

     paint.setAntiAlias(true); 
     paint.setFilterBitmap(true); 
     paint.setDither(true); 
     canvas.drawARGB(0, 0, 0, 0); 
//  paint.setColor(Color.parseColor("#BAB399")); 
     paint.setColor(Color.parseColor("#FF0000")); 
     canvas.drawCircle(sbmp.getWidth()/2 + 0.7f, sbmp.getHeight()/2 + 0.7f, sbmp.getWidth()/2 + 0.1f, paint); 
     paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); 
     canvas.drawBitmap(sbmp, rect, rect, paint); 

     return output; 
    } 
} 
4

よりも大きくしていることもサポートライブラリV4:

Google reference

/** 
* A Drawable that wraps a bitmap and can be drawn with rounded corners. You can create a 
* RoundedBitmapDrawable from a file path, an input stream, or from a 
* {@link android.graphics.Bitmap} object. 
* <p> 
* Also see the {@link android.graphics.Bitmap} class, which handles the management and 
* transformation of raw bitmap graphics, and should be used when drawing to a 
* {@link android.graphics.Canvas}. 
* </p> 
*/ 
public abstract class RoundedBitmapDrawable extends Drawable .... 
3
For circular imageview use the below code 

public class RoundedImageView extends ImageView { 

    public RoundedImageView(Context context) { 
     super(context); 
    } 

    public RoundedImageView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    public RoundedImageView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
     BitmapDrawable drawable = (BitmapDrawable) getDrawable(); 

     if (drawable == null) { 
      return; 
     } 

     if (getWidth() == 0 || getHeight() == 0) { 
      return; 
     } 

     Bitmap fullSizeBitmap = drawable.getBitmap(); 

     int scaledWidth = getMeasuredWidth(); 
     int scaledHeight = getMeasuredHeight(); 

     /* 
     * scaledWidth = scaledWidth/2; scaledHeight = scaledHeight/2; 
     */ 

     Bitmap mScaledBitmap; 
     if (scaledWidth == fullSizeBitmap.getWidth() 
       && scaledHeight == fullSizeBitmap.getHeight()) { 
      mScaledBitmap = fullSizeBitmap; 
     } else { 
      mScaledBitmap = Bitmap.createScaledBitmap(fullSizeBitmap, 
        scaledWidth, scaledHeight, true /* filter */); 
     } 

     // Bitmap roundBitmap = getRoundedCornerBitmap(mScaledBitmap); 

     // Bitmap roundBitmap = getRoundedCornerBitmap(getContext(), 
     // mScaledBitmap, 10, scaledWidth, scaledHeight, false, false, 
     // false, false); 
     // canvas.drawBitmap(roundBitmap, 0, 0, null); 

     Bitmap circleBitmap = getCircledBitmap(mScaledBitmap); 

     canvas.drawBitmap(circleBitmap, 0, 0, null); 

    } 

    public Bitmap getRoundedCornerBitmap(Context context, Bitmap input, 
      int pixels, int w, int h, boolean squareTL, boolean squareTR, 
      boolean squareBL, boolean squareBR) { 

     Bitmap output = Bitmap.createBitmap(w, h, Config.ARGB_8888); 
     Canvas canvas = new Canvas(output); 
     final float densityMultiplier = context.getResources() 
       .getDisplayMetrics().density; 

     final int color = 0xff424242; 

     final Paint paint = new Paint(); 
     final Rect rect = new Rect(0, 0, w, h); 
     final RectF rectF = new RectF(rect); 

     // make sure that our rounded corner is scaled appropriately 
     final float roundPx = pixels * densityMultiplier; 

     paint.setAntiAlias(true); 
     canvas.drawARGB(0, 0, 0, 0); 
     paint.setColor(color); 
     canvas.drawRoundRect(rectF, roundPx, roundPx, paint); 

     // draw rectangles over the corners we want to be square 
     if (squareTL) { 
      canvas.drawRect(0, 0, w/2, h/2, paint); 
     } 
     if (squareTR) { 
      canvas.drawRect(w/2, 0, w, h/2, paint); 
     } 
     if (squareBL) { 
      canvas.drawRect(0, h/2, w/2, h, paint); 
     } 
     if (squareBR) { 
      canvas.drawRect(w/2, h/2, w, h, paint); 
     } 

     paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); 
     canvas.drawBitmap(input, 0, 0, paint); 

     return output; 
    } 

    Bitmap getCircledBitmap(Bitmap bitmap) { 

     Bitmap result = Bitmap.createBitmap(bitmap.getWidth(), 
       bitmap.getHeight(), Bitmap.Config.ARGB_8888); 

     Canvas canvas = new Canvas(result); 

     int color = Color.BLUE; 
     Paint paint = new Paint(); 
     Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); 

     paint.setAntiAlias(true); 
     canvas.drawARGB(0, 0, 0, 0); 
     paint.setColor(color); 
     // canvas.drawRoundRect(rectF, roundPx, roundPx, paint); 
     canvas.drawCircle(bitmap.getWidth()/2, bitmap.getHeight()/2, 
       bitmap.getHeight()/2, paint); 

     paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); 
     canvas.drawBitmap(bitmap, rect, rect, paint); 

     return result; 
    } 

} 
0

あなたがPorterDuffXfermodeを使用している場合は、ハードウェアアクセラレーションを無効にしてみてください:

マニフェストでは全体の活動のために:

<activity android:hardwareAccelerated="false" /> 

それともxfermodeを使用されている特定のビュー上:

myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null); 
関連する問題