2010-06-08 4 views
8

Je dois faire pivoter un ImageView de quelques degrés. Je fais cela par la surcharge et le sous-classement ImageView onDraw()Comment faire pivoter un dessin avec l'anti-alias activé

@Override 
protected void onDraw(Canvas canvas) { 
    canvas.save(); 
    canvas.scale(0.92f,0.92f); 
    canvas.translate(14, 0); 
    canvas.rotate(1,0,0); 
    super.onDraw(canvas); 
    canvas.restore(); 
} 

Le problème est que l'image qui en résulte montre un tas de crénelage.

http://img.skitch.com/20100608-gmdy4sexsm1c71di9rgiktdjhu.png

Comment puis-je anticrénelage un ImageView que je dois tourner afin d'éliminer les effets d'escalier? Y a-t-il une meilleure manière de faire cela?

Répondre

4

Si vous savez que votre Drawable est un BitmapDrawable, vous pouvez utiliser l'anti-aliasing dans la peinture du bitmap pour faire quelque chose comme ce qui suit:

/** 
* Not as full featured as ImageView.onDraw(). Does not handle 
* drawables other than BitmapDrawable, crop to padding, or other adjustments. 
*/ 
@Override 
protected void onDraw(Canvas canvas) { 
    final Drawable d = getDrawable(); 

    if(d!=null && d instanceof BitmapDrawable && ((BitmapDrawable)d).getBitmap()!=null) { 
     final Paint p = new Paint(Paint.ANTI_ALIAS_FLAG); 
     final int paddingLeft = getPaddingLeft(); 
     final int paddingTop = getPaddingTop(); 

     canvas.save(); 

     // do my rotation and other adjustments 
     canvas.scale(0.92f,0.92f); 
     canvas.rotate(1,0,0); 

     if(paddingLeft!=0) 
      canvas.translate(paddingLeft,0); 

     if(paddingTop!=0) 
      canvas.translate(0,paddingTop); 

     canvas.drawBitmap(((BitmapDrawable)d).getBitmap(),0,0,p); 
     canvas.restore(); 
    } 
} 
0

Cette rotation permet de résoudre une partie seulement du problème - bords déchiquetés, mais l'image est devenue plutôt bizarre.

iFound seulement une solution encore: dans OnDraw ou d'expédition méthode draw

 Bitmap bmp = ((BitmapDrawable)image.getDrawable()).getBitmap(); 
    double scale = (0.0+bmp.getWidth()+40.0)/getWidth(); 
    if (scale > 1){ 
     bmp = Bitmap.createScaledBitmap(bmp, getWidth()-40, (int) (bmp.getHeight()/scale), true); 
    } 

    canvas.drawColor(Color.TRANSPARENT); 
    canvas.save(); 

    canvas.translate(20, yShift); 

    int left = borderSize; 
    int top = borderSize; 
    int right = bmp.getWidth() - borderSize; 
    int bottom = bmp.getHeight() - borderSize; 

    if(showText){ 
     mPaint.setColor(Color.WHITE); 
     canvas.rotate(getAngel()); 
     canvas.drawRect(left, top, right, bottom, mPaint); 

     canvas.translate(0,0); 
     textFrame.draw(canvas); 
    }else{ 
     // rotaed bitmap 
     mMatrix.setRotate(getAngel()); 

     // draw bitmap after creation of new rotated bitmap from rotated matrix 
     canvas.drawBitmap(Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), mMatrix, true) 
        , 0, 0, mPaint); 
    } 
    canvas.restore();  
3

Set d'anticrénelage et filterBitmap à la peinture qui est dessiner l'image bitmap. J'ai eu un problème similaire et cela a fonctionné pour moi:

Paint bitmapPaint = new Paint(); 
bitmapPaint.setAntiAlias(true); 
bitmapPaint.setFilterBitmap(true); 
0

@ solution de Primoz990 a fonctionné pour moi :) J'ai aussi permis tramage, donc mon code final qui supprime les bords déchiquetés sur la rotation est la suivante:

Paint bitmapPaint = new Paint(); 
bitmapPaint.setAntiAlias(true); 
bitmapPaint.setFilterBitmap(true); 
bitmapPaint.setDither(true); 
1

j'ai fait ce qui suit pour le faire fonctionner:

Dans AndroidManifest.xml I a permis accélération matérielle <application android:hardwareAccelerated="true">.

Au lieu d'utiliser une coutume dessiner méthode, je l'ai changé la couche type de vue-parent à l'accélération matérielle avec l'anti-aliasing activé et ajouté mes sous-vues comme suit:

Paint layerPaint = new Paint(); 
layerPaint.setAntiAlias(true); 
layerPaint.setFilterBitmap(true); 
layerPaint.setDither(true); 

RelativeLayout parentLayout = (RelativeLayout) LayoutInflater.from(context).inflate(R.layout.myLayout, null); 
parentLayout.setLayerType(View.LAYER_TYPE_HARDWARE, layerPaint); 

parentLayout.addView(myChildView); 

Je dois ajouter que l'écrêtage ne peut pas être désactivé lors de l'utilisation de cette approche.

Questions connexes