Görünümlerdeki Düzenler

Oluşturma yöntemini deneyin
Jetpack Compose, Android için önerilen kullanıcı arayüzü araç setidir. Compose'da düzenlerle nasıl çalışacağınızı öğrenin.

Düzen, uygulamanızdaki bir kullanıcı arayüzünün yapısını (ör. bir etkinlikteki) tanımlar. Düzendeki tüm öğeler, View ve ViewGroup nesnelerinin hiyerarşisi kullanılarak oluşturulur. View, genellikle kullanıcının görebileceği ve etkileşime girebileceği bir şey çizer. ViewGroup, şekil 1'de gösterildiği gibi View ve diğer ViewGroup nesneleri için düzen yapısını tanımlayan görünmez bir kapsayıcıdır.

Şekil 1. Bir kullanıcı arayüzü düzenini tanımlayan görünüm hiyerarşisi çizimi.

View nesneleri genellikle widgetlar olarak adlandırılır ve Button veya TextView gibi birçok alt sınıftan biri olabilir. ViewGroup nesneleri genellikle düzen olarak adlandırılır ve LinearLayout veya ConstraintLayout gibi farklı bir düzen yapısı sağlayan birçok türden biri olabilir.

Bir düzeni iki şekilde bildirebilirsiniz:

  • Kullanıcı arayüzü öğelerini XML'de belirtin. Android, widget'lar ve düzenler için olduğu gibi View sınıflarına ve alt sınıflarına karşılık gelen basit bir XML sözlüğü sağlar. Ayrıca, sürükle ve bırak özellikli bir arayüz kullanarak XML düzeninizi oluşturmak için Android Studio'nun Düzen Düzenleyici'sini de kullanabilirsiniz.

  • Düzen öğelerini çalışma zamanında örneklendirmek. Uygulamanız, View ve ViewGroup nesneleri oluşturup özelliklerini programatik olarak değiştirebilir.

Kullanıcı arayüzünüzü XML'de tanımlamak, uygulamanızın sunumunu, davranışını kontrol eden koddan ayırmanıza olanak tanır. XML dosyaları kullanmak, farklı ekran boyutları ve yönleri için farklı düzenler sağlamayı da kolaylaştırır. Bu konu, Farklı ekran boyutlarını destekleme bölümünde daha ayrıntılı olarak açıklanmıştır.

Android çerçevesi, uygulamanızın kullanıcı arayüzünü oluşturmak için bu yöntemlerden birini veya ikisini birden kullanma esnekliği sağlar. Örneğin, uygulamanızın varsayılan düzenlerini XML'de belirtip çalışma zamanında düzeni değiştirebilirsiniz.

XML'i yazın

Android'in XML sözlüğünü kullanarak, kullanıcı arayüzü düzenlerini ve içerdikleri ekran öğelerini, iç içe yerleştirilmiş bir dizi öğe içeren HTML biçiminde web sayfaları oluşturduğunuz gibi hızlı bir şekilde tasarlayabilirsiniz.

Her düzen dosyası, View veya ViewGroup nesnesi olması gereken tam olarak bir kök öğe içermelidir. Kök öğeyi tanımladıktan sonra, düzeninizi tanımlayan bir View hiyerarşisini kademeli olarak oluşturmak için alt öğe olarak ek düzen nesneleri veya widget'lar ekleyebilirsiniz. Örneğin, TextView ve Button öğelerini tutmak için dikey LinearLayout kullanan bir XML düzenini aşağıda görebilirsiniz:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical" >
    <TextView android:id="@+id/text"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:text="Hello, I am a TextView" />
    <Button android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello, I am a Button" />
</LinearLayout>

Düzeninizi XML'de tanımladıktan sonra, düzgün şekilde derlenebilmesi için dosyayı Android projenizin res/layout/ dizinine .xml uzantısıyla kaydedin.

Düzen XML dosyasının söz dizimi hakkında daha fazla bilgi edinmek için Düzen kaynağı bölümüne bakın.

XML kaynağını yükleme

Uygulamanızı derlediğinizde, her XML düzen dosyası bir View kaynağında derlenir. Uygulamanızın geri çağırma uygulamasındaki düzen kaynağını yükleyin.Activity.onCreate() Bunu yapmak için setContentView() yöntemini çağırın ve bunu, şu biçimdeki düzen kaynağınıza referans olarak iletin: R.layout.layout_file_name. Örneğin, XML düzeniniz main_layout.xml olarak kaydedilmişse Activity düzeniniz için aşağıdaki gibi yükleyin:

Kotlin

fun onCreate(savedInstanceState: Bundle) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.main_layout)
}

Java

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_layout);
}

Activity başlatıldığında Android çerçevesi, Activity içindeki onCreate() geri çağırma yöntemini çağırır. Etkinlik yaşam döngüleri hakkında daha fazla bilgi için Etkinliklere giriş konusuna bakın.

Özellikler

Her View ve ViewGroup nesnesi, kendi çeşitlerini destekler. Bazı özellikler bir View nesnesine özgüdür. Örneğin TextView, textSize özelliğini destekler. Bununla birlikte, bu özellikler bu sınıfı genişleten View nesneleri tarafından da devralınır. Kök View sınıfından (id özelliği gibi) devralındıklarından bazıları tüm View nesneleri için ortaktır. Diğer özellikler, düzen parametreleri olarak kabul edilir. Bunlar, nesnenin üst ViewGroup nesnesi tarafından tanımlanan View nesnesinin belirli düzen yönlerini tanımlayan özelliklerdir.

ID

Herhangi bir View nesnesi, ağaç içinde View öğesini benzersiz bir şekilde tanımlamak için kendisiyle ilişkilendirilmiş bir tam sayı kimliğine sahip olabilir. Uygulama derlendiğinde bu kimliğe tam sayı olarak başvurulur. Ancak kimlik, genellikle düzen XML dosyasında id özelliğinde bir dize olarak atanır. Bu, tüm View nesnelerinde ortak bir XML özelliğidir ve View sınıfıyla tanımlanır. Bunu çok sık kullanıyorsunuz. XML etiketi içindeki bir kimliğin söz dizimi aşağıdaki gibidir:

android:id="@+id/my_button"

Dizenin başındaki at simgesi (@), XML ayrıştırıcının kimlik dizesinin geri kalanını ayrıştırıp genişlettiğini ve bunu bir kimlik kaynağı olarak tanımladığını belirtir. Artı simgesi (+), oluşturulması ve R.java dosyasındaki kaynaklarınıza eklenmesi gereken yeni bir kaynak adı olduğu anlamına gelir.

Android çerçevesi başka birçok kimlik kaynağı sunar. Bir Android kaynak kimliğine başvururken artı simgesine ihtiyacınız yoktur ancak android paket ad alanını aşağıdaki gibi eklemeniz gerekir:

android:id="@android:id/empty"

android paket ad alanı, yerel kaynaklar sınıfı yerine android.R kaynak sınıfındaki bir kimliğe başvuruda bulunduğunuzu gösterir.

Uygulamanızda görünüm oluşturmak ve bu görünümlere referans vermek için aşağıdaki genel bir kalıp kullanabilirsiniz:

  1. Düzen dosyasında bir görünüm tanımlayın ve buna aşağıdaki örnekte olduğu gibi benzersiz bir kimlik atayın:
    <Button android:id="@+id/my_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/my_button_text"/>
    
  2. Görünüm nesnesinin bir örneğini oluşturun ve bunu aşağıdaki örnekte gösterildiği gibi düzenden (genellikle onCreate() yöntemiyle) yakalayın:

    Kotlin

    val myButton: Button = findViewById(R.id.my_button)
    

    Java

    Button myButton = (Button) findViewById(R.id.my_button);
    

Görünüm nesneleri için kimlik tanımlamak, RelativeLayout oluştururken önemlidir. Göreli düzende, eşdüzey görünümler, benzersiz kimlik tarafından başvurulan başka bir eşdüzey görünüme göre kendi düzenlerini tanımlayabilir.

Bir kimliğin, ağacın tamamında benzersiz olması gerekmez ancak aradığınız ağacın parçası içinde benzersiz olması gerekir. Genellikle ağacın bütününü kapsayabilir bu yüzden mümkün olduğunca onu benzersiz kılmak en iyisidir.

Düzen parametreleri

layout_something adlı XML düzen özellikleri, View için, bulunduğu ViewGroup için uygun olan düzen parametrelerini tanımlar.

Her ViewGroup sınıfı, ViewGroup.LayoutParams kapsamını genişleten iç içe yerleştirilmiş bir sınıf uygular. Bu alt sınıf, her alt görünümün boyutunu ve konumunu görünüm grubuna uygun şekilde tanımlayan mülk türlerini içerir. Şekil 2'de gösterildiği gibi üst görünüm grubu, alt görünüm grubu dahil olmak üzere her alt görünüm için düzen parametrelerini tanımlar.

Şekil 2. Her görünümle ilişkilendirilmiş düzen parametreleriyle bir görünüm hiyerarşisini görselleştirme.

Her LayoutParams alt sınıfının, değerleri ayarlamak için kendi söz dizimi vardır. Her alt öğe, üst öğesi için uygun bir LayoutParams tanımlamalıdır ancak kendi alt öğeleri için farklı bir LayoutParams tanımlayabilir.

Tüm görünüm grupları, layout_width ve layout_height kullanılarak bir genişlik ve yükseklik içerir ve bunları tanımlamak için her görünüm gereklidir. Birçok LayoutParams, isteğe bağlı kenar boşlukları ve kenarlıklar içerir.

Tam ölçümlerle genişlik ve yüksekliği belirtebilirsiniz, ancak bunu sık sık yapmak istemeyebilirsiniz. Çoğunlukla, genişliği veya yüksekliği ayarlamak için şu sabit değerlerden birini kullanırsınız:

  • wrap_content: Görünümünüzü, içeriğinin gerektirdiği boyutlara göre boyutlandırmasını sağlar.
  • match_parent: Görünümünüzün, üst görüntüleme grubunun izin verdiği ölçüde büyük olmasını sağlar.

Genel olarak, piksel gibi mutlak birimler kullanarak bir düzen genişliği ve yüksekliğinin belirtilmesi önerilmez. Uygulamanızın çeşitli cihaz ekran boyutlarında düzgün bir şekilde görüntülenmesine yardımcı olduğundan, yoğunluktan bağımsız piksel birimleri (dp), wrap_content veya match_parent gibi göreli ölçümler kullanmak daha iyi bir yaklaşımdır. Kabul edilen ölçüm türleri Düzen kaynağı'nda tanımlanmıştır.

Düzen konumu

Bir görünüm dikdörtgen bir geometriye sahiptir. Bir çift sol ve üst koordinat olarak ifade edilen bir konuma ve genişlik ve yükseklik olarak ifade edilen iki boyuta sahiptir. Konum ve boyutların birimi pikseldir.

getLeft() ve getTop() yöntemlerini çağırarak bir görünümün konumunu alabilirsiniz. İlk değer, görünümü temsil eden dikdörtgenin sol (x) koordinatını döndürür. İkinci değer, görünümü temsil eden dikdörtgenin üst (y) koordinatını döndürür. Bu yöntemler, görünümün konumunu üst öğeye göre döndürür. Örneğin, getLeft() değeri 20 değerini verdiğinde bu, görünümün doğrudan üst öğesinin sol kenarının 20 piksel sağında bulunduğu anlamına gelir.

Buna ek olarak, gereksiz hesaplamalardan kaçınmak için kolaylık yöntemleri de vardır: getRight() ve getBottom(). Bu yöntemler, görünümü temsil eden dikdörtgenin sağ ve alt kenarlarının koordinatlarını döndürür. Örneğin, getRight() çağrısı şu hesaplamaya benzer: getLeft() + getWidth().

Boyut, dolgu ve kenar boşlukları

Bir görünümün boyutu, genişlik ve yükseklikle ifade edilir. Bir görünümün iki çift genişlik ve yükseklik değeri vardır.

İlk çift, ölçülen genişlik ve ölçülen yükseklik olarak bilinir. Bu boyutlar, bir görünümün üst öğesi içinde ne kadar büyük olmak istediğini tanımlar. getMeasuredWidth() ve getMeasuredHeight() çağrılarını yaparak ölçülen boyutları elde edebilirsiniz.

İkinci çift, width ve height veya bazen çizim genişliği ve çizim yüksekliği olarak bilinir. Bu boyutlar, ekrandaki görünümün, çizim zamanında ve düzenden sonraki gerçek boyutunu tanımlar. Bu değerler, ölçülen genişlik ve yükseklikten farklı olabilir, ancak zorunlu değildir. Genişliği ve yüksekliği, getWidth() ve getHeight() özelliklerini çağırarak elde edebilirsiniz.

Bir görünüm, boyutlarını ölçmek için dolgusunu dikkate alır. Dolgu, görünümün sol, üst, sağ ve alt bölümleri için piksel cinsinden ifade edilir. Görünüm içeriğini belirli sayıda piksele göre kaydırmak için dolguyu kullanabilirsiniz. Örneğin, ikilik sol dolgu, görünümün içeriğini sol kenarın sağına iki piksel iter. Dolguyu setPadding(int, int, int, int) yöntemini kullanarak ayarlayabilir ve getPaddingLeft(), getPaddingTop(), getPaddingRight() ve getPaddingBottom() yöntemlerini çağırarak sorgulayabilirsiniz.

Görünüm bir dolgu tanımlayabilir ancak kenar boşluklarını desteklemez. Ancak görünüm grupları kenar boşluklarını destekler. Daha fazla bilgi için ViewGroup ve ViewGroup.MarginLayoutParams sayfalarını inceleyin.

Boyutlar hakkında daha fazla bilgi için Boyut konusuna bakın.

Kenar boşluklarını ve dolguyu programatik olarak ayarlamanın yanı sıra bunları aşağıdaki örnekte gösterildiği gibi XML düzenlerinizde de ayarlayabilirsiniz:

  <?xml version="1.0" encoding="utf-8"?>
  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical" >
      <TextView android:id="@+id/text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="16dp"
                android:padding="8dp"
                android:text="Hello, I am a TextView" />
      <Button android:id="@+id/button"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_marginTop="16dp"
              android:paddingBottom="4dp"
              android:paddingEnd="8dp"
              android:paddingStart="8dp"
              android:paddingTop="4dp"
              android:text="Hello, I am a Button" />
  </LinearLayout>
  

Yukarıdaki örnekte uygulanan kenar boşluğu ve dolgu gösterilmektedir. TextView öğesinin her yerine eşit kenar boşlukları ve dolgu uygulandı. Button ise bunları farklı kenarlara bağımsız olarak nasıl uygulayabileceğinizi gösterir.

Sık kullanılan düzenler

ViewGroup sınıfının her bir alt sınıfı, içine yerleştirdiğiniz görünümleri benzersiz bir şekilde gösterebilir. ConstraintLayout, en esnek ve düzen hiyerarşinizin sığ kalmasını sağlamak için en iyi araçları sağlayan en esnek düzen türüdür.

Aşağıda, Android platformunda yerleşik olarak bulunan yaygın düzen türlerinden bazıları verilmiştir.

Doğrusal düzen oluşturma

Alt öğelerini tek bir yatay veya dikey satırda düzenler ve pencere uzunluğu ekranın uzunluğunu aşıyorsa kaydırma çubuğu oluşturur.

Web Görünümü'nde web uygulamaları oluşturma

Web sayfalarını görüntüler.

Dinamik listeler oluşturma

Düzeninizin içeriği dinamikse veya önceden belirlenmiş değilse RecyclerView veya AdapterView alt sınıfını kullanabilirsiniz. RecyclerView, belleği AdapterView uygulamasından daha verimli kullandığı için genellikle daha iyi bir seçenektir.

RecyclerView ve AdapterView ile yaygın olarak kullanılan düzenler şunlardır:

Liste

Tek sütunluk kayan bir liste görüntüler.

Izgara

Sütun ve satırlardan oluşan bir kayan ızgara görüntüler.

RecyclerView daha fazla imkan ve özel düzen yöneticisi oluşturma seçeneği sunar.

Bağdaştırıcı görünümünü verilerle doldurma

AdapterView ListView veya GridView gibi AdapterView örneğini, harici bir kaynaktan veri alan ve her bir veri girişini temsil eden View oluşturan bir Adapter'ye bağlayarak doldurabilirsiniz.

Android, bir AdapterView için farklı veri türlerini almak ve görünüm oluşturmak amacıyla faydalı olan birkaç Adapter alt sınıfı sağlar. En yaygın iki adaptör şunlardır:

ArrayAdapter
Veri kaynağınız bir diziyse bu bağdaştırıcıyı kullanın. Varsayılan olarak ArrayAdapter, her öğede toString() çağrısı yaparak ve içeriği TextView içine yerleştirerek her dizi öğesi için bir görünüm oluşturur.

Örneğin, ListView içinde görüntülemek istediğiniz bir dize diziniz varsa her dizenin ve dize dizisinin düzenini belirtmek için bir oluşturucu kullanarak yeni bir ArrayAdapter başlatın:

Kotlin

    val adapter = ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, myStringArray)
    

Java

    ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
            android.R.layout.simple_list_item_1, myStringArray);
    

Bu oluşturucunun bağımsız değişkenleri şunlardır:

  • Uygulamanız Context
  • Dizideki her dize için bir TextView içeren düzen
  • Dize dizisi

Ardından ListView cihazınızda setAdapter() numaralı telefonu arayın:

Kotlin

    val listView: ListView = findViewById(R.id.listview)
    listView.adapter = adapter
    

Java

    ListView listView = (ListView) findViewById(R.id.listview);
    listView.setAdapter(adapter);
    

Her bir öğenin görünümünü özelleştirmek amacıyla dizinizdeki nesneler için toString() yöntemini geçersiz kılabilirsiniz. TextView dışında bir öğe olan her öğe için bir görünüm oluşturmak istiyorsanız (örneğin, her dizi öğesi için ImageView istiyorsanız) ArrayAdapter sınıfını genişletin ve getView() değerini geçersiz kılarak her öğe için istediğiniz görünüm türünü döndürün.

SimpleCursorAdapter
Verileriniz bir Cursor cihazından geldiğinde bu adaptörü kullanın. SimpleCursorAdapter kullanırken Cursor içindeki her bir satır için kullanılacak bir düzen ve istediğiniz düzen görünümlerine eklenmesini istediğiniz Cursor sütunları belirleyin. Örneğin, kişilerin adları ve telefon numaralarından oluşan bir liste oluşturmak istiyorsanız her kişi için bir satır ve adlar ile numaralar için sütun içeren bir Cursor döndüren bir sorgu gerçekleştirebilirsiniz. Daha sonra, her bir sonucun düzeninde Cursor sütunundan hangi sütunların bulunmasını istediğinizi belirten bir dize dizisi ve her sütunun yerleştirilmesi gereken görünümleri belirten bir tam sayı dizisi oluşturursunuz:

Kotlin

    val fromColumns = arrayOf(ContactsContract.Data.DISPLAY_NAME,
                              ContactsContract.CommonDataKinds.Phone.NUMBER)
    val toViews = intArrayOf(R.id.display_name, R.id.phone_number)
    

Java

    String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME,
                            ContactsContract.CommonDataKinds.Phone.NUMBER};
    int[] toViews = {R.id.display_name, R.id.phone_number};
    

SimpleCursorAdapter örneğini örneklediğinizde her bir sonuç için kullanılacak düzeni, sonuçları içeren Cursor ve şu iki diziyi iletin:

Kotlin

    val adapter = SimpleCursorAdapter(this,
            R.layout.person_name_and_number, cursor, fromColumns, toViews, 0)
    val listView = getListView()
    listView.adapter = adapter
    

Java

    SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
            R.layout.person_name_and_number, cursor, fromColumns, toViews, 0);
    ListView listView = getListView();
    listView.setAdapter(adapter);
    

Daha sonra SimpleCursorAdapter, her bir fromColumns öğesini karşılık gelen toViews görünümüne ekleyerek Cursor içindeki her satır için sağlanan düzeni kullanarak bir görünüm oluşturur.

Uygulamanızın kullanım süresi içinde bağdaştırıcınız tarafından okunan temel verileri değiştirirseniz notifyDataSetChanged() numaralı telefonu arayın. Bu işlem, ekteki görünüme verilerin değiştirildiğini bildirir ve kendisini yeniler.

Tıklama etkinliklerini işleme

AdapterView.OnItemClickListener arayüzünü uygulayarak AdapterView içindeki her öğedeki tıklama etkinliklerine yanıt verebilirsiniz. Örneğin:

Kotlin

listView.onItemClickListener = AdapterView.OnItemClickListener { parent, view, position, id ->
    // Do something in response to the click.
}

Java

// Create a message handling object as an anonymous class.
private OnItemClickListener messageClickedHandler = new OnItemClickListener() {
    public void onItemClick(AdapterView parent, View v, int position, long id) {
        // Do something in response to the click.
    }
};

listView.setOnItemClickListener(messageClickedHandler);

Ek kaynaklar

GitHub'daki Sunflower demo uygulamasında düzenlerin nasıl kullanıldığını görün.