Drawables – Übersicht

Schreiben Sie jetzt
Jetpack Compose ist das empfohlene UI-Toolkit für Android. Hier erfahren Sie, wie Sie Grafiken in „Compose“ anzeigen lassen.
<ph type="x-smartling-placeholder"></ph> Bilder werden geladen →

Wenn Sie in Ihrer App statische Bilder anzeigen möchten, können Sie die Klasse Drawable und ihre abgeleiteten Klassen zum Zeichnen von Formen und Bilder. Eine Drawable ist eine allgemeine Abstraktion für etwas, das gezeichnet werden kann. Die verschiedenen abgeleiteten Klassen helfen bei spezifischen Bildern, und Sie können sie erweitern, um eigene Drawable-Objekte zu definieren. die sich anders verhalten.

Neben der Verwendung von Klassenkonstruktoren gibt es zwei Möglichkeiten, eine Drawable zu definieren und zu instanziieren:

  • Sie können eine in Ihrem Projekt gespeicherte Bildressource (eine Bitmapdatei) aufblähen.
  • Schwingen Sie eine XML-Ressource auf, die die Drawable-Eigenschaften definiert.

Hinweis: Möglicherweise bevorzugen Sie stattdessen die Verwendung eines Vektor-Drawables, das ein Bild mit einer Reihe von Punkten, Linien und Kurven sowie zugehörige Farbinformationen. Dadurch können Vektor-Drawables für verschiedene Größen ohne Qualitätsverlust skaliert werden. Weitere Informationen finden Sie unter Vektor Drawables-Übersicht.

Drawables aus Ressourcenbildern erstellen

Sie können Ihrer App Grafiken hinzufügen, indem Sie auf eine Bilddatei aus Ihrem Projektressourcen. Unterstützte Dateitypen sind PNG (bevorzugt), JPG (akzeptabel), und GIF (nicht zu empfehlen). App-Symbole, -Logos und andere Grafiken, z. B. die verwendeten für Spiele, gut für diese Technik geeignet sind.

Wenn Sie eine Bildressource verwenden möchten, fügen Sie Ihre Datei dem res/drawable/ hinzu Verzeichnis Ihres Projekts. Im Projekt können Sie auf das Bild verweisen, -Ressource aus Ihrem Code oder Ihrem XML-Layout. In beiden Fällen wird sie als Ressourcen-ID: Dies ist der Dateiname ohne Dateityperweiterung. Für Beispiel: my_image.png als my_image.

Hinweis:Bildressourcen werden im Das Verzeichnis res/drawable/ wird eventuell automatisch optimiert mit verlustfreie Bildkomprimierung durch das aapt-Tool während des Build-Prozesses . Dies ist beispielsweise bei einer PNG-Datei in echter Farbe der Fall, die nicht mehr als 256 Farben erfordert. kann in eine 8-Bit-PNG-Datei mit Farbpalette konvertiert werden. Dies führt zu einem Bild. die gleiche Qualität haben, aber weniger Arbeitsspeicher benötigen. Daher werden die Bild-Binärdateien die sich in diesem Verzeichnis befinden, können sich bei der Erstellung ändern. Wenn Sie vorhaben, Um das Bild in eine Bitmap umzuwandeln, platziere deine Bilder im Bereich res/raw/-Ordner, in dem das aapt-Tool die ändern können.

Das folgende Code-Snippet zeigt, wie ein ImageView erstellt wird, das ein aus einer Drawable-Ressource erstelltes Bild und fügt es dem Layout hinzu:

Kotlin

private lateinit var constraintLayout: ConstraintLayout

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    // Instantiate an ImageView and define its properties
    val i = ImageView(this).apply {
        setImageResource(R.drawable.my_image)
        contentDescription = resources.getString(R.string.my_image_desc)

        // set the ImageView bounds to match the Drawable's dimensions
        adjustViewBounds = true
        layoutParams = ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT)
    }

    // Create a ConstraintLayout in which to add the ImageView
    constraintLayout = ConstraintLayout(this).apply {

        // Add the ImageView to the layout.
        addView(i)
    }

    // Set the layout as the content view.
    setContentView(constraintLayout)
}

Java

ConstraintLayout constraintLayout;

protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);

  // Create a ConstraintLayout in which to add the ImageView
  constraintLayout = new ConstraintLayout(this);

  // Instantiate an ImageView and define its properties
  ImageView i = new ImageView(this);
  i.setImageResource(R.drawable.my_image);
  i.setContentDescription(getResources().getString(R.string.my_image_desc));

  // set the ImageView bounds to match the Drawable's dimensions
  i.setAdjustViewBounds(true);
  i.setLayoutParams(new ViewGroup.LayoutParams(
          ViewGroup.LayoutParams.WRAP_CONTENT,
          ViewGroup.LayoutParams.WRAP_CONTENT));

  // Add the ImageView to the layout and set the layout as the content view.
  constraintLayout.addView(i);
  setContentView(constraintLayout);
}

In anderen Fällen möchten Sie Ihre Bildressource möglicherweise als Drawable-Objekt verarbeiten, wie im Folgenden gezeigt. Beispiel:

Kotlin

val myImage: Drawable = ResourcesCompat.getDrawable(context.resources, R.drawable.my_image, null)

Java

Resources res = context.getResources();
Drawable myImage = ResourcesCompat.getDrawable(res, R.drawable.my_image, null);

Warnung:Jede eindeutige Ressource in Ihrem Projekt kann nur einen Status beibehalten, unabhängig davon, wie viele verschiedene Objekte und instanziieren Sie sie. Beispiel: Wenn Sie zwei Drawable-Objekte aus derselben Bildressource instanziieren und für ein Objekt ändern (z. B. das Alpha-Element), dann wirkt sich das auch auf der andere. Wenn es sich um mehrere Instanzen einer Image-Ressource handelt, der direkten Transformation des Drawable-Objekts, sollten Sie eine Tweening Animation

Das folgende XML-Snippet zeigt, wie du einer ImageView im XML-Layout eine Drawable-Ressource hinzufügen kannst:

<ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/my_image"
        android:contentDescription="@string/my_image_desc" />

Weitere Informationen zur Verwendung von Projektressourcen finden Sie unter Ressourcen und Assets.

Hinweis:Wenn Sie Bildressourcen als Quelle für Drawables verwenden, Achten Sie darauf, dass die Bilder die richtige Größe für verschiedene Pixeldichten haben. Wenn die Bilder nicht korrekt sind, werden sie vertikal skaliert, was zu Artefakten in Ihren Drawables führen kann. Weitere Informationen erhalten Sie unter Support für verschiedene Pixeldichten.

Drawables aus XML-Ressourcen erstellen

Wenn es einen Drawable-Wert gibt, Objekt, das Sie erstellen möchten, das anfangs nicht von Variablen abhängig ist, die in Ihrem Code oder Nutzerinteraktion ist, ist die Definition des Drawable in XML eine gute Option. Gleichmäßig Erwarten, dass sich die Eigenschaften des Drawable während der Interaktion des Nutzers ändern mit Ihrer Anwendung verwenden, sollten Sie das Objekt in XML definieren, da Sie die Eigenschaften später ändern können. das Objekt wurde instanziiert.

Nachdem Sie Drawable in XML definiert haben, speichern Sie die Datei im res/drawable/-Verzeichnis Ihres Projekts. Das folgende Beispiel zeigt die XML-Datei, definiert eine TransitionDrawable Ressource, die von Drawable übernimmt:

<!-- res/drawable/expand_collapse.xml -->
<transition xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/image_expand"/>
    <item android:drawable="@drawable/image_collapse"/>
</transition>

Rufen Sie dann das Objekt ab und instanziieren Sie es, indem Sie den Aufruf Resources#getDrawable() und die Ressourcen-ID Ihrer XML-Datei übergeben. Beliebig Drawable-Unterklasse die die Methode inflate() unterstützt, können in XML definiert und instanziiert werden. durch Ihre App.

<ph type="x-smartling-placeholder">

Jede Drawable-Klasse, die die XML-Inflation unterstützt, verwendet spezifische XML-Attribute zum Definieren der Objekteigenschaften. Mit dem folgenden Code wird die Methode TransitionDrawable und legt es als Inhalt eines ImageView-Objekt:

Kotlin

val transition= ResourcesCompat.getDrawable(
        context.resources,
        R.drawable.expand_collapse,
        null
) as TransitionDrawable

val image: ImageView = findViewById(R.id.toggle_image)
image.setImageDrawable(transition)

// Description of the initial state that the drawable represents.
image.contentDescription = resources.getString(R.string.collapsed)

// Then you can call the TransitionDrawable object's methods.
transition.startTransition(1000)

// After the transition is complete, change the image's content description
// to reflect the new state.

Java

Resources res = context.getResources();
TransitionDrawable transition =
    (TransitionDrawable) ResourcesCompat.getDrawable(res, R.drawable.expand_collapse, null);

ImageView image = (ImageView) findViewById(R.id.toggle_image);
image.setImageDrawable(transition);

// Description of the initial state that the drawable represents.
image.setContentDescription(getResources().getString(R.string.collapsed));

// Then you can call the TransitionDrawable object's methods.
transition.startTransition(1000);

// After the transition is complete, change the image's content description
// to reflect the new state.

Weitere Informationen zu den unterstützten XML-Attributen finden Sie in den Klassen. oben aufgeführt.

Form-Drawables

Ein ShapeDrawable-Objekt kann eine gute Option sein wenn Sie dynamisch eine zweidimensionale Grafik zeichnen möchten. Sie können Primitive Formen in einem ShapeDrawable-Objekt programmatisch zeichnen und wenden Sie die Stile an, die Ihre App benötigt.

ShapeDrawable ist eine abgeleitete Klasse von Drawable. Aus diesem Grund können Sie ShapeDrawable, wenn Drawable erwartet wird. Für Sie können beispielsweise ein ShapeDrawable-Objekt verwenden, um den Hintergrund einer Ansicht, indem er an die setBackgroundDrawable()-Methode der Ansicht übergeben wird. Sie können Ihre Form auch als benutzerdefinierte Ansicht hinzufügen und sie einem Layout in Ihrer App hinzufügen.

Da ShapeDrawable eine eigene draw()-Methode hat, können Sie abgeleitete Klasse von View, die die ShapeDrawable während des onDraw()-Ereignisses ein, wie in das folgende Codebeispiel:

Kotlin

class CustomDrawableView(context: Context) : View(context) {
    private val drawable: ShapeDrawable = run {
        val x = 10
        val y = 10
        val width = 300
        val height = 50
        contentDescription = context.resources.getString(R.string.my_view_desc)

        ShapeDrawable(OvalShape()).apply {
            // If the color isn't set, the shape uses black as the default.
            paint.color = 0xff74AC23.toInt()
            // If the bounds aren't set, the shape can't be drawn.
            setBounds(x, y, x + width, y + height)
        }
    }

    override fun onDraw(canvas: Canvas) {
        drawable.draw(canvas)
    }
}

Java

public class CustomDrawableView extends View {
  private ShapeDrawable drawable;

  public CustomDrawableView(Context context) {
    super(context);

    int x = 10;
    int y = 10;
    int width = 300;
    int height = 50;
    setContentDescription(context.getResources().getString(
            R.string.my_view_desc));

    drawable = new ShapeDrawable(new OvalShape());
    // If the color isn't set, the shape uses black as the default.
    drawable.getPaint().setColor(0xff74AC23);
    // If the bounds aren't set, the shape can't be drawn.
    drawable.setBounds(x, y, x + width, y + height);
  }

  protected void onDraw(Canvas canvas) {
    drawable.draw(canvas);
  }
}

Sie können die Klasse CustomDrawableView im Codebeispiel verwenden. wie bei jeder anderen benutzerdefinierten Ansicht. So können Sie zum Beispiel programmatisch zu einer Aktivität in Ihrer App hinzufügen, wie im Folgenden gezeigt. Beispiel:

Kotlin

private lateinit var customDrawableView: CustomDrawableView

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    customDrawableView = CustomDrawableView(this)

    setContentView(customDrawableView)
}

Java

CustomDrawableView customDrawableView;

protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  customDrawableView = new CustomDrawableView(this);

  setContentView(customDrawableView);
}

Wenn Sie stattdessen die benutzerdefinierte Ansicht im XML-Layout verwenden möchten, ist der Die Klasse CustomDrawableView muss den Konstruktor View(Context, AttributeSet) überschreiben, der aufgerufen wird, wenn die Klasse aus XML überhöht werden. Das folgende Beispiel zeigt, wie die CustomDrawableView im XML-Layout:

<com.example.shapedrawable.CustomDrawableView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        />

Die ShapeDrawable-Klasse, wie viele andere auch Drawable-Typen im android.graphics.drawable-Paket kannst du Folgendes tun: Definieren Sie verschiedene Eigenschaften des Objekts mithilfe öffentlicher Methoden. Ein Beispiel Eigenschaften wie Alphatransparenz, Farbfilter, Dither, Deckkraft und Farbe.

Du kannst auch einfache Drawable-Formen mithilfe von XML-Ressourcen definieren. Weitere Informationen erhalten Sie unter Form-Drawable in Drawable-Ressourcentypen

NinePatch-Drawables

Eine NinePatchDrawable-Grafik ist ein dehnbares Bitmapbild, das Sie als Hintergrund einer Ansicht verwenden können. Android-Geräte passt die Grafikgröße automatisch an den Inhalt der Ansicht an. Eine Die Verwendung eines NinePatch-Images ist der Hintergrund, der von der Standard-Android-App Schaltflächen: Schaltflächen müssen so gedehnt werden, dass mehrere Zeichenfolgen verschiedener Längen akzeptiert werden. A Die NinePatch-Grafik ist ein Standard-PNG-Bild mit einem zusätzlichen 1-Pixel-Rahmen. Es muss mit der Erweiterung 9.png im res/drawable/-Verzeichnis Ihres Projekts.

Mithilfe des Rahmens können Sie die dehnbaren und statischen Bereiche des Bildes definieren. Sie kennzeichnen einen dehnbaren Abschnitt, indem Sie einen oder mehrere 1 Pixel breite zeichnen. Schwarze Linie(n) im linken und oberen Teil des Rahmens (die anderen Rahmenpixel) sollte vollständig transparent oder weiß sein). Sie können so viele dehnbare Abschnitte ganz nach Bedarf anpassen. Die relative Größe der dehnbaren Abschnitte bleibt gleich, sodass bleibt der größte Abschnitt immer der größte.

Sie können auch einen optionalen Drawable-Abschnitt des Bildes definieren (effektiv die Abstände), indem Sie rechts eine Linie und unten eine Linie zeichnen. Wenn ein Das View-Objekt legt die NinePatch-Grafik als Hintergrund fest. und gibt dann den Text der Ansicht an, streckt er sich selbst, sodass der gesamte Text wird nur den durch die rechte und untere Zeile (falls eingeschlossen) vorgesehenen Bereich festgelegt. Wenn keine Abstände enthalten sind, nutzt Android die linken und oberen Linien, um Zeichnungsbereich definieren.

Um den Unterschied zwischen den Linien zu verdeutlichen, definieren die linke und die obere Linie welche Pixel des Bildes repliziert werden dürfen, um das Bild zu strecken Bild. Die untere und die rechte Linie definieren den relativen Bereich im Bild, der die Inhalte der Ansicht einnehmen dürfen.

Abbildung 1 zeigt ein Beispiel für eine NinePatch-Grafik zur Definition einer Schaltfläche:

Bild des dehnbaren Bereichs
und Padding-Feld

Abbildung 1: Beispiel für eine NinePatch-Grafik der eine Schaltfläche definiert,

Diese NinePatch-Grafik definiert einen dehnbaren Bereich mit der linken und oberen Linien und den Zeichnungsbereich mit den unteren und rechten Linien. Im oberen Bild Die gepunkteten grauen Linien kennzeichnen die Regionen des Images, die repliziert wurden. um das Bild zu dehnen. Das rosa Rechteck im unteren Bild identifiziert Die Region, in der der Inhalt der Ansicht zulässig ist. Wenn die Inhalte nicht in diesen Bereich passen, wird das Bild so gestreckt, dass es passt.

Das Tool Draw 9-patch bietet eine äußerst praktische Möglichkeit, Ihre NinePatch-Images mithilfe einer WYSIWYG-Grafik zu erstellen. Editor. Es werden sogar Warnungen ausgegeben, wenn in der Region, die Sie für die kann es zu Zeichenartefakten aufgrund des Pixel- Replikation.

Das folgende Beispiel für eine Layout-XML-Datei zeigt, wie eine NinePatch-Grafik hinzugefügt wird. auf ein paar Schaltflächen. Das NinePatch-Bild wird unter res/drawable/my_button_background.9.png

<Button android:id="@+id/tiny"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerInParent="true"
        android:text="Tiny"
        android:textSize="8sp"
        android:background="@drawable/my_button_background"/>

<Button android:id="@+id/big"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerInParent="true"
        android:text="Biiiiiiig text!"
        android:textSize="30sp"
        android:background="@drawable/my_button_background"/>

Beachten Sie, dass die layout_width und layout_height Attribute sind auf wrap_content gesetzt, damit die Schaltfläche gut passt. um den Text herum.

Abbildung 2 zeigt die beiden Schaltflächen, die aus dem XML- und dem NinePatch-Bild gerendert werden. wie oben dargestellt. Beachten Sie, wie Breite und Höhe der Schaltfläche je nach Text variieren. und das Hintergrundbild wird gestreckt.

Bild von winzigen und
normale Schaltflächen

Abbildung 2:Mit einer XML-Datei gerenderte Schaltflächen und eine NinePatch-Grafik

Benutzerdefinierte Drawables

Wenn Sie benutzerdefinierte Zeichnungen erstellen möchten, können Sie dazu die Klasse Drawable oder eine ihrer abgeleiteten Klassen erweitern.

Die wichtigste Methode zur Implementierung ist draw(Canvas). da dies das Canvas-Objekt bereitstellt, das Sie zur Bereitstellung Ihre Zeichenanleitungen.

Der folgende Code zeigt eine einfache abgeleitete Klasse von Drawable. mit dem ein Kreis gezeichnet wird:

Kotlin

class MyDrawable : Drawable() {
    private val redPaint: Paint = Paint().apply { setARGB(255, 255, 0, 0) }

    override fun draw(canvas: Canvas) {
        // Get the drawable's bounds
        val width: Int = bounds.width()
        val height: Int = bounds.height()
        val radius: Float = Math.min(width, height).toFloat() / 2f

        // Draw a red circle in the center
        canvas.drawCircle((width / 2).toFloat(), (height / 2).toFloat(), radius, redPaint)
    }

    override fun setAlpha(alpha: Int) {
        // This method is required
    }

    override fun setColorFilter(colorFilter: ColorFilter?) {
        // This method is required
    }

    override fun getOpacity(): Int =
        // Must be PixelFormat.UNKNOWN, TRANSLUCENT, TRANSPARENT, or OPAQUE
        PixelFormat.OPAQUE
}

Java

public class MyDrawable extends Drawable {
    private final Paint redPaint;

    public MyDrawable() {
        // Set up color and text size
        redPaint = new Paint();
        redPaint.setARGB(255, 255, 0, 0);
    }

    @Override
    public void draw(Canvas canvas) {
        // Get the drawable's bounds
        int width = getBounds().width();
        int height = getBounds().height();
        float radius = Math.min(width, height) / 2;

        // Draw a red circle in the center
        canvas.drawCircle(width/2, height/2, radius, redPaint);
    }

    @Override
    public void setAlpha(int alpha) {
        // This method is required
    }

    @Override
    public void setColorFilter(ColorFilter colorFilter) {
        // This method is required
    }

    @Override
    public int getOpacity() {
        // Must be PixelFormat.UNKNOWN, TRANSLUCENT, TRANSPARENT, or OPAQUE
        return PixelFormat.OPAQUE;
    }
}

Dann kannst du dein Drawable an einer beliebigen Stelle hinzufügen, ImageView, wie hier gezeigt:

Kotlin

val myDrawing = MyDrawable()
val image: ImageView = findViewById(R.id.imageView)
image.setImageDrawable(myDrawing)
image.contentDescription = resources.getString(R.string.my_image_desc)

Java

MyDrawable mydrawing = new MyDrawable();
ImageView image = findViewById(R.id.imageView);
image.setImageDrawable(mydrawing);
image.setContentDescription(getResources().getString(R.string.my_image_desc));

Unter Android 7.0 (API-Level 24) und höher kannst du auch Instanzen deines benutzerdefinierten Drawable-Elements definieren mit XML auf folgende Weise verwenden:

  • Verwendung des voll qualifizierten Klassennamens als XML-Elementnamen. Bei diesem Ansatz wird die benutzerdefinierte Drawable-Klasse muss eine öffentliche Klasse der obersten Ebene sein:
    <com.myapp.MyDrawable xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="#ffff0000" />
    
  • Verwendung von drawable als XML-Tag-Namen und Angabe der voll qualifizierten Klasse Name aus dem Klassenattribut. Dieser Ansatz kann sowohl für öffentliche Top-Level-Klassen als auch für öffentlichen statischen inneren Klassen:
    <drawable xmlns:android="http://schemas.android.com/apk/res/android"
        class="com.myapp.MyTopLevelClass$MyDrawable"
        android:color="#ffff0000" />
    
<ph type="x-smartling-placeholder">

Drawables färben

Unter Android 5.0 (API-Level 21) und höher können Sie Bitmaps und neun Patches entsprechend der Definition Alphamasken. Sie können sie mit Farbressourcen oder Themenattributen färben, die zur Farbe aufgelöst werden. Ressourcen (z. B. ?android:attr/colorPrimary). Normalerweise erstellen Sie diese Assets und sie automatisch an Ihr Design anpassen.

Du kannst BitmapDrawable, NinePatchDrawable oder VectorDrawable färben. -Objekt mit der Methode setTint() zu erstellen. Sie können Legen Sie auch die Färbung und den Modus in Ihren Layouts mit den android:tint und android:tintMode-Attribute.

Hervorgehobene Farben aus einem Bild extrahieren

Die Android Support Library enthält die Klasse Palette, mit der du markante Farben aus einem Bild extrahieren kannst. Du kannst deine Drawables als Bitmap laden und an Palette übergeben, um auf seine Farben zuzugreifen. Weitere Informationen finden Sie unter Farben auswählen mit Palette API