Uygulamanızda statik resimler göstermeniz gerektiğinde, şekil ve resim çizmek için Drawable
sınıfını ve alt sınıflarını kullanabilirsiniz. Drawable
, çizilebilecek bir şey için genel bir soyutlamadır. Çeşitli alt sınıflar, belirli görüntü senaryolarına yardımcı olur. Bunları, benzersiz şekillerde davranan kendi çekilebilir nesnelerinizi tanımlamak için genişletebilirsiniz.
Sınıf kurucularını kullanmanın yanı sıra bir Drawable
öğesini tanımlamanın ve somutlaştırmanın iki yolu vardır:
- Projenizde kayıtlı bir görüntü kaynağını (bit eşlem dosyası) şişirir.
- Çekilebilir özellikleri tanımlayan bir XML kaynağını şişirin.
Not: Bunun yerine, bir dizi nokta, çizgi ve eğriden oluşan bir resmi ve ilişkili renk bilgilerini tanımlayan bir vektör çekilebilir özelliğini kullanmayı tercih edebilirsiniz. Bu, vektör çekilebilirlerinin kaliteden ödün vermeden farklı boyutlar için ölçeklendirilmesine olanak tanır. Daha fazla bilgi için Vektör çizimlerine genel bakış bölümünü inceleyin.
Kaynak resimlerden çekilebilir metinler oluşturma
Proje kaynaklarınızdaki bir görüntü dosyasına referans vererek uygulamanıza grafik ekleyebilirsiniz. Desteklenen dosya türleri PNG (tercih edilir), JPG (kabul edilebilir) ve GIF'tir (önerilmez). Uygulama simgeleri, logolar ve oyunlarda kullanılanlar gibi diğer grafikler bu tekniğe uygundur.
Bir resim kaynağı kullanmak için dosyanızı, projenizin res/drawable/
dizinine ekleyin. Projenize girdikten sonra, kodunuzdan veya XML düzeninizden görüntü kaynağına başvurabilirsiniz. Her iki yöntemde de, dosya türü uzantısı olmayan dosya adı olan bir kaynak kimliği kullanılır. Örneğin, my_image.png
öğesine my_image
olarak bakın.
Not: res/drawable/
dizinine yerleştirilen resim kaynakları, derleme işlemi sırasında aapt
aracı tarafından kayıpsız resim sıkıştırma kullanılarak otomatik olarak optimize edilebilir. Örneğin, 256'dan fazla renk gerektirmeyen gerçek renkli bir PNG, renk paleti içeren 8 bit bir PNG'ye dönüştürülebilir. Böylece, eşit kalitede ancak daha az bellek gerektiren
bir resim elde edilir. Sonuç olarak, bu dizine yerleştirilen görüntü ikili programları derleme zamanında değişebilir. Bir görüntüyü bit eşlem olarak dönüştürmek için bit akışı olarak okumayı planlıyorsanız, resimlerinizi aapt
aracının değiştirmeyeceği res/raw/
klasörüne yerleştirin.
Aşağıdaki kod snippet'i, çekilebilir bir kaynaktan oluşturulmuş bir görüntüyü kullanan ve bunu düzene ekleyen bir ImageView
öğesinin nasıl oluşturulacağını gösterir:
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); }
Diğer durumlarda, resim kaynağınızı aşağıdaki örnekte gösterildiği gibi bir Drawable
nesnesi olarak kullanmak isteyebilirsiniz:
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);
Uyarı: Projenizdeki her benzersiz kaynak, kaç farklı nesne başlatırsanız sunun yalnızca bir durumu koruyabilir. Örneğin, aynı resim kaynağından iki Drawable
nesnesini örneklendirir ve bir nesnenin özelliğini (alfa gibi) değiştirirseniz diğerini de etkiler. Bir görüntü kaynağının birden çok örneğiyle çalışırken, Drawable
nesnesini doğrudan dönüştürmek yerine bir ara animasyon uygulamanız gerekir.
Aşağıdaki XML snippet'i, XML düzeninde bir ImageView
öğesine çekilebilir kaynağın nasıl ekleneceğini gösterir:
<ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/my_image" android:contentDescription="@string/my_image_desc" />
Proje kaynaklarını kullanma hakkında daha fazla bilgi için Kaynaklar ve öğeler başlıklı makaleye bakın.
Not: Çekilebilir malzemelerinizin kaynağı olarak resim kaynaklarını kullanırken resimlerin çeşitli piksel yoğunlukları için uygun boyutta olduğundan emin olun. Resimler doğru değilse sığacak şekilde ölçeklendirilirler. Bu da, çekilebilirlerinizde öğelere neden olabilir. Daha fazla bilgi için Farklı piksel yoğunluklarını destekleme bölümünü okuyun.
XML kaynaklarından çekilebilir öğeler oluşturma
Başlangıçta kodunuz veya kullanıcı etkileşiminiz tarafından tanımlanan değişkenlere bağlı olmayan bir Drawable
nesnesi oluşturmak istiyorsanız XML'de Drawable
öğesini tanımlamak iyi bir seçenektir. Kullanıcının uygulamanızla etkileşimi sırasında Drawable
ürününüzün özelliklerini değiştirmesini bekleseniz bile, nesne örneklendikten sonra özelliklerini değiştirebileceğiniz için nesneyi XML biçiminde tanımlamayı düşünmelisiniz.
Drawable
öğenizi XML'de tanımladıktan sonra, dosyayı projenizin res/drawable/
dizinine kaydedin. Aşağıdaki örnekte, Drawable
kaynağından devralan bir TransitionDrawable
kaynağını tanımlayan XML gösterilmektedir:
<!-- 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>
Ardından, Resources#getDrawable()
yöntemini çağırıp XML dosyanızın kaynak kimliğini ileterek nesneyi alın ve örneklendirin. inflate()
yöntemini destekleyen tüm Drawable
alt sınıfları XML olarak tanımlanabilir ve uygulamanız tarafından örneklenebilir.
XML şişirmeyi destekleyen her çekilebilir sınıf, nesne özelliklerini tanımlamaya yardımcı olan belirli XML özelliklerini kullanır. Aşağıdaki kod TransitionDrawable
öğesini somutlaştırır ve bir ImageView
nesnesinin içeriği olarak ayarlar:
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.
Desteklenen XML özellikleri hakkında daha fazla bilgi için yukarıda listelenen sınıflara bakın.
Çekilebilir şekiller
İki boyutlu bir grafiği dinamik olarak çizmek istediğinizde ShapeDrawable
nesnesi iyi bir seçenek olabilir. Programatik olarak bir ShapeDrawable
nesnesi üzerinde temel şekiller çizebilir ve uygulamanızın ihtiyaç duyduğu stilleri uygulayabilirsiniz.
ShapeDrawable
, Drawable
sınıfının bir alt sınıfıdır. Bu nedenle, Drawable
olması beklenen her yerde ShapeDrawable
kullanabilirsiniz. Örneğin, bir ShapeDrawable
nesnesini görünümün setBackgroundDrawable()
yöntemine geçirerek bir görünümün arka planını ayarlamak için kullanabilirsiniz. Şeklinizi kendi özel görünümü
olarak çizebilir ve uygulamanızdaki bir düzene ekleyebilirsiniz.
ShapeDrawable
kendi draw()
yöntemine sahip olduğundan aşağıdaki kod örneğinde gösterildiği gibi onDraw()
etkinliği sırasında ShapeDrawable
nesnesini çizen bir View
alt sınıfı oluşturabilirsiniz:
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); } }
Yukarıdaki kod örneğinde, diğer tüm özel görünümlerde olduğu gibi CustomDrawableView
sınıfını kullanabilirsiniz. Örneğin, bunu aşağıdaki örnekte gösterildiği gibi uygulamanızdaki bir etkinliğe programatik olarak ekleyebilirsiniz:
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); }
Bunun yerine XML düzeninde özel görünümü kullanmak isterseniz CustomDrawableView
sınıfı, sınıf XML'den şişirildiğinde çağrılan View(Context, AttributeSet)
oluşturucuyu geçersiz kılmalıdır. Aşağıdaki örnekte, XML düzeninde CustomDrawableView
öğesinin nasıl belirtileceği gösterilmektedir:
<com.example.shapedrawable.CustomDrawableView android:layout_width="fill_parent" android:layout_height="wrap_content" />
ShapeDrawable
sınıfı, android.graphics.drawable
paketindeki diğer birçok çekilebilir tür gibi, herkese açık yöntemler kullanarak nesnenin çeşitli özelliklerini tanımlamanıza olanak tanır. Ayarlamak isteyebileceğiniz bazı örnek özellikler arasında alfa şeffaflığı, renk filtresi, parlaklık, opaklık ve renk yer alır.
XML kaynaklarını kullanarak temel çekilebilir şekilleri de tanımlayabilirsiniz. Daha fazla bilgi için Çekilebilir kaynak türleri bölümündeki Şekil çekilebilir bölümüne bakın.
NinePatch çekilebilir birimleri
NinePatchDrawable
grafiği, görünümün arka planı olarak kullanabileceğiniz uzatılabilir bir bit eşlem resmidir. Android,
görünümün içeriğine uyması için grafiği otomatik olarak yeniden boyutlandırır. NinePatch resminin kullanımına örnek olarak standart Android düğmeleri tarafından kullanılan arka plan verilebilir. Düğmelerin çeşitli uzunluklardaki dizelere uyum sağlamak için genişletilmesi gerekir.
NinePatch grafiği, ekstra 1 piksellik bir kenarlık içeren standart bir PNG resmidir.
9.png
uzantısıyla birlikte projenizin res/drawable/
dizinine kaydedilmelidir.
Resmin uzatılabilir ve statik alanlarını tanımlamak için kenarlığı kullanın. Kenarlığın sol ve üst kısmına 1 piksel genişliğinde bir (veya daha fazla) siyah çizgi çizerek uzatılabilir bir bölümü belirtirsiniz (diğer kenarlık pikselleri tamamen şeffaf veya beyaz olmalıdır). İstediğiniz kadar uzatılabilir bölümünüz olabilir. Uzatılabilir bölümlerin göreli boyutu aynı kalır, böylece en büyük bölüm her zaman en büyük olmaya devam eder.
Ayrıca, sağa ve alta bir çizgi çizerek resmin isteğe bağlı çekilebilir bir bölümünü (etkili bir şekilde dolgu çizgileri) tanımlayabilirsiniz. Bir View
nesnesi, NinePatch grafiğini arka plan olarak ayarlar ve daha sonra, görünümün metnini belirtirse metnin tamamı, yalnızca sağ ve alt çizgiler (varsa) tarafından belirtilen alanı dolduracak şekilde kendisini uzatır.
Dolgu çizgileri eklenmezse Android bu çekilebilir alanı tanımlamak için sol ve üst çizgileri kullanır.
Çizgiler arasındaki farkı netleştirmek amacıyla, sol ve üst çizgiler, resmi uzatmak için resmin hangi piksellerinin kopyalanmasına izin verileceğini tanımlar. Alt ve sağ çizgiler, resim içinde görünüm içeriğinin kapladığı göreli alanı tanımlar.
Şekil 1'de bir düğmeyi tanımlamak için kullanılan bir NinePatch grafiği örneği gösterilmektedir:
Bu NinePatch grafiği, sol ve üst çizgilerle uzatılabilir bir alanı, alt ve sağ çizgilerle çekilebilir alanı tanımlar. Üstteki resimde bulunan noktalı gri çizgiler, görüntünün esnetmek için kopyalanan bölgelerini tanımlar. Alttaki resimdeki pembe dikdörtgen, görünüm içeriğine izin verilen bölgeyi belirtir. İçerikler bu bölgeye sığmazsa resim genişletilerek bunların sığması sağlanır.
Draw 9-patch aracı, bir WYSIWYG grafik düzenleyici kullanarak NinePatch resimlerinizi oluşturmak için son derece kullanışlı bir yol sunar. Hatta, uzatılabilir alan için tanımladığınız bölge, piksel çoğaltma nedeniyle çizim yapıları oluşturma riskiyle karşı karşıyaysa uyarı verir.
Aşağıdaki örnek düzen XML'inde, birkaç düğmeye NinePatch grafiğinin nasıl ekleneceği gösterilmektedir. NinePatch resmi res/drawable/my_button_background.9.png
konumuna kaydedilir.
<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"/>
Düğmenin metnin etrafına düzgün bir şekilde sığması için layout_width
ve layout_height
özelliklerinin wrap_content
olarak ayarlandığını unutmayın.
Şekil 2'de yukarıda gösterilen XML ve NinePatch resminden oluşturulan iki düğme gösterilmektedir. Düğme genişliğinin ve yüksekliğinin metne göre nasıl değiştiğine ve arka plan resminin uygun şekilde genişlediğine dikkat edin.
Özel çekilebilir kaynaklar
Drawable
sınıfını (veya alt sınıflarından herhangi birini) genişleterek özel çizimler oluşturabilirsiniz.
Uygulanacak en önemli yöntem, çizim talimatlarınızı sağlamak için kullanmanız gereken Canvas
nesnesini sağladığından draw(Canvas)
yöntemidir.
Aşağıdaki kod, daire çizen basit bir Drawable
alt sınıfını göstermektedir:
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; } }
Daha sonra, çekilebilir dosyanızı burada gösterildiği gibi bir ImageView
öğesine istediğiniz yere ekleyebilirsiniz:
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));
Android 7.0 (API düzeyi 24) ve sonraki sürümlerde, XML ile özel çekilebilir dosyanızın örneklerini aşağıdaki yöntemlerle de tanımlayabilirsiniz:
- XML öğe adı olarak tam nitelikli sınıf adını kullanma. Bu yaklaşımda özel çekilebilir sınıf, herkese açık üst düzey bir sınıf olmalıdır:
<com.myapp.MyDrawable xmlns:android="http://schemas.android.com/apk/res/android" android:color="#ffff0000" />
- XML etiketi adı olarak
drawable
kullanma ve class özelliğinden tam nitelikli sınıf adını belirtme. Bu yaklaşım, hem herkese açık üst düzey sınıflar hem de herkese açık statik iç sınıflar için kullanılabilir:<drawable xmlns:android="http://schemas.android.com/apk/res/android" class="com.myapp.MyTopLevelClass$MyDrawable" android:color="#ffff0000" />
Çekilebilir öğelere ton ekleme
Android 5.0 (API düzeyi 21) ve sonraki sürümlerde, alfa maskeleri olarak tanımlanan bit eşlemleri ve dokuz yamayı renklendirebilirsiniz. Renk kaynaklarıyla uyumlu hale getiren renk kaynakları veya tema özellikleriyle
Tonlama uygulayabilirsiniz (örneğin, ?android:attr/colorPrimary
). Genellikle bu öğeleri yalnızca bir kez oluşturur ve temanızla eşleşecek şekilde otomatik olarak renklendirirsiniz.
setTint()
yöntemiyle BitmapDrawable
, NinePatchDrawable
veya VectorDrawable
nesnelerine tonlama uygulayabilirsiniz. Ayrıca, android:tint
ve android:tintMode
özelliklerini kullanarak düzenlerinizde tonlama rengini ve modunu da ayarlayabilirsiniz.
Görseldeki belirgin renkleri ayıklayın
Android Destek Kitaplığı, resimlerden belirgin renkleri çıkarabilmenizi sağlayan Palette
sınıfını içerir.
Çekilebilir öğelerinizi Bitmap
olarak yükleyip renklerine erişmesi için Palette
adlı iş ortağına iletebilirsiniz.
Daha fazla bilgi için Palet API'si ile renk seçme bölümünü okuyun.