2016-04-26 5 views
2

ich eine benutzerdefinierte Ansicht mit dem folgenden Code haben:Verschwommenes Bild nach Leinwand drehen, nur in Android 6

private final Drawable outerGauge; 
private final Drawable innerGauge; 
private float rotateX; 
private float rotateY; 
private int rotation = 0; 

{ 
    outerGauge = getContext().getDrawable(R.drawable.gauge_outer); 
    innerGauge = getContext().getDrawable(R.drawable.gauge_inner); 
} 

@Override 
protected void onDraw(Canvas canvas) { 
    super.onDraw(canvas); 
    outerGauge.draw(canvas); 
    canvas.rotate(rotation, rotateX, rotateY); 
    innerGauge.draw(canvas); 
    canvas.rotate(-rotation, rotateX, rotateY); 
} 

Die meiste Zeit dieses vollkommen klare Bilder erzeugt. Manchmal sieht das Ergebnis jedoch so aus: Das scheint nur auf einem meiner beiden Testgeräte zu passieren. Das Gerät ist ein Motorola Moto G, mit dem Android 6 Upgrade. Das andere Testgerät, das immer einwandfrei klare Bilder zu produzieren scheint, ist ein OnePlus X, Android 5. Es ist auch nicht konsistent, es passiert manchmal, und dann nicht wieder im nächsten Moment. Von dem, was ich testen konnte, hängt es nicht einmal von der Menge der angewendeten Rotation ab. Ich habe es jedoch nie in geraden Winkeln gesehen (0, 90, 180 Grad), und es scheint schlimmer zu sein bei Winkeln, die näher bei 45 oder 135 Grad liegen.

Das fragliche Bild ist ein importiertes SVG, das direkt in den Ordner res/drawable gestellt wird. Daher kann es nicht die Auflösung sein. (Außerdem wird gauge_outer in genau demselben Ordner platziert und genau so gemacht, obwohl dieser nicht verschwommen wird.)

Irgendwelche Ideen, wie man das löst?


Edit:

Okay, egal, was ich über die gesamte Widersprüchlichkeit sagte. Es scheint völlig konsistent zu sein und am schlimmsten zu sein, wenn die Rotation näher und näher an 90 Grad kommt. Sobald die Drehung genau 90 Grad beträgt, verschwindet der Indikator vollständig.


Edit:

Siehe: zwei Emulatoren, ein mit Android 5 und ein mit Android 6:

Android 5Android 6

Der vollständige Quellcode ist wie folgt:

package nl.dvandenberg.gauge; 

import android.content.Context; 
import android.graphics.Canvas; 
import android.graphics.drawable.Drawable; 
import android.util.AttributeSet; 
import android.view.View; 

public class GaugeView extends View { 
    private static final int ORIGINAL_ROTATE_Y = 510; 
    private static final int ORIGINAL_IMAGE_HEIGHT = 613; 
    private static final int ORIGINAL_IMAGE_WIDTH = 1046; 
    private final Drawable outerGauge; 
    private final Drawable innerGauge; 
    private float rotateX; 
    private float rotateY; 
    private int rotation = 0; 

    { 
     outerGauge = getContext().getDrawable(R.drawable.gauge_outer); 
     innerGauge = getContext().getDrawable(R.drawable.gauge_inner); 
    } 

    public GaugeView(Context context) { 
     super(context); 
     setProgress(48); 
    } 

    public GaugeView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     setProgress(48); 
    } 

    public GaugeView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     setProgress(48); 
    } 

    public void setProgress(double percentage) { 
     this.rotation = (int) (180 * Math.min(100, Math.max(0, percentage))/100); 
     invalidate(); 
    } 

    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
     double width = MeasureSpec.getSize(widthMeasureSpec); 
     double idealHeight = ORIGINAL_IMAGE_HEIGHT * width/ORIGINAL_IMAGE_WIDTH; 
     double height = Math.min(idealHeight, MeasureSpec.getSize(heightMeasureSpec)); 
     width = width * height/idealHeight; 
     heightMeasureSpec = MeasureSpec.makeMeasureSpec((int) height, MeasureSpec.getMode(heightMeasureSpec)); 

     rotateX = (float) (width/2f); 
     rotateY = (float) (height/ORIGINAL_IMAGE_HEIGHT * ORIGINAL_ROTATE_Y); 

     outerGauge.setBounds(0, 0, (int) width, (int) height); 
     innerGauge.setBounds(0, 0, (int) width, (int) height); 
     super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
     super.onDraw(canvas); 
     outerGauge.draw(canvas); 
     canvas.rotate(rotation, rotateX, rotateY); 
     innerGauge.draw(canvas); 
    } 
} 

mit Drawable/Gauge_inner.xml

<?xml version="1.0" encoding="utf-8"?> 
<vector xmlns:android="http://schemas.android.com/apk/res/android" 
    android:width="1046dp" 
    android:height="613dp" 
    android:viewportWidth="1046" 
    android:viewportHeight="613"> 

    <path 
     android:fillColor="#aa3939" 
     android:pathData="M142.541,516.071 C145.053,517.623,156.088,519.334,183.255,522.586 
C203.832,525.024,251.438,530.676,289.03,535.184 
C326.708,539.641,359.782,543.523,362.537,543.896 
C365.292,544.268,388.127,547.018,413.445,550.067 L459.289,555.468 
L462.946,560.401 C468.075,567.485,479.691,577.405,489.255,582.968 
C499.701,589.062,520.069,594.737,531.817,594.883 
C571.623,595.225,607.57,570.083,620.01,533.226 
C624.956,518.592,626.123,507.412,624.269,492.201 
C622.686,479.259,620.262,472.461,612.212,458.518 
C602.012,440.852,592.681,431.69,575.424,422.602 
C537.988,402.763,489.163,413.401,462.78,447.108 L458.957,452.086 
L449.523,453.146 C444.316,453.727,420.115,456.614,395.829,459.552 
C371.456,462.538,346.451,465.429,340.177,466.165 
C333.904,466.9,293.067,471.772,249.427,476.991 
C205.788,482.211,164.951,487.082,158.678,487.817 
C144.122,489.408,139.036,491.998,136.796,498.719 
C134.433,505.626,136.72,512.388,142.541,516.07 Z" /> 
</vector> 

und ziehbar/gauge_outer.xml

<?xml version="1.0" encoding="utf-8"?> 
<vector xmlns:android="http://schemas.android.com/apk/res/android" 
    android:width="1046dp" 
    android:height="613dp" 
    android:viewportWidth="1046" 
    android:viewportHeight="613"> 

    <path 
     android:fillColor="#aa3939" 
     android:pathData="M488.981,0.56719 C465.882,2.06727,430.783,6.96753,412.984,11.0677 
C392.285,15.768,387.285,17.0681,375.285,20.6683 
C231.691,63.4706,113.696,164.376,49.898,299.183 
C16.6993,369.187,0,444.491,0,523.495 
C0,540.296,0.0999961,541.696,1.99992,543.596 
C3.99984,545.596,5.29979,545.596,59.4977,545.596 
C113.696,545.596,114.996,545.596,116.995,543.596 
C118.895,541.696,118.995,540.296,118.995,522.595 
C118.995,504.894,118.895,503.494,116.995,501.594 
C115.095,499.694,113.695,499.594,85.2962,499.594 L55.6974,499.594 
L56.2974,489.793 C60.0973,433.69,76.3966,372.387,101.396,320.384 
C103.996,314.984,106.496,310.383,106.896,310.183 
C107.396,309.883,110.796,311.483,114.596,313.683 
C118.396,315.983,124.396,319.483,127.995,321.583 
C131.595,323.583,139.195,328.083,144.994,331.484 
C155.694,337.684,159.993,338.884,163.193,336.284 
C164.893,334.984,171.293,324.483,177.992,312.083 
C183.292,302.282,183.092,299.882,176.492,295.782 
C173.992,294.282,162.593,287.582,151.093,281.081 L130.294,269.08 L135.294,261.58 
C166.593,214.877,210.691,170.375,258.589,137.273 
C268.189,130.673,269.889,129.873,270.489,131.273 
C272.389,136.273,298.388,179.776,299.988,180.576 
C300.988,181.176,302.788,181.576,303.888,181.576 
C306.288,181.576,334.787,165.275,336.787,162.775 
C339.187,159.575,337.987,155.575,330.887,143.274 
C326.987,136.574,322.987,129.773,322.087,128.273 
C321.187,126.673,318.087,121.273,315.287,116.372 
C312.387,111.372,309.987,107.072,309.987,106.671 
C309.987,105.371,342.586,90.7702,360.385,84.0698 
C388.684,73.5692,427.382,63.5687,455.981,59.6685 
C468.68,57.8684,490.98,55.5683,495.579,55.5683 L499.979,55.5683 L499.979,85.0699 
C499.979,113.271,500.079,114.671,501.979,116.572 
C503.879,118.472,505.279,118.572,522.978,118.572 
C540.677,118.572,542.077,118.472,543.977,116.572 
C545.877,114.672,545.977,113.272,545.977,84.8703 L545.977,55.2687 
L555.977,55.9687 C581.776,57.5688,617.875,63.7691,644.874,71.0695 
C670.273,77.9699,702.072,89.7705,722.771,99.871 
C729.071,102.971,734.671,105.671,735.271,105.871 
C735.871,106.071,730.171,117.072,722.172,131.072 
C713.772,145.773,707.973,156.973,707.973,158.573 
C707.973,162.273,709.373,163.573,718.973,169.274 
C741.272,182.375,743.072,183.075,746.772,179.775 
C748.472,178.375,765.571,149.773,773.871,134.373 L776.471,129.773 
L787.471,137.373 C834.969,170.075,877.067,212.377,910.266,260.98 
C912.866,264.78,914.866,268.28,914.766,268.78 
C914.566,269.28,903.866,275.78,890.967,283.181 
C878.068,290.581,866.668,297.582,865.768,298.782 
C862.268,302.782,863.268,305.182,878.268,330.084 
C884.168,339.785,886.468,339.885,900.967,331.484 
C906.767,328.084,914.366,323.584,917.966,321.583 
C921.566,319.483,927.566,315.983,931.365,313.683 
C935.265,311.383,938.565,309.583,938.865,309.583 
C939.565,309.583,946.665,324.184,952.164,337.084 
C972.463,383.986,986.363,440.49,989.663,489.792 L990.263,499.592 
L960.664,499.592 C932.265,499.592,930.865,499.692,928.965,501.592 
C927.065,503.492,926.965,504.892,926.965,522.593 
C926.965,540.294,927.065,541.694,928.965,543.594 
C930.965,545.594,932.265,545.594,986.463,545.594 
C1041.86,545.594,1041.96,545.594,1044.06,543.494 
C1046.26,541.294,1046.26,540.994,1045.66,513.192 
C1044.76,470.69,1040.36,436.088,1031.36,398.586 
C1027.46,382.685,1026.86,380.485,1020.26,360.084 
C1009.06,325.382,990.461,284.58,971.762,253.578 
C923.864,174.276,855.866,108.873,775.07,64.3706 
C712.572,29.8688,645.075,8.96764,574.477,2.06727 
C555.278,0.16716,507.68,-0.63288,488.981,0.56719 Z" /> 
</vector> 
+0

Wo sitzen die Bilder in den Ressourcenordnern? – weston

+0

Wird es wirklich von 'canvas.rotate' verursacht? Wenn Sie diese '.rotate' Zeilen entfernen, sieht es wieder gut aus? – weston

+0

@weston Ich habe meine Frage aktualisiert, leider ist das Entfernen von .rotate aufgrund der inkonsistenten Art des Problems nicht wirklich eine praktikable Teststrategie. Es scheint, als ob eine Drehung um 0 Grad niemals irgendwelche Probleme verursacht, was im Grunde dasselbe ist. Um deine Frage zu beantworten, glaube ich nicht, dass canvas.rotate die Ursache ist, sondern ein Faktor ist. –

Antwort

2

Obwohl keine Antwort, ich habe es geschafft, eine Abhilfe zu finden. Bei dieser Problemumgehung wird das Bild auf eine Zeichenfläche gezeichnet, die mit einer Bitmap verknüpft ist, die dann in der onDraw-Methode auf die endgültige gedrehte Zeichenfläche gezeichnet wird.

Es scheint, dass dieses Problem wirklich nur mit nodpi-drawables auftritt, mit anderen Worten, importierte Svg's. Es ist jedoch sehr konsistent. Ob die Form ein Mehrwegvektor oder ein einfaches Quadrat ist, spielt keine Rolle, das Problem wird immer genau die gleiche Form annehmen, wobei die Bilder vollständig verschwinden, wenn die Leinwand um 90 ° gedreht wird.

Der vollständige Code verwenden ich dieses Problem zu umgehen, ist wie folgt:

package nl.dvandenberg.energymonitor.customViews; 

import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.Canvas; 
import android.graphics.Color; 
import android.graphics.drawable.Drawable; 
import android.util.AttributeSet; 
import android.view.View; 

import nl.dvandenberg.energymonitor.R; 

public class GaugeView extends View { 
    private static final int ORIGINAL_ROTATE_Y = 510; 
    private static final int ORIGINAL_IMAGE_HEIGHT = 613; 
    private static final int ORIGINAL_IMAGE_WIDTH = 1046; 
    private final Drawable outerGauge, innerGauge; 
    private float rotateX; 
    private float rotateY; 
    private int rotation = 0; 

    private Bitmap innerGaugeBitmap; 

    private final Canvas innerGaugeCanvas; 

    { 
     outerGauge = getContext().getDrawable(R.drawable.gauge_outer); 
     innerGauge = getContext().getDrawable(R.drawable.gauge_inner); 
     innerGaugeCanvas = new Canvas(); 
    } 

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

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

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

    public void setProgress(double percentage) { 
     this.rotation = (int) (180 * Math.min(100, Math.max(0, percentage))/100); 
     invalidate(); 
    } 

    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
     double width = MeasureSpec.getSize(widthMeasureSpec); 
     double idealHeight = ORIGINAL_IMAGE_HEIGHT * width/ORIGINAL_IMAGE_WIDTH; 
     double height = Math.min(idealHeight, MeasureSpec.getSize(heightMeasureSpec)); 
     width = width * height/idealHeight; 
     heightMeasureSpec = MeasureSpec.makeMeasureSpec((int) height, MeasureSpec.getMode(heightMeasureSpec)); 

     rotateX = (float) (width/2f); 
     rotateY = (float) (height/ORIGINAL_IMAGE_HEIGHT * ORIGINAL_ROTATE_Y); 

     outerGauge.setBounds(0, 0, (int) width, (int) height); 
     innerGauge.setBounds(0, 0, (int) width, (int) height); 

     if (innerGaugeBitmap != null){ 
      innerGaugeBitmap.recycle(); 
     } 
     innerGaugeBitmap = Bitmap.createBitmap((int) width, (int) height, Bitmap.Config.ARGB_8888); // Gives LINT-warning draw-allocation, but no other way to upscale bitmaps exists. 
     innerGaugeCanvas.setBitmap(innerGaugeBitmap); 
     innerGaugeBitmap.eraseColor(Color.TRANSPARENT); 
     innerGauge.draw(innerGaugeCanvas); 
     super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
     outerGauge.draw(canvas); 
     canvas.rotate(rotation, rotateX, rotateY); 
     canvas.drawBitmap(innerGaugeBitmap,0,0,null); 
    } 
} 

mit der wichtigen Teil auftritt im onMeasure Methode:

 if (innerGaugeBitmap != null){ 
      innerGaugeBitmap.recycle(); 
     } 
     innerGaugeBitmap = Bitmap.createBitmap((int) width, (int) height, Bitmap.Config.ARGB_8888); // Gives LINT-warning draw-allocation, but no other way to upscale bitmaps exists. 
     innerGaugeCanvas.setBitmap(innerGaugeBitmap); 
     innerGaugeBitmap.eraseColor(Color.TRANSPARENT); 
     innerGauge.draw(innerGaugeCanvas); 

I eine bugreport bei https://code.google.com/p/android/issues/detail?id=208453

eingereicht
+0

danke, erwähnen, dass Svg Rotation Probleme verursacht war wirklich hilfreich – Ragaisis