Görünümlerdeki düzenler

Compose 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ı tanımlar (ör. bir etkinlikte). 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şimde bulunabileceği bir şey çizer. ViewGroup, Şekil 1'de gösterildiği gibi View ve diğer ViewGroup nesnelerinin düzen yapısını tanımlayan görünmez bir kapsayıcıdır.

Şekil 1. Kullanıcı arayüzü yerleşimini tanımlayan bir görünüm hiyerarşisinin resmi.

View nesneleri genellikle widget olarak adlandırılır ve Button veya TextView gibi birçok alt sınıfa ait olabilir. ViewGroup nesneleri genellikle düzenler olarak adlandırılır ve farklı düzen yapıları sağlayan birçok türden biri olabilir. Örneğin, LinearLayout veya ConstraintLayout.

Bir düzeni iki şekilde bildirebilirsiniz:

  • Kullanıcı arayüzü öğelerini XML'de bildirin. Android, View sınıflarına ve alt sınıflarına (ör. widget'lar ve düzenler için olanlar) karşılık gelen basit bir XML sözlüğü sağlar. Ayrıca, sürükle ve bırak arayüzünü kullanarak XML düzeninizi oluşturmak için Android Studio'nun Layout Editor'ını da kullanabilirsiniz.

  • Çalışma zamanında düzen öğelerini oluşturun. Uygulamanız View ve ViewGroup nesneleri oluşturabilir ve özelliklerini programatik olarak değiştirebilir.

Kullanıcı arayüzünüzü XML'de tanımlayarak uygulamanızın sunumunu, davranışını kontrol eden koddan ayırabilirsiniz. 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 ele alınmıştır.

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

XML'yi yazma

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

Her düzen dosyası tam olarak bir kök öğe içermelidir. Bu öğe, View veya ViewGroup nesnesi olmalıdır. Kök öğeyi tanımladıktan sonra, düzeninizi tanımlayan bir View hiyerarşisi oluşturmak için ek düzen nesneleri veya widget'ları alt öğeler olarak ekleyebilirsiniz. Örneğin, TextView ve Button öğelerini tutmak için dikey bir LinearLayout kullanan bir XML düzeni aşağıda verilmiştir:

<?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, dosyayı Android projenizin res/layout/ dizininde .xml uzantısıyla kaydedin. Böylece dosya düzgün şekilde derlenir.

Düzen XML dosyasının söz dizimi hakkında daha fazla bilgi için Düzen kaynağı konusuna bakın.

XML kaynağını yükleme

Uygulamanızı derlediğinizde her XML düzen dosyası bir View kaynağına derlenir. Düzen kaynağını uygulamanızın Activity.onCreate() geri çağırma uygulamasında yükleyin. Bunu yapmak için setContentView()'ı çağırın ve düzen kaynağınızın referansını şu biçimde iletin: R.layout.layout_file_name. Örneğin, XML düzeniniz main_layout.xml olarak kaydedilmişse Activity 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);
}

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

Özellikler

Her View ve ViewGroup nesnesi, kendi XML özelliklerini destekler. Bazı özellikler View nesnesine özgüdür. Örneğin, TextView, textSize özelliğini destekler. Ancak bu özellikler, bu sınıfı genişleten tüm View nesneler tarafından da devralınır. Bazı özellikler, kök View sınıfından devralındıkları için tüm View nesnelerde ortaktır (ör. id özelliği). Diğer özellikler, View nesnesinin üst ViewGroup nesnesi tarafından tanımlanan, View nesnesinin belirli düzen yönlerini açıklayan özellikler olan düzen parametreleri olarak kabul edilir.

Kimlik

Herhangi bir View nesnesi, ağaçtaki View nesnesini benzersiz şekilde tanımlamak için kendisiyle ilişkilendirilmiş bir tam sayı kimliğine sahip olabilir. Uygulama derlendiğinde bu kimliğe tam sayı olarak referans verilir ancak kimlik genellikle düzen XML dosyasında id özelliğinde dize olarak atanır. Bu, tüm View nesneleri için ortak olan bir XML özelliğidir ve View sınıfı tarafından tanımlanır. Çok sık kullanıyorsanız Bir XML etiketindeki kimlik için kullanılan söz dizimi şöyledir:

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 kimlik kaynağı olarak tanımladığını gösterir. Artı işareti (+), R.java dosyasında oluşturulup kaynaklarınıza eklenmesi gereken yeni bir kaynak adı olduğunu gösterir.

Android çerçevesi, birçok başka kimlik kaynağı sunar. Bir Android kaynak kimliğine referans verirken artı sembolüne 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 kaynak sınıfı yerine android.R kaynak sınıfındaki bir kimliğe referans verdiğinizi gösterir.

Görünümler oluşturmak ve uygulamanızdan bunlara referans vermek için aşağıdaki gibi ortak bir kalıp kullanabilirsiniz:

  1. Düzen dosyasında bir görünüm tanımlayın ve aşağıdaki örnekte olduğu gibi bu görünüme 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 düzenden yakalayın. Bu işlem genellikle aşağıdaki örnekte gösterildiği gibi onCreate() yönteminde yapılır:

    Kotlin

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

    Java

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

RelativeLayout oluştururken görünüm nesneleri için kimlik tanımlamak önemlidir. Göreceli düzende, kardeş görünümler düzenlerini benzersiz kimlikle referans verilen başka bir kardeş görünüme göre tanımlayabilir.

Kimliğin ağacın tamamında benzersiz olması gerekmez ancak arama yaptığınız ağaç bölümünde benzersiz olması gerekir. Bu genellikle ağacın tamamı olabilir. Bu nedenle, mümkün olduğunda benzersiz hale getirmeniz en iyisidir.

Düzen parametreleri

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

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

Şekil 2. Her görünümle ilişkili düzen parametrelerinin bulunduğu bir görünüm hiyerarşisinin görselleştirilmesi.

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. Bununla birlikte, kendi alt öğeleri için farklı bir LayoutParams da tanımlayabilir.

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

Genişlik ve yüksekliği tam ölçülerle belirtebilirsiniz ancak bunu sık sık yapmak istemeyebilirsiniz. Genellikle genişliği veya yüksekliği ayarlamak için aşağıdaki sabitlerden birini kullanırsınız:

  • wrap_content: Görünümünüze, içeriğinin gerektirdiği boyutlara göre kendini boyutlandırmasını söyler.
  • match_parent: Görünümünüzün, üst görünüm grubu tarafından izin verilen en büyük boyuta ulaşmasını sağlar.

Genel olarak, piksel gibi mutlak birimler kullanarak düzen genişliği ve yüksekliği belirtmenizi önermiyoruz. Uygulamanızın çeşitli cihaz ekran boyutlarında düzgün ş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çümleri kullanmak daha iyi bir yaklaşımdır. Kabul edilen ölçüm türleri düzen kaynağı'nda tanımlanır.

Düzen konumu

Görünümün dikdörtgen geometrisi vardır. Sol ve üst koordinat çifti olarak ifade edilen bir konumu ve genişlik ile yükseklik olarak ifade edilen iki boyutu vardır. Konum ve boyut birimi pikseldir.

getLeft() ve getTop() yöntemlerini çağırarak bir görünümün konumunu alabilirsiniz. İlk işlev, görünümü temsil eden dikdörtgenin sol (x) koordinatını döndürür. İkincisi, görünümü temsil eden dikdörtgenin üst (y) koordinatını döndürür. Bu yöntemler, görünümün üst öğesine göre konumunu döndürür. Örneğin, getLeft() 20 değerini döndürdüğünde görünümün, doğrudan üst öğesinin sol kenarının 20 piksel sağında olduğu anlaşılır.

Ayrıca, gereksiz hesaplamaları önlemek için kolaylık sağlayan yöntemler de vardır: örneğin 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() işlevini çağırmak aşağıdaki hesaplamaya benzer: getLeft() + getWidth().

Boyut, dolgu ve kenar boşlukları

Görünümün boyutu genişlik ve yükseklik ile ifade edilir. Bir görünümde iki çift genişlik ve yükseklik değeri bulunur.

İ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 olacağını tanımlar. Ölçülen boyutları getMeasuredWidth() ve getMeasuredHeight() işlevlerini çağırarak elde edebilirsiniz.

İkinci çift, genişlik ve yükseklik veya bazen çizim genişliği ve çizim yüksekliği olarak bilinir. Bu boyutlar, çizim sırasında ve düzenden sonra ekrandaki görünümün gerçek boyutunu tanımlar. Bu değerler, ölçülen genişlik ve yükseklikten farklı olabilir ancak farklı olması gerekmez. getWidth() ve getHeight() işlevlerini çağırarak genişlik ve yüksekliği elde edebilirsiniz.

Bir görünüm, boyutlarını ölçmek için dolgusunu dikkate alır. Doldurma, görünümün sol, üst, sağ ve alt kısımları için piksel cinsinden ifade edilir. Görünümün içeriğini belirli sayıda pikselle kaydırmak için dolgu kullanabilirsiniz. Örneğin, iki piksellik bir sol dolgu, görünümün içeriğini sol kenarın sağında iki piksel uzağa iter. setPadding(int, int, int, int) yöntemini kullanarak dolgu ayarlayabilir ve getPaddingLeft(), getPaddingTop(), getPaddingRight() ve getPaddingBottom() yöntemlerini çağırarak dolguyu sorgulayabilirsiniz.

Bir görünüm dolguyu tanımlayabilse de kenar boşluklarını desteklemez. Ancak, görüntüleme 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 başlıklı makaleyi inceleyin.

Kenar boşluklarını ve dolguyu programatik olarak ayarlamanın yanı sıra 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>
  

Önceki örnekte kenar boşluğu ve dolgu uygulanmaktadır. TextView öğesinin her tarafına eşit kenar boşlukları ve dolgu uygulanmıştır. Button ise bunları farklı kenarlara bağımsız olarak nasıl uygulayabileceğinizi gösterir.

Yaygın düzenler

ViewGroup sınıfının her alt sınıfı, içine yerleştirdiğiniz görünümleri görüntülemek için benzersiz bir yol sağlar. En esnek düzen türü ve düzen hiyerarşinizi sığ tutmak için en iyi araçları sağlayan tür ConstraintLayout'dır.

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

Doğrusal düzen oluşturma

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

WebView'da web uygulamaları oluşturma

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

Dinamik listeler oluşturma

Düzeninizin içeriği dinamik olduğunda veya önceden belirlenmediğinde RecyclerView ya da AdapterView alt sınıfını kullanabilirsiniz. RecyclerView, belleği AdapterView'den daha verimli kullandığı için genellikle daha iyi bir seçenektir.

RecyclerView ve AdapterView ile mümkün olan yaygın düzenler şunlardır:

Liste

Kaydırılabilir tek sütunlu bir liste görüntüler.

Izgara

Sütun ve satırlardan oluşan kaydırılabilir bir ızgara gösterir.

RecyclerView daha fazla olasılık ve özel bir düzen yöneticisi oluşturma seçeneği sunar.

Bir adaptör görünümünü verilerle doldurma

AdapterView gibi bir ListView veya GridView öğesini, AdapterView örneğini bir Adapter öğesine bağlayarak doldurabilirsiniz. Bu işlem, harici bir kaynaktan veri alır ve her veri girişini temsil eden bir View oluşturur.

Android, farklı türlerdeki verileri almak ve AdapterView için görünümler oluşturmak üzere kullanışlı olan birkaç Adapter alt sınıfı sağlar. En yaygın iki adaptör şunlardır:

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

Örneğin, bir ListView içinde göstermek istediğiniz bir dizeler diziniz varsa her dize ve dize dizisi için düzeni belirtmek üzere 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() numarasını 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 öğenin görünümünü özelleştirmek için dizinizdeki nesneler için toString() yöntemini geçersiz kılabilirsiniz. Alternatif olarak, her öğe için TextView dışında bir görünüm oluşturmak istiyorsanız (ör. her dizi öğesi için ImageView istiyorsanız) ArrayAdapter sınıfını genişletin ve getView()'i geçersiz kılarak her öğe için istediğiniz görünüm türünü döndürün.

SimpleCursorAdapter
Verileriniz Cursor kaynağından geldiğinde bu adaptörü kullanın. SimpleCursorAdapter kullanırken Cursor içindeki her satır için kullanılacak bir düzeni ve Cursor içindeki hangi sütunların istediğiniz düzenin görünümlerine eklenmesini istediğinizi belirtin. Örneğin, kişilerin adlarının ve telefon numaralarının listesini oluşturmak istiyorsanız her kişi için bir satır ve adlar ile numaralar için sütunlar içeren bir Cursor döndüren bir sorgu gerçekleştirebilirsiniz. Ardından, her sonuç için düzende Cursor öğesinden hangi sütunların olacağını belirten bir dize dizisi ve her sütunun yerleştirilmesi gereken ilgili 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 öğesini oluşturduğunuzda her sonuç için kullanılacak düzeni, sonuçları içeren Cursor öğesini 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);
    

Ardından, her bir fromColumns öğesini ilgili toViews görünümüne ekleyerek sağlanan düzeni kullanarak Cursor içindeki her satır için bir görünüm oluşturur.SimpleCursorAdapter

Uygulamanızın kullanım ömrü boyunca, bağdaştırıcınız tarafından okunan temel verileri değiştirirseniz notifyDataSetChanged() işlevini çağırın. Bu işlem, eklenen görünümü verilerin değiştirildiği konusunda bilgilendirir ve görünüm kendini yeniler.

Tıklama etkinliklerini işleme

AdapterView arayüzünü uygulayarak AdapterView.OnItemClickListener içindeki her öğede 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

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