2013-01-01 5 views
13

Es gibt eine nice post des beliebten Google-Entwicklers Romain Guy, die zeigt, wie Sie eine gerundete Ecken in einer Ansicht effizient zeichnen ("StreamDrawable" in his code).Verwenden einer abgerundeten Ecken Zeichen

Die Probe selbst funktioniert sehr gut auf meinem Galaxy S3, wenn im Portrait-Modus, aber ich habe ein paar Probleme mit ihm:

  1. wenn der Bildschirm klein ist (zum Beispiel auf QVGA-Bildschirmen), die gezeigt Bilder werden beschnitten.

  2. Wenn ein Eingabebitmap zu klein ist, als ich es anzeigen möchte, sind die Kanten des Ausgabebilds verschmiert. Auch auf dem Galaxy S3, wenn Sie den Beispielcode ausführen und es ist auf die Landschaft, es sieht schrecklich:

    enter image description here

  3. ich es immer noch nicht sicher bin (da ich eine Abhilfe der Skalierung des Bildes verwenden für Verwenden Sie den Beispielcode, aber es ist der Meinung, dass selbst diese Lösung bei Verwendung in einer ListView ein wenig langsam ist. Vielleicht gibt es dafür eine pigscript-Lösung?

Es spielt keine Rolle, ob ich setImageDrawable oder setBackgroundDrawable verwende. Es muss etwas im Drawable selbst sein.

Ich habe versucht, mit den Variablen und dem BitmapShader zu spielen, aber nichts hat funktioniert. Leider TileMode hat keinen Wert für nur das Bild zu dehnen, nur Tiling es in irgendeiner Weise.

Als Workaround kann ich eine neue skalierte Bitmap erstellen, aber es ist nur eine Ausweichlösung. Sicherlich gibt es einen besseren Weg, der auch nicht mehr Speicher verbraucht als er sollte.

Wie behebe ich diese Probleme und verwende diesen tollen Code?

+0

sollten Sie einen Kommentar zu diesem Artikel schreiben oder ihn anpingen, hier zu antworten. –

+0

Ich denke, er hat :) – DaRolla

+0

hast du das Problem gelöst? – tasomaniac

Antwort

9

Ich denke, dass die Lösung, die auf this website präsentiert wird, gut funktioniert.

Im Gegensatz zu anderen Lösungen verursacht es keine Speicherlecks, obwohl es auf der Lösung von Romain Guy basiert.

EDIT: jetzt auf der Support-Bibliothek, können Sie auch verwenden RoundedBitmapDrawable (mit RoundedBitmapDrawableFactory).

+0

Können Sie auf die Idee dahinter hinweisen (oder irgendwo, wo ich sie finden kann)? Ich habe wirklich keine Zeit, dieses ganze Projekt zu lesen. – suitianshi

+0

Ja, die Idee basiert sehr auf dem, was Romain Guy auf seiner Website präsentiert hat: http://www.curious-creature.org/2012/12/11/android -Rezept-1-Bild-mit-abgerundeten Ecken /. –

4

Ich hatte einige Größenprobleme mit diesem Code, und ich habe es gelöst.

Vielleicht wird dies Ihnen helfen, auch:

1) im Konstruktor speichert die Bitmap in einer lokalen Variablen (zB privaten bmp Bitmap;)

2) zwei weitere Methoden außer Kraft setzen:

@Override 
    public int getIntrinsicWidth() { 
    return bmp.getWidth(); 
} 

@Override 
    public int getIntrinsicHeight() { 
    return bmp.getHeight(); 
} 

Mit freundlichen Grüßen, DaRolla

+1

nein, es hat nicht geholfen, und übrigens, wenn Sie nur die Breite und Höhe eines Bitmap benötigen, können Sie speichern sie stattdessen und setzen sie in den CTOR. –

+0

@DaRolla Danke, dass du mich darauf aufmerksam gemacht hast, hat mir viel Zeit gespart. – CanC

0

Es gibt zugrunde liegendes Problem, dass der TileMode des BitmapShader keine Skalierung o hat ption. Sie werden in der Quelle beachten Sie, dass es auf Shader.TileMode.CLAMP gesetzt worden ist, und die Dokumentation beschreiben, dass als:

die Kantenfarbe replizieren, wenn der Shader außerhalb seiner ursprünglichen Grenzen zieht

um dieses Problem zu umgehen Es gibt drei Lösungen:

  1. Beschränken Sie die Größe der Ansicht, in der der Zeichensatz an die Größe der Bitmap verwendet wird.
  2. Den Zeichnungsbereich einschränken; zum Beispiel ändern:

    int width = bounds.width() - mMargin; 
    int height = bounds.height() - mMargin; 
    mRect.set(mMargin, mMargin, width, height); 
    

    An:

    int width = Math.min(mBitmap.getWidth(), bounds.width()) - mMargin; 
    int height = Math.min(mBitmap.getHeight(), bounds.height()) - mMargin; 
    mRect.set(mMargin, mMargin, width, height); 
    
  3. Maßstab der Bitmap auf die Größe des ziehbar. Ich habe den Shader in onBoundsChange verschoben zu schaffen() und haben von hier aus eine neue Bitmap erstellen entschieden:

    bitmap = Bitmap.createScaledBitmap(mBitmap, width, height, true); 
    mBitmapShader = new BitmapShader(bitmap, 
         Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); 
    

    Beachten Sie, dass dies ein potentiell langsamen Betrieb und wird auf dem Haupt-Thread ausgeführt werden. Sie sollten sorgfältig überlegen, wie Sie es implementieren möchten, bevor Sie sich für diese letzte Lösung entscheiden.

+0

Was sind die Vor- und Nachteile jeder dieser Methoden? der dritte ist offensichtlich langsam und verbraucht mehr Speicher, aber was ist mit den anderen? welchen empfiehlst du? –

+0

Wenn Sie möchten, dass sich die Bitmap auf die Größe der Ansicht ausdehnt, ist eine Implementierung, die der letzten ähnlich ist, die einzige Möglichkeit, einen "BitmapShader" zu verwenden. Der erste wird die Größe der Ansicht selbst einschränken, während der zweite nur den Shader in der oberen linken Ecke der Ansicht malen wird. –

+0

Nun, was ist, wenn ich möchte, dass es sich wie ein normales imageView verhält, nur damit das Bild selbst abgerundete Ecken hat? –