Ringkasan yang dapat digambar

Mencoba cara Compose
Jetpack Compose adalah toolkit UI yang direkomendasikan untuk Android. Pelajari cara menampilkan grafik di Compose.

Jika perlu menampilkan gambar statis di aplikasi, Anda dapat menggunakan class Drawable dan subclass-nya untuk menggambar bentuk dan gambar. Drawable adalah abstraksi umum untuk sesuatu yang bisa digambar. Berbagai subclass berguna terkait image spesifik skenario, dan Anda dapat memperluasnya untuk mendefinisikan objek drawable Anda sendiri yang berperilaku unik.

Ada dua cara untuk menentukan dan membuat instance Drawable selain menggunakan class constructor:

  • Meluaskan resource gambar (file bitmap) yang tersimpan di project Anda.
  • Meluaskan resource XML yang menentukan properti drawable.

Catatan: Anda mungkin lebih suka menggunakan vektor drawable, yang mendefinisikan gambar dengan serangkaian titik, garis, dan kurva, beserta informasi warna terkait. Parameter ini memungkinkan vektor drawable disesuaikan untuk berbagai ukuran tanpa mengurangi kualitas. Untuk informasi selengkapnya, lihat Vektor ringkasan drawable.

Membuat drawable dari gambar resource

Anda bisa menambahkan grafik ke aplikasi dengan mereferensikan file gambar dari sumber daya proyek. Jenis file yang didukung adalah PNG (lebih disukai), JPG (dapat diterima), dan GIF (tidak direkomendasikan). Ikon aplikasi, logo, dan grafik lainnya, seperti yang digunakan dalam {i>game<i}, sangat cocok untuk teknik ini.

Untuk menggunakan resource gambar, tambahkan file Anda ke res/drawable/ direktori proyek. Setelah berada di project, Anda dapat mereferensikan gambar resource dari kode atau tata letak XML Anda. Bagaimanapun, ini disebut dengan menggunakan sebuah ID resource, yang merupakan nama file tanpa ekstensi jenis file. Sebagai contoh, lihat my_image.png sebagai my_image.

Catatan: Resource gambar yang ditempatkan di Direktori res/drawable/ dapat dioptimalkan secara otomatis dengan Kompresi gambar lossless oleh alat aapt selama build {i>checkout<i}. Misalnya, PNG warna asli yang tidak memerlukan lebih dari 256 warna dapat dikonversi ke PNG 8-bit dengan palet warna. Ini menghasilkan gambar dengan kualitas yang sama tetapi membutuhkan lebih sedikit memori. Hasilnya, biner gambar yang ditempatkan di direktori ini dapat berubah pada waktu build. Jika Anda berencana membaca sebagai bitstream untuk mengonversinya ke bitmap, letakkan gambar Anda dalam Folder res/raw/, di mana alat aapt tidak mengubahnya.

Cuplikan kode berikut menunjukkan cara membuat ImageView yang menggunakan gambar yang dibuat dari resource drawable dan menambahkannya ke tata letak:

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);
}

Dalam kasus lain, Anda mungkin ingin menangani resource gambar sebagai objek Drawable, seperti ditunjukkan dalam contoh berikut contoh:

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);

Peringatan: Setiap resource unik dalam project Anda hanya dapat mempertahankan satu status, tidak peduli berapa banyak objek yang berbeda buat instance untuk resource tersebut. Misalnya, jika Anda membuat instance dua objek Drawable dari resource gambar yang sama dan mengubah properti (seperti alfa) untuk satu objek, maka hal itu juga akan memengaruhi satu sama lain. Saat menangani beberapa instance resource gambar, transformasi objek Drawable secara langsung, Anda harus melakukan remaja animasi.

Cuplikan XML di bawah ini menunjukkan cara menambahkan resource drawable ke ImageView dalam tata letak XML:

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

Untuk informasi selengkapnya tentang cara menggunakan resource project, lihat Resource dan aset.

Catatan: Saat menggunakan resource gambar sebagai sumber drawable, memastikan gambar memiliki ukuran yang sesuai untuk berbagai kepadatan piksel. Jika gambar yang tidak benar akan ditingkatkan skalanya agar sesuai, yang dapat menyebabkan artefak dalam drawable Anda. Untuk informasi selengkapnya, baca Mendukung kepadatan piksel.

Membuat drawable dari resource XML

Jika ada Drawable yang ingin Anda buat, yang awalnya tidak bergantung pada variabel yang ditentukan oleh kode atau interaksi pengguna, maka menentukan Drawable dalam XML adalah opsi yang bagus. Merata jika Anda ingin Drawable mengubah propertinya selama interaksi pengguna dengan aplikasi Anda, Anda harus mempertimbangkan untuk mendefinisikan objek dalam XML, karena Anda bisa memodifikasi properti setelah objek telah dibuat instance-nya.

Setelah Anda menentukan Drawable di XML, simpan file di res/drawable/ pada project Anda. Contoh berikut menunjukkan XML yang mendefinisikan TransitionDrawable resource, yang diturunkan dari Drawable:

<!-- 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>

Kemudian, ambil dan buat instance objek dengan memanggil Resources#getDrawable() dan meneruskan ID resource file XML Anda. Apa saja Subclass Drawable yang mendukung metode inflate() dapat ditentukan dalam XML dan dibuat instance-nya oleh aplikasi Anda.

Setiap class drawable yang mendukung perluasan XML menggunakan atribut XML tertentu yang membantu menentukan properti objek. Kode berikut membuat instance TransitionDrawable dan menyetelnya sebagai konten Objek ImageView:

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.

Untuk informasi selengkapnya tentang atribut XML yang didukung, lihat class yang tercantum di atas.

Drawable bentuk

Objek ShapeDrawable dapat menjadi opsi yang bagus jika Anda ingin menggambar secara dinamis grafik dua dimensi. Anda dapat menggambar bentuk dasar secara terprogram pada objek ShapeDrawable dan menerapkan gaya yang dibutuhkan aplikasi Anda.

ShapeDrawable adalah subclass dari Drawable. Karena alasan ini, Anda dapat menggunakan ShapeDrawable di mana pun Drawable diharapkan. Sebagai Misalnya, Anda dapat menggunakan objek ShapeDrawable untuk menyetel latar belakang tampilan dengan meneruskannya ke metode setBackgroundDrawable() tampilan. Anda juga bisa menggambar bentuk sesuai dengan tampilan kustom Anda sendiri dan menambahkannya ke tata letak dalam aplikasi Anda.

Karena ShapeDrawable memiliki metode draw() sendiri, Anda dapat membuat subclass dari View yang menggambar ShapeDrawable selama peristiwa onDraw(), seperti ditunjukkan dalam contoh kode berikut:

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);
  }
}

Anda dapat menggunakan class CustomDrawableView dalam contoh kode di atas seperti yang Anda gunakan pada tampilan kustom lainnya. Sebagai contoh, Anda dapat secara terprogram menambahkannya ke aktivitas di aplikasi Anda, seperti yang ditunjukkan contoh:

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);
}

Jika Anda ingin menggunakan tampilan kustom dalam tata letak XML, maka metode Class CustomDrawableView harus mengganti konstruktor View(Context, AttributeSet), yang dipanggil saat class di-inflate dari XML. Contoh berikut menunjukkan cara mendeklarasikan atribut CustomDrawableView dalam tata letak XML:

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

Class ShapeDrawable, seperti banyak class lainnya jenis drawable dalam paket android.graphics.drawable, memungkinkan Anda mendefinisikan berbagai properti objek dengan menggunakan metode publik. Beberapa contoh properti yang mungkin ingin Anda sesuaikan antara lain transparansi alfa, filter warna, dither, opasitas, dan warna.

Anda juga dapat menentukan bentuk-bentuk drawable dasar menggunakan resource XML. Untuk selengkapnya informasi, lihat Drawable bentuk di Jenis resource drawable.

Drawable NinePatch

Grafik NinePatchDrawable adalah gambar bitmap yang bisa direntangkan yang bisa digunakan sebagai latar belakang tampilan. Android secara otomatis mengubah ukuran grafik untuk mengakomodasi isi tampilan. Channel contoh penggunaan gambar NinePatch adalah latar belakang yang digunakan oleh tombol—tombol harus membentang untuk mengakomodasi string dengan panjang yang berbeda. J Grafis NinePatch adalah gambar PNG standar yang mencakup batas tambahan berukuran 1 piksel. Kunci ini harus disimpan dengan ekstensi 9.png di res/drawable/ pada project Anda.

Gunakan garis batas ini untuk menentukan area stretchable dan area statis gambar. Anda mengindikasikan bagian yang dapat direntangkan dengan menggambar satu (atau beberapa) lebar 1 piksel garis hitam di bagian kiri dan atas batas (piksel pembatas lainnya harus sepenuhnya transparan atau putih). Anda dapat memiliki sebanyak mungkin bagian yang dapat direntangkan sesuai keinginan. Ukuran relatif dari bagian yang dapat direntangkan tetap sama, jadi bagian terbesar akan selalu menjadi yang terbesar.

Anda juga bisa mendefinisikan bagian drawable opsional dari gambar (secara efektif, garis {i>padding<i}) dengan menggambar garis di sebelah kanan dan garis di bagian bawah. Jika Objek View menetapkan grafis NinePatch sebagai latar belakangnya lalu menentukan teks tampilan, akan melebarkan sendiri sehingga semua teks hanya menempati area yang ditentukan oleh garis kanan dan bawah (jika disertakan). Jika garis padding tidak disertakan, Android akan menggunakan garis kiri dan atas untuk menentukan area drawable ini.

Untuk memperjelas perbedaan antara garis, garis kiri dan atas menentukan piksel gambar mana yang diperbolehkan untuk direplikasi untuk meregangkan gambar. Garis bawah dan kanan menentukan area relatif dalam gambar yang isi tampilan yang boleh ditempati.

Gambar 1 menunjukkan contoh grafis NinePatch yang digunakan untuk menentukan sebuah tombol:

Gambar area yang dapat direntangkan
dan kotak padding

Gambar 1: Contoh grafis NinePatch yang mendefinisikan tombol

Grafis NinePatch ini menentukan satu area yang dapat direntangkan dengan kiri dan atas garis, dan area drawable dengan garis bawah dan kanan. Pada gambar di atas, garis abu-abu putus-putus mengidentifikasi area gambar yang direplikasi untuk meregangkan gambar. Persegi panjang merah muda di gambar bawah mengidentifikasi wilayah tempat konten tampilan diizinkan. Jika konten tidak sesuai dengan wilayah ini, maka gambar direntangkan agar pas.

Alat Draw 9-patch menawarkan cara yang sangat praktis untuk membuat gambar NinePatch, menggunakan grafik WYSIWYG . Aplikasi ini bahkan memberikan peringatan jika wilayah yang telah Anda tentukan untuk area yang dapat direntangkan area ini berisiko menghasilkan artefak gambar akibat penggunaan piksel replikasi.

Contoh XML tata letak berikut menunjukkan cara menambahkan grafis NinePatch hingga beberapa tombol. Gambar NinePatch disimpan ke 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"/>

Perhatikan bahwa layout_width dan layout_height disetel ke wrap_content agar tombol terlihat pas di sekitar teks.

Gambar 2 menunjukkan dua tombol yang dirender dari XML dan gambar NinePatch yang ditunjukkan di atas. Perhatikan bagaimana lebar dan tinggi tombol bervariasi menurut teks, dan gambar latar memanjang untuk mengakomodasinya.

Gambar kecil dan
tombol ukuran normal

Gambar 2: Tombol yang dirender menggunakan XML dan grafis NinePatch

Drawable kustom

Jika ingin membuat beberapa gambar kustom, Anda dapat melakukannya dengan memperluas class Drawable (atau salah satu subclass-nya).

Metode paling penting untuk diterapkan adalah draw(Canvas) karena ini menyediakan objek Canvas yang harus Anda gunakan untuk menyediakan instruksi gambar Anda.

Kode berikut menampilkan subclass sederhana dari Drawable yang menggambar lingkaran:

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;
    }
}

Kemudian Anda dapat menambahkan drawable di mana pun Anda inginkan, misalnya ke ImageView seperti yang ditunjukkan di sini:

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));

Di Android 7.0 (API level 24) dan yang lebih tinggi, Anda juga bisa menentukan instance dari drawable kustom Anda dengan XML melalui cara berikut:

  • Menggunakan nama class yang sepenuhnya memenuhi syarat sebagai nama elemen XML. Untuk pendekatan ini, kustom drawable harus berupa class publik level teratas:
    <com.myapp.MyDrawable xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="#ffff0000" />
    
  • Menggunakan drawable sebagai nama tag XML dan menentukan class yang sepenuhnya memenuhi syarat dari atribut kelas. Pendekatan ini dapat digunakan baik untuk kelas publik tingkat atas dan public static inner class:
    <drawable xmlns:android="http://schemas.android.com/apk/res/android"
        class="com.myapp.MyTopLevelClass$MyDrawable"
        android:color="#ffff0000" />
    

Menambahkan tint ke drawable

Dengan Android 5.0 (API level 21) dan yang lebih tinggi, Anda bisa mewarnai bitmap dan nine-patch yang didefinisikan sebagai {i>alpha mask<i}. Anda dapat mewarnainya dengan resource warna atau atribut tema yang me-resolve warna (misalnya, ?android:attr/colorPrimary). Biasanya, Anda yang membuat aset ini sekali saja dan warnanya secara otomatis agar sesuai dengan tema Anda.

Anda dapat menerapkan tint ke BitmapDrawable, NinePatchDrawable, atau VectorDrawable objek dengan metode setTint(). Anda dapat tetapkan warna dan mode tint di tata letak Anda dengan android:tint dan Atribut android:tintMode.

Mengekstrak warna yang menonjol dari gambar

Android Support Library menyertakan class Palette, yang memungkinkan Anda mengekstrak warna-warna yang menonjol dari sebuah gambar. Anda dapat memuat drawable sebagai Bitmap dan meneruskannya ke Palette untuk mengakses warnanya. Untuk informasi selengkapnya, baca Memilih warna dengan Palette API.