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 dapat digambar. Berbagai subclass berguna dalam skenario gambar
tertentu, dan Anda dapat memperluasnya untuk menentukan objek drawable Anda sendiri
yang berperilaku secara 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 menentukan gambar dengan sekumpulan titik, garis, dan kurva, beserta informasi warna terkait. Hal ini memungkinkan vektor drawable diskalakan ke berbagai ukuran tanpa mengurangi kualitas. Untuk informasi selengkapnya, lihat Ringkasan vektor drawable.
Membuat drawable dari gambar resource
Anda dapat menambahkan grafis ke aplikasi dengan mereferensikan file gambar dari resource project Anda. Jenis file yang didukung adalah PNG (disarankan), JPG (dapat diterima), dan GIF (tidak direkomendasikan). Ikon aplikasi, logo, dan grafis lainnya, seperti yang digunakan dalam game, sangat cocok untuk teknik ini.
Untuk menggunakan resource gambar, tambahkan file Anda ke direktori res/drawable/
project Anda. Setelah berada di project, Anda dapat mereferensikan resource
gambar dari kode atau tata letak XML Anda. Bagaimanapun, file ini dirujuk untuk menggunakan
ID resource, yang merupakan nama file tanpa ekstensi jenis file. Misalnya, rujuk ke my_image.png
sebagai my_image
.
Catatan: Resource gambar yang ditempatkan di
direktori res/drawable/
dapat otomatis dioptimalkan dengan
kompresi gambar lossless oleh alat aapt
selama proses
build. Misalnya, PNG warna asli yang tidak memerlukan lebih dari 256 warna
dapat dikonversi menjadi PNG 8 bit dengan palet warna. Cara ini akan menghasilkan gambar
dengan kualitas yang sama tetapi memerlukan lebih sedikit memori. Akibatnya, biner gambar yang ditempatkan di direktori ini dapat berubah selama waktu build. Jika Anda berencana membaca
gambar sebagai bitstream untuk mengonversinya ke bitmap, taruh gambar dalam
folder res/raw/
, tempat alat aapt
tidak
memodifikasinya.
Cuplikan kode berikut menunjukkan cara mem-build 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 pada contoh
berikut:
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, berapa pun jumlah objek berbeda yang Anda buat instance-nya. Misalnya, jika Anda membuat instance dua objek Drawable
dari resource gambar yang sama dan
mengubah properti (misalnya alfa) untuk satu objek, hal ini juga akan memengaruhi
objek lainnya. Saat menangani beberapa instance resource gambar, alih-alih
mengubah langsung objek Drawable
, Anda harus menjalankan
animasi
hitung nilai.
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: Ketika menggunakan resource gambar sebagai sumber drawable, pastikan gambar memiliki ukuran yang sesuai untuk berbagai kepadatan piksel. Jika tidak benar, gambar akan ditingkatkan skalanya agar pas, yang dapat menyebabkan artefak dalam drawable Anda. Untuk mengetahui informasi selengkapnya, baca Mendukung kepadatan piksel yang berbeda.
Membuat drawable dari resource XML
Jika ada objek Drawable
yang ingin Anda buat, yang awalnya tidak bergantung pada variabel yang ditetapkan oleh
kode Anda atau interaksi pengguna, menentukan Drawable
dalam XML adalah opsi yang tepat. Meskipun Anda memperkirakan Drawable
akan mengubah propertinya selama interaksi pengguna dengan aplikasi, Anda harus mempertimbangkan untuk menentukan objek ini dalam XML, karena Anda dapat mengubah properti setelah objek dibuat.
Setelah Anda menentukan Drawable
dalam XML, simpan file di
direktori res/drawable/
project Anda. Contoh berikut menunjukkan XML yang
menentukan
resource TransitionDrawable
, yang diwarisi 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>
Selanjutnya, ambil dan buat instance objek dengan memanggil
Resources#getDrawable()
dan meneruskan ID resource file XML Anda. Setiap subclass Drawable
yang mendukung metode inflate()
dapat ditentukan dalam XML dan dibuat instance-nya oleh aplikasi Anda.
Setiap class drawable yang mendukung inflation XML menggunakan atribut XML tertentu
yang membantu menentukan properti objek. Kode berikut membuat instance
TransitionDrawable
dan menetapkannya 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.
Sumber daya dapat digambar untuk bentuk
Objek ShapeDrawable
dapat menjadi opsi yang bagus
jika Anda ingin menggambar grafis dua dimensi secara dinamis. Anda dapat
menggambar bentuk dasar secara terprogram pada objek ShapeDrawable
dan menerapkan gaya yang diperlukan aplikasi Anda.
ShapeDrawable
adalah subclass dari Drawable
. Karena alasan ini, Anda dapat menggunakan
ShapeDrawable
di mana pun Drawable
diharapkan. Misalnya, Anda dapat menggunakan objek ShapeDrawable
untuk menetapkan latar belakang
tampilan dengan meneruskannya ke metode setBackgroundDrawable()
tampilan. Anda juga dapat menggambar bentuk sebagai
tampilan kustomnya sendiri dan menambahkannya ke tata letak di aplikasi Anda.
Karena ShapeDrawable
memiliki metode draw()
sendiri, Anda dapat membuat
subclass View
yang menggambar objek ShapeDrawable
selama peristiwa onDraw()
, seperti yang 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. Misalnya, Anda dapat
menambahkannya secara terprogram ke aktivitas di aplikasi, seperti yang ditunjukkan dalam contoh
berikut:
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, class
CustomDrawableView
harus mengganti konstruktor View(Context, AttributeSet)
yang akan dipanggil saat class
di-inflate dari XML. Contoh berikut menunjukkan cara mendeklarasikan
CustomDrawableView
dalam tata letak XML:
<com.example.shapedrawable.CustomDrawableView android:layout_width="fill_parent" android:layout_height="wrap_content" />
Class ShapeDrawable
, seperti banyak
jenis drawable lainnya dalam paket android.graphics.drawable
, memungkinkan Anda untuk
menentukan berbagai properti objek dengan menggunakan metode publik. Beberapa contoh
properti yang mungkin ingin Anda sesuaikan meliputi transparansi alfa, filter warna,
dither, opasitas, dan warna.
Anda juga dapat menentukan bentuk-bentuk drawable dasar menggunakan resource XML. Untuk mengetahui informasi selengkapnya, lihat Drawable bentuk dalam Jenis resource drawable.
Drawable NinePatch
Grafis NinePatchDrawable
adalah
gambar bitmap yang dapat direntangkan yang dapat Anda gunakan sebagai latar belakang tampilan. Android
akan otomatis mengubah ukuran grafis untuk mengakomodasi konten tampilan. Contoh
penggunaan gambar NinePatch adalah latar belakang yang digunakan oleh tombol
Android standar—tombol harus direntangkan untuk mengakomodasi string dengan panjang yang bervariasi. Grafis
NinePatch adalah gambar PNG standar yang menyertakan batas tambahan 1 piksel.
Ekstensi tersebut harus disimpan dengan ekstensi 9.png
di direktori res/drawable/
project Anda.
Gunakan garis batas ini untuk menentukan area stretchable dan area statis gambar. Anda menunjukkan bagian yang dapat direntangkan dengan menggambar satu (atau beberapa) garis hitam selebar 1 piksel di bagian kiri dan atas batas (piksel batas lainnya harus sepenuhnya transparan atau putih). Anda dapat memiliki sebanyak mungkin bagian yang dapat direntangkan sesuai keinginan. Ukuran relatif bagian yang dapat direntangkan tetap sama, sehingga bagian terbesar akan selalu menjadi yang terbesar.
Anda juga dapat menentukan bagian drawable opsional gambar (secara efektif,
garis padding) dengan menggambar garis di sebelah kanan dan garis di bawah. Jika
objek View
menetapkan grafis NinePatch sebagai latar belakangnya,
lalu menentukan teks tampilan, objek tersebut akan membentang sendiri sehingga semua teks
hanya menempati area yang ditetapkan oleh baris 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 boleh direplikasi untuk merentangkan gambar. Garis bawah dan garis kanan menentukan area relatif dalam gambar yang boleh ditempati oleh isi tampilan.
Gambar 1 menunjukkan contoh grafis NinePatch yang digunakan untuk menentukan sebuah tombol:

Gambar 1: Contoh grafis NinePatch yang menentukan tombol
Grafis NinePatch ini menentukan satu area yang dapat direntangkan dengan garis kiri dan atas, serta area drawable dengan garis bawah dan kanan. Pada gambar atas, garis abu-abu putus-putus mengidentifikasi area gambar yang direplikasi untuk merentangkan gambar. Persegi panjang merah muda pada gambar bawah menunjukkan wilayah tempat isi tampilan diperbolehkan. Jika isinya tidak pas di wilayah ini, gambar akan direntangkan agar pas.
Alat Draw 9-patch menawarkan cara yang sangat berguna untuk membuat gambar NinePatch, menggunakan editor grafis WYSIWYG. Fitur ini bahkan memunculkan peringatan jika wilayah yang telah Anda tentukan untuk area yang dapat direntangkan berisiko menghasilkan artefak gambar sebagai akibat dari replikasi piksel.
Contoh XML tata letak berikut menunjukkan cara menambahkan grafis NinePatch
ke 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 atribut layout_width
dan layout_height
disetel ke wrap_content
agar tombol pas di sekitar
teks.
Gambar 2 menunjukkan dua tombol yang dirender dari gambar XML dan NinePatch yang ditampilkan di atas. Perhatikan bagaimana lebar dan tinggi tombol bervariasi sesuai teks, dan gambar latar direntangkan untuk mengakomodasinya.

Gambar 2: Tombol yang dirender menggunakan resource 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 yang paling penting untuk diimplementasikan adalah draw(Canvas)
karena metode ini menyediakan objek Canvas
yang harus Anda gunakan untuk memberikan
petunjuk menggambar.
Kode berikut menunjukkan 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 ke mana pun yang diinginkan, misalnya ke
ImageView
seperti yang ditampilkan 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 dapat menentukan instance drawable kustom dengan XML melalui cara berikut:
- Menggunakan nama class yang sepenuhnya memenuhi syarat sebagai nama elemen XML. Untuk pendekatan ini, class drawable kustom harus berupa class level teratas publik:
<com.myapp.MyDrawable xmlns:android="http://schemas.android.com/apk/res/android" android:color="#ffff0000" />
- Menggunakan
drawable
sebagai nama tag XML dan menentukan nama class yang sepenuhnya memenuhi syarat dari atribut class. Pendekatan ini dapat digunakan untuk class publik level atas dan class dalam statis publik:<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 baru, Anda dapat menambahkan tint ke bitmap dan nine-patch yang ditentukan sebagai
mask alfa. Anda dapat menambahkan tint dengan resource warna atau atribut tema yang ditetapkan ke resource
warna (misalnya, ?android:attr/colorPrimary
). Biasanya, Anda membuat aset ini
hanya sekali dan mewarnainya secara otomatis agar sesuai dengan tema.
Anda dapat menerapkan tint ke objek BitmapDrawable
, NinePatchDrawable
, atau VectorDrawable
dengan metode setTint()
. Anda juga
dapat menetapkan warna dan mode tint dalam tata letak dengan atribut android:tint
dan
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 mengetahui informasi selengkapnya, baca Memilih warna dengan
Palette API.