Özel görünüm bileşenleri oluşturma

Oluşturma yöntemini deneyin
Jetpack Compose, Android için önerilen kullanıcı arayüzü araç setidir. Compose'da düzenlerle çalışma hakkında bilgi edinin.

Android, kullanıcı arayüzünüzü oluşturmak için View ve ViewGroup temel düzen sınıflarına dayalı olarak gelişmiş ve güçlü, bileşene ayrılmış bir model sunar. Platformda, kullanıcı arayüzünüzü oluşturmak için kullanabileceğiniz önceden oluşturulmuş çeşitli View ve ViewGroup alt sınıfı (sırasıyla, widget'lar ve düzenler) bulunmaktadır.

Kullanılabilir widget'ların kısmi listesinde Button, TextView, EditText, ListView, CheckBox, RadioButton, Gallery, Spinner ile daha özel amaçlı AutoCompleteTextView, ImageSwitcher ve TextSwitcher yer alır.

Mevcut düzenler arasında LinearLayout, FrameLayout, RelativeLayout ve diğerleri yer alır. Daha fazla örnek için Genel düzenler bölümüne bakın.

Önceden oluşturulmuş widget'ların veya düzenlerin hiçbiri ihtiyaçlarınızı karşılamıyorsa kendi View alt sınıfınızı oluşturabilirsiniz. Yalnızca mevcut bir widget veya düzende küçük ayarlamalar yapmanız gerekiyorsa widget'ı ya da düzeni alt sınıflandırabilir ve yöntemlerini geçersiz kılabilirsiniz.

Kendi View alt sınıflarınızı oluşturmak, bir ekran öğesinin görünümü ve işlevi üzerinde hassas kontrole sahip olmanızı sağlar. Özel görünümlerle sahip olduğunuz kontrol hakkında fikir vermesi için aşağıda özel görünümlerle yapabileceklerinize ilişkin bazı örnekler verilmiştir:

  • Tamamen özel oluşturulmuş bir View türü (örneğin, 2D grafikler kullanılarak oluşturulmuş ve analog elektronik kontrole benzeyen bir "ses kontrol" düğmesi) oluşturabilirsiniz.
  • Karma kutu (pop-up listesi ve ücretsiz giriş metin alanının kombinasyonu), çift bölmeli seçici kontrolü (her birinde hangi öğenin hangi listede olduğunu yeniden atayabileceğiniz bir liste içeren sol ve sağ bölme) oluşturmak için View bileşen grubunu yeni bir tek bileşende birleştirebilirsiniz.
  • Bir EditText bileşeninin ekrandaki oluşturulma şeklini geçersiz kılabilirsiniz. NotePad örnek uygulaması, bu efekti kullanarak çizgili bir not defteri sayfası oluşturur.
  • Tuşa basma gibi diğer etkinlikleri yakalayabilir ve bunları özel bir şekilde (örneğin, oyun için) yönetebilirsiniz.

Aşağıdaki bölümlerde, özel görünümlerin nasıl oluşturulacağı ve bunların uygulamanızda nasıl kullanılacağı açıklanmaktadır. Ayrıntılı referans bilgileri için View sınıfına bakın.

Temel yaklaşım

Kendi View bileşenlerinizi oluşturmak için bilmeniz gerekenlere genel bir bakışı burada bulabilirsiniz:

  1. Mevcut bir View sınıfının veya alt sınıfının kapsamını kendi sınıfınızla genişletin.
  2. Üst sınıftaki yöntemlerden bazılarını geçersiz kıl. on ile başlayan üst sınıf yöntemleri (ör. onDraw(), onMeasure() ve onKeyDown()). Bu, yaşam döngüsü ve diğer işlev kancaları için geçersiz kıldığınız Activity veya ListActivity içindeki on etkinliklerine benzer.
  3. Yeni uzantı sınıfınızı kullanın. İşlem tamamlandığında, temel alınan görünüm yerine yeni uzantı sınıfınızı kullanabilirsiniz.

Tamamen özelleştirilmiş bileşenler

İstediğiniz gibi görünen, tamamen özelleştirilmiş grafik bileşenler oluşturabilirsiniz. Belki eski bir analog göstergeye benzeyen grafik bir VU ölçüm cihazı veya bir karaoke makinesiyle birlikte şarkı söyleyirken zıplayan bir topun kelimeler boyunca hareket ettiği, şarkı eşliğinde söylenen bir metin görünümü isteyebilirsiniz. Nasıl birleştirdiğinizden bağımsız olarak yerleşik bileşenlerin yapamayacağı bir şey yapmak isteyebilirsiniz.

Neyse ki, uygulamanızın masaüstü iş istasyonunuzdan çok daha az güçte çalışan bir cihazda çalışması gerekebileceğini göz önünde bulundurarak, yalnızca hayal gücünüz, ekran boyutu ve mevcut işlem gücüyle sınırlı olarak, istediğiniz gibi görünen ve davranan bileşenler oluşturabilirsiniz.

Tamamen özelleştirilmiş bir bileşen oluşturmak için aşağıdakileri göz önünde bulundurun:

  • View, genişletebileceğiniz en genel görünümdür. Bu nedenle, genellikle yeni süper bileşeninizi oluşturmak için bu görünümü genişleterek işe başlarsınız.
  • XML'den özellikler ve parametreler alabilen bir kurucu sağlayabilir ve VU ölçüm cihazının rengi ve aralığı ya da iğnenin genişliği ve sönümlemesi gibi kendi özelliklerinizi ve parametrelerinizi kullanabilirsiniz.
  • Muhtemelen kendi etkinlik işleyicilerinizi, mülk erişimcilerinizi ve değiştiricilerinizi oluşturmanın yanı sıra bileşen sınıfınızda daha gelişmiş bir davranış oluşturmak istersiniz.
  • Neredeyse kesinlikle onMeasure() politikasını geçersiz kılmak istersiniz. Ayrıca, bileşenin bir şey göstermesini istiyorsanız onDraw() öğesini geçersiz kılmanız da gerekebilir. Her ikisinin de varsayılan davranışı olsa da varsayılan onDraw() hiçbir şey yapmaz ve varsayılan onMeasure() her zaman 100x100'lük bir boyut ayarlar. Bu boyutu muhtemelen istemediğiniz bir gerçektir.
  • Ayrıca, gerektiğinde diğer on yöntemlerini geçersiz kılabilirsiniz.

onDraw() ve onMeasure() öğelerini genişletin

onDraw() yöntemi, 2D grafikler, diğer standart veya özel bileşenler, stilize edilmiş metin ya da aklınıza gelebilecek her şey dahil olmak üzere istediğiniz her şeyi uygulayabileceğiniz bir Canvas sunar.

onMeasure() biraz daha dahil. onMeasure(), bileşeniniz ile kapsayıcısı arasındaki oluşturma sözleşmesinin kritik bir parçasıdır. İçerdiği parçaların ölçümlerini verimli ve doğru bir şekilde raporlamak için onMeasure() geçersiz kılınmalıdır. Bu durum, üst öğe tarafından onMeasure() yöntemine geçirilen sınır gereksinimleri ve hesaplandıktan sonra ölçülen genişlik ve yükseklikle setMeasuredDimension() yöntemini çağırma şartı nedeniyle biraz daha karmaşık hale getirir. Bu yöntemi geçersiz kılınmış bir onMeasure() yönteminden çağırmazsanız ölçüm zamanında bir istisna oluşur.

Özetle, onMeasure() uygulaması aşağıdaki gibi görünür:

  • Geçersiz kılınan onMeasure() yöntemi, genişlik ve yükseklik özellikleriyle çağrılır. Bu özellikler, oluşturduğunuz genişlik ve yükseklik ölçümleriyle ilgili kısıtlamaların gereksinimleri olarak değerlendirilir. widthMeasureSpec ve heightMeasureSpec parametrelerinin ikisi de boyutları temsil eden tam sayı kodlarıdır. Bu spesifikasyonların gerektirebileceği kısıtlama türleri için tam referansı View.onMeasure(int, int) adresindeki referans belgelerde bulabilirsiniz. Bu referans belgelerde, ölçüm işleminin tamamı da açıklanmaktadır.
  • Bileşeninizin onMeasure() yöntemi, bileşeni oluşturmak için gerekli olan ölçüm genişliğini ve yüksekliğini hesaplar. Geçirilen spesifikasyonların sınırları içinde kalmaya çalışmalıdır (ancak bunları aşabilir). Bu durumda ebeveyn kırpma, kaydırma, istisna yapma veya onMeasure() adlı çocuğa farklı ölçüm özellikleriyle tekrar denemesini isteme gibi ne yapacağını seçebilir.
  • Genişlik ve yükseklik hesaplanırken, hesaplanan ölçümlerle setMeasuredDimension(int width, int height) yöntemini çağırın. Aksi takdirde istisna oluşur.

Çerçevenin görüntülemeler için çağırdığı diğer standart yöntemlerin bir özetini burada bulabilirsiniz:

Kategori Yöntemler Açıklama
içerik üretimi Markalar Bir kurucu biçimi, görünüm koddan oluşturulduğunda ve görünüm bir düzen dosyasından şişirildiğinde çağrılan bir formdur. İkinci form, düzen dosyasında tanımlanan özellikleri ayrıştırır ve uygular.
onFinishInflate() Bir görüntülemeden sonra çağrıldı ve tüm alt öğeleri XML'den şişirildi.
Düzen onMeasure(int, int) Bu görünüm ve tüm alt öğeleri için boyut gereksinimlerini belirlemek amacıyla çağrıldı.
onLayout(boolean, int, int, int, int) Bu görünümün tüm alt öğelerine boyut ve konum ataması gerektiğinde çağrılır.
onSizeChanged(int, int, int, int) Bu görünümün boyutu değiştirildiğinde çağrılır.
Çizim onDraw(Canvas) Görünümün içeriğini oluşturması gerektiğinde çağrılır.
Etkinlik işleme onKeyDown(int, KeyEvent) Tuş kapatma etkinliği gerçekleştiğinde çağrılır.
onKeyUp(int, KeyEvent) Tuş etkinliği gerçekleştiğinde çağrılır.
onTrackballEvent(MotionEvent) Bir iztopu hareketi etkinliği gerçekleştiğinde çağrılır.
onTouchEvent(MotionEvent) Dokunmatik ekran hareketi etkinliği gerçekleştiğinde çağrılır.
Odak onFocusChanged(boolean, int, Rect) Görüntünün odağı kaybolduğunda veya kaybolduğunda çağrılır.
onWindowFocusChanged(boolean) Görünümü içeren pencere odaklanmaya başladığında veya kaybolduğunda çağrılır.
Ekleniyor onAttachedToWindow() Görünüm bir pencereye eklendiğinde çağrılır.
onDetachedFromWindow() Görünüm penceresinden ayrıldığında çağrılır.
onWindowVisibilityChanged(int) Görünümü içeren pencerenin görünürlüğü değiştirildiğinde çağrılır.

Bileşik denetimler

Tamamen özelleştirilmiş bir bileşen oluşturmak yerine, mevcut bir kontrol grubundan oluşan yeniden kullanılabilir bir bileşeni bir araya getirmek istiyorsanız en iyi seçenek bileşik bileşen (veya birleşik kontrol) oluşturmak olabilir. Özetle bu, bir dizi atomik kontrolü veya görünümü, tek bir öğe gibi değerlendirilebilecek mantıksal bir öğe grubu altında bir araya getirir. Örneğin, birleşik kutu, tek bir satır EditText alanı ve yanında pop-up liste bulunan bitişik bir düğmenin kombinasyonu olabilir. Kullanıcı düğmeye dokunur ve listeden bir şey seçerse EditText alanı doldurulur ancak kullanıcı isterse doğrudan EditText alanına bir şey de yazabilir.

Android'de bunu yapmak için kullanabileceğiniz iki görünüm daha vardır: Spinner ve AutoCompleteTextView. Yine de, açılan kutu için bu konsept iyi bir örnektir.

Bir bileşik bileşen oluşturmak için aşağıdakileri yapın:

  • Activity öğesinde olduğu gibi, içerilen bileşenleri oluşturmak için bildirim temelli (XML tabanlı) yaklaşımı kullanın veya bunları kodunuzdan programlı bir şekilde iç içe yerleştirin. Normal başlangıç noktası bir tür Layout olduğundan, Layout uzunluğunda bir sınıf oluşturun. Birleşik kutularda yatay yönlü bir LinearLayout kullanabilirsiniz. Diğer düzenleri iç içe yerleştirebilirsiniz. Böylece bileşik bileşen rastgele bir şekilde karmaşık ve yapılandırılmış olabilir.
  • Yeni sınıfın kurucusunda, üst sınıfın beklediği parametreleri alın ve bunları önce üst sınıf kurucuya geçirin. Ardından, yeni bileşeninizde kullanmak için diğer görünümleri ayarlayabilirsiniz. Burada EditText alanını ve pop-up listesini oluşturursunuz. Oluşturucunuzun çekip kullanabileceği XML'e kendi özelliklerinizi ve parametrelerinizi ekleyebilirsiniz.
  • İsteğe bağlı olarak, içerilen görünümlerinizin oluşturabileceği etkinlikler için işleyiciler oluşturun. Bir liste seçimi yapılırsa EditText içeriğini güncellemek üzere liste öğesi tıklama işleyici için bir işleyici yöntemi örnek olarak verilebilir.
  • İsteğe bağlı olarak, erişimciler ve değiştiricilerle kendi mülklerinizi oluşturabilirsiniz. Örneğin, başlangıçta EditText değerinin bileşende ayarlanmasına izin verin ve gerektiğinde içeriğini sorgulayın.
  • İsteğe bağlı olarak onDraw() ve onMeasure() değerlerini geçersiz kılın. Düzen, muhtemelen iyi sonuç veren varsayılan davranışa sahip olduğundan bu işlem, Layout genişletilirken genellikle gerekli değildir.
  • İsteğe bağlı olarak, onKeyDown() gibi diğer on yöntemlerini geçersiz kılın. Örneğin, belirli bir tuşa dokunulduğunda bir birleşik kutu pop-up listesinden belirli varsayılan değerleri seçebilirsiniz.

Özel kontrol için temel olarak Layout kullanmanın avantajları vardır. Örneğin:

  • Bir etkinlik ekranında olduğu gibi bildirim temelli XML dosyalarını kullanarak düzeni belirtebilir veya görünümleri programatik olarak oluşturup kodunuzdan düzene iç içe yerleştirebilirsiniz.
  • onDraw() ve onMeasure() yöntemleri ile diğer on yöntemlerinin çoğu uygun davranışa sahiptir. Bu nedenle, bunları geçersiz kılmanız gerekmez.
  • Rastgele karmaşık bileşik görünümleri hızlı bir şekilde oluşturabilir ve bunları tek bir bileşen gibi yeniden kullanabilirsiniz.

Mevcut görünüm türünü değiştirme

İstediğinize benzer bir bileşen varsa bu bileşeni genişletebilir ve değiştirmek istediğiniz davranışı geçersiz kılabilirsiniz. Yapacağınız tüm işlemleri tamamen özelleştirilmiş bir bileşenle yapabilirsiniz ancak View hiyerarşisinde daha uzmanlaşmış bir sınıfla başlayarak, istediğiniz şeyi ücretsiz olarak yapan bazı davranışlar elde edebilirsiniz.

Örneğin, NotePad örnek uygulaması, Android platformunu kullanmanın birçok yönünü gösterir. Bunların arasında, çizgili not defteri oluşturmak için bir EditText görünümü genişletme de kullanılabilir. Bu mükemmel bir örnek değil. Buna yönelik API'ler değişebilir ama ilkeleri görebilirsiniz.

Henüz yapmadıysanız NotePad örneğini Android Studio'ya aktarın veya sağlanan bağlantıyı kullanarak kaynağa bakın. Özellikle NoteEditor.java dosyasındaki LinedEditText tanımını inceleyin.

Bu dosyada dikkat edilmesi gereken bazı noktalar şunlardır:

  1. Tanım

    Sınıf aşağıdaki satırla tanımlanır:
    public static class LinedEditText extends EditText

    LinedEditText, NoteEditor etkinliği içindeki bir iç sınıf olarak tanımlanır ancak NoteEditor sınıfının dışından NoteEditor.LinedEditText olarak erişilebilir olması için herkese açıktır.

    Ayrıca LinedEditText, static değerine sahiptir. Yani üst sınıftaki verilere erişmesine izin veren "sentetik yöntemler" oluşturmaz. Bu da NoteEditor ile yakından ilişkili bir şey değil, ayrı bir sınıf olarak davrandığı anlamına gelir. Bu, dış sınıftan durum erişimine ihtiyaçları olmayan iç sınıfları oluşturmanın daha temiz bir yoludur. Oluşturulan sınıfı küçük tutar ve diğer sınıflardan kolayca kullanılabilmesini sağlar.

    LinedEditText, bu durumda özelleştirilecek görünüm olan EditText adlı görünümü genişletir. İşiniz bittiğinde yeni sınıf normal bir EditText görünümünün yerini alabilir.

  2. Sınıfı başlatma

    Her zaman olduğu gibi, önce süper çağrılır. Bu, varsayılan bir kurucu değildir ancak parametreleştirilmiş bir oluşturucudur. EditText, bir XML düzen dosyasından şişirildiğinde bu parametrelerle oluşturulur. Dolayısıyla, kurucunun bunları alıp süper sınıf oluşturucuya da iletmesi gerekir.

  3. Geçersiz kılınan yöntemler

    Bu örnek yalnızca onDraw() yöntemini geçersiz kılar, ancak kendi özel bileşenlerinizi oluştururken diğerlerini geçersiz kılmanız gerekebilir.

    Bu örnekte onDraw() yöntemini geçersiz kılmak, EditText görünümündeki mavi çizgileri boyayabilmenizi sağlar. Tuval, geçersiz kılınan onDraw() yöntemine geçirilir. super.onDraw() yöntemi, yöntem sona ermeden önce çağrılır. Superclass yöntemi çağrılmalıdır. Bu durumda, eklemek istediğiniz satırları boyadıktan sonra en sonda çağırın.

  4. Özel bileşen

    Artık özel bileşeniniz var, peki onu nasıl kullanabilirsiniz? NotePad örneğinde, özel bileşen doğrudan bildirim temelli düzenden kullanılmaktadır. Bu nedenle, res/layout klasöründeki note_editor.xml öğesine bakın:

    <view xmlns:android="http://schemas.android.com/apk/res/android"
        class="com.example.android.notepad.NoteEditor$LinedEditText"
        android:id="@+id/note"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/transparent"
        android:padding="5dp"
        android:scrollbars="vertical"
        android:fadingEdge="vertical"
        android:gravity="top"
        android:textSize="22sp"
        android:capitalize="sentences"
    />
    

    Özel bileşen, XML'de bir genel görünüm olarak oluşturulur ve sınıf, tam paket kullanılarak belirtilir. Tanımladığınız iç sınıfa, Java programlama dilindeki iç sınıflara referans vermenin standart bir yolu olan NoteEditor$LinedEditText gösterimi kullanılarak başvuruda bulunulur.

    Özel görünüm bileşeniniz bir iç sınıf olarak tanımlanmamışsa görünüm bileşenini XML öğe adıyla belirtip class özelliğini hariç tutabilirsiniz. Örneğin:

    <com.example.android.notepad.LinedEditText
      id="@+id/note"
      ... />
    

    LinedEditText sınıfının artık ayrı bir sınıf dosyası olduğuna dikkat edin. Sınıf, NoteEditor sınıfının içine yerleştirildiğinde bu teknik işe yaramaz.

    Tanımdaki diğer özellik ve parametreler, özel bileşen oluşturucuya iletilen ve ardından EditText oluşturucuya iletilen özelliklerdir. Dolayısıyla bunlar, EditText görünümü için kullandığınız parametrelerdir. Kendi parametrelerinizi de ekleyebilirsiniz.

Özel bileşenler oluşturmak, ihtiyacınız olduğu kadar karmaşıktır.

Daha karmaşık bir bileşen daha fazla on yöntemini geçersiz kılıp kendi yardımcı yöntemlerini tanıtarak özelliklerini ve davranışını önemli ölçüde özelleştirebilir. Tek sınır, sizin hayal gücünüz ve bileşenin ne yapması gerektiğidir.