Uygulama erişilebilirliğini iyileştirme ilkeleri

Android çerçevesi, erişilebilirlik gereksinimleri olan kullanıcılara yardımcı olmak için uygulamalardaki içerikleri kullanıcılara sunabilen ve aynı zamanda uygulamaları onlar adına çalıştırabilen bir erişilebilirlik hizmeti oluşturmanıza olanak tanır.

Android, aşağıdakiler de dahil olmak üzere çeşitli sistem erişilebilirlik hizmetleri sağlar:

  • TalkBack: Az gören veya kör kullanıcılara yardımcı olur. Bu uygulama, içerikleri sentezlenmiş bir sesle duyurur ve kullanıcı hareketlerine yanıt olarak bir uygulamada işlemler gerçekleştirir.
  • Anahtar Erişimi: Bedensel engelli kişilere yardımcı olur. Etkileşimli öğeleri vurgular ve kullanıcının bir düğmeye basmasına karşılık olarak işlemler gerçekleştirir. Cihazı sadece bir veya iki düğme kullanarak kontrol etmenizi sağlar.

Uygulamanızın, erişilebilirlik gereksinimleri olan kullanıcıların uygulamanızı başarılı bir şekilde kullanmasına yardımcı olmak için bu sayfada açıklanan en iyi uygulamalara uyması gerekir. Bu uygulama, Uygulamaları daha erişilebilir hale getirme bölümünde açıklanan yönergelere dayalı olmalıdır.

İlerleyen bölümlerde açıklanan bu en iyi uygulamaların her biri, uygulamanızın erişilebilirliğini daha da iyileştirebilir:

Etiket öğeleri
Kullanıcılar, uygulamanızdaki her etkileşimli ve anlamlı kullanıcı arayüzü öğesinin içeriğini ve amacını anlayabilmelidir.
Erişilebilirlik işlemleri ekleme
Erişilebilirlik işlemleri ekleyerek, erişilebilirlik hizmetlerini kullananların uygulamanızdaki kritik kullanıcı akışlarını tamamlamasını sağlayabilirsiniz.
Sistem widget'larını genişletme
Kendi özel görünümlerinizi oluşturmak yerine çerçevenin içerdiği görünüm öğelerine göre hareket edin. Çerçevenin görünüm ve widget sınıfları, uygulamanızın ihtiyaç duyduğu erişilebilirlik özelliklerinin çoğunu zaten sağlar.
Renk dışında işaretler kullanma
Kullanıcılar, kullanıcı arayüzündeki öğe kategorilerini açıkça ayırt edebilmelidir. Bunu yapmak için renklerin yanı sıra desen ve konumu kullanarak bu farkları ifade edin.
Medya içeriğini daha erişilebilir hale getirme
Bu içeriği tüketen kullanıcıların tamamen görsel veya işitsel işaretlerle uğraşmak zorunda kalmaması için uygulamanızın video veya ses içeriğine açıklama ekleyin.

Etiket öğeleri

Uygulamanızdaki her bir etkileşimli kullanıcı arayüzü öğesi için kullanıcılara yararlı ve açıklayıcı etiketler sağlamanız önemlidir. Her etiket, belirli bir öğenin anlamını ve amacını açıklamalıdır. TalkBack gibi ekran okuyucular, bu etiketleri kullanıcılara duyurabilir.

Çoğu durumda, bir kullanıcı arayüzü öğesinin açıklamasını öğeyi içeren düzen kaynak dosyasında belirtirsiniz. Etiketleri genellikle uygulamaları daha erişilebilir hale getirme kılavuzunda açıklandığı gibi contentDescription özelliğini kullanarak eklersiniz. Aşağıdaki bölümlerde başka etiketleme teknikleri açıklanmıştır.

Düzenlenebilir öğeler

EditText nesneleri gibi düzenlenebilir öğeleri etiketlerken, bu örnek metni ekran okuyucuların kullanımına sunmanın yanı sıra öğenin kendisinde geçerli bir giriş örneği sağlayan metinleri göstermek de yararlı olur. Bu durumlarda, aşağıdaki snippet'te gösterildiği gibi android:hint özelliğini kullanabilirsiniz:

<!-- The hint text for en-US locale would be
     "Apartment, suite, or building". -->
<EditText
   android:id="@+id/addressLine2"
   android:hint="@string/aptSuiteBuilding" ... />

Bu durumda, View nesnesinin android:labelFor özelliği EditText öğesinin kimliğine ayarlanmalıdır. Daha ayrıntılı bilgi için aşağıdaki bölümü inceleyin.

Birinin diğerini açıkladığı öğe çiftleri

EditText öğesinde genellikle kullanıcıların EditText öğesine ne girmesi gerektiğini açıklayan karşılık gelen bir View nesnesi bulunur. View nesnesinin android:labelFor özelliğini ayarlayarak bu ilişkiyi belirtebilirsiniz.

Bu tür öğe çiftlerini etiketlemeye ilişkin bir örnek aşağıdaki snippet'te görünür:


<!-- Label text for en-US locale would be "Username:" -->
<TextView
   android:id="@+id/usernameLabel" ...
   android:text="@string/username"
   android:labelFor="@+id/usernameEntry" />

<EditText
   android:id="@+id/usernameEntry" ... />

<!-- Label text for en-US locale would be "Password:" -->
<TextView
   android:id="@+id/passwordLabel" ...
   android:text="@string/password
   android:labelFor="@+id/passwordEntry" />

<EditText
   android:id="@+id/passwordEntry"
   android:inputType="textPassword" ... />

Koleksiyondaki öğeler

Bir koleksiyonun öğelerine etiket eklerken her etiket benzersiz olmalıdır. Bu şekilde, bir etiketi duyururken sistemin erişilebilirlik hizmetleri, ekrandaki tek bir öğeye referans verebilir. Bu yazışma, kullanıcıların kullanıcı arayüzünde ne zaman geçiş yaptıklarını veya odağı zaten keşfettikleri bir öğeye ne zaman taşıdıklarını bilmelerini sağlar.

Özellikle, her alt öğenin benzersiz bir şekilde tanımlanabilmesi için yeniden kullanılan düzenlerdeki öğelere (RecyclerView nesneleri gibi) ek metin veya bağlamsal bilgiler ekleyin.

Bunu yapmak için bağdaştırıcı uygulamanızın bir parçası olarak içerik açıklamasını aşağıdaki kod snippet'inde gösterildiği gibi ayarlayın:

Kotlin

data class MovieRating(val title: String, val starRating: Integer)

class MyMovieRatingsAdapter(private val myData: Array<MovieRating>):
        RecyclerView.Adapter<MyMovieRatingsAdapter.MyRatingViewHolder>() {

    class MyRatingViewHolder(val ratingView: ImageView) :
            RecyclerView.ViewHolder(ratingView)

    override fun onBindViewHolder(holder: MyRatingViewHolder, position: Int) {
        val ratingData = myData[position]
        holder.ratingView.contentDescription = "Movie ${position}: " +
                "${ratingData.title}, ${ratingData.starRating} stars"
    }
}

Java

public class MovieRating {
    private String title;
    private int starRating;
    // ...
    public String getTitle() { return title; }
    public int getStarRating() { return starRating; }
}

public class MyMovieRatingsAdapter
        extends RecyclerView.Adapter<MyAdapter.MyRatingViewHolder> {
    private MovieRating[] myData;


    public static class MyRatingViewHolder extends RecyclerView.ViewHolder {
        public ImageView ratingView;
        public MyRatingViewHolder(ImageView iv) {
            super(iv);
            ratingView = iv;
        }
    }

    @Override
    public void onBindViewHolder(MyRatingViewHolder holder, int position) {
        MovieRating ratingData = myData[position];
        holder.ratingView.setContentDescription("Movie " + position + ": " +
                ratingData.getTitle() + ", " + ratingData.getStarRating() +
                " stars")
    }
}

İlgili içerik grupları

Uygulamanız, doğal bir grup oluşturan birkaç kullanıcı arayüzü öğesi görüntülüyorsa (şarkı ayrıntıları veya bir mesajın özellikleri gibi) bu öğeleri, genellikle ViewGroup alt sınıfı olan bir kapsayıcı içinde düzenleyin. Container nesnesinin android:screenReaderFocusable özelliğini true ve her iç nesnenin android:focusable özelliğini false olarak ayarlayın. Bu şekilde erişilebilirlik hizmetleri, içeriğin içindeki açıklamaları tek bir duyuruda art arda sunabilir. İlgili öğelerin bu şekilde birleştirilmesi, yardımcı teknoloji kullanıcılarının ekrandaki bilgileri daha verimli bir şekilde keşfetmesine yardımcı olur.

Aşağıdaki snippet'te birbiriyle ilişkili içerik parçaları bulunmaktadır. Bu nedenle, ConstraintLayout örneği olan kapsayıcı öğenin android:screenReaderFocusable özelliği true, iç TextView öğelerinin her birinin android:focusable özelliği false olarak ayarlanmıştır:

<!-- In response to a single user interaction, accessibility services announce
     both the title and the artist of the song. -->
<ConstraintLayout
    android:id="@+id/song_data_container" ...
    android:screenReaderFocusable="true">

    <TextView
        android:id="@+id/song_title" ...
        android:focusable="false"
        android:text="@string/my_song_title" />
    <TextView
        android:id="@+id/song_artist"
        android:focusable="false"
        android:text="@string/my_songwriter" />
</ConstraintLayout>

Erişilebilirlik hizmetleri iç öğelerin açıklamalarını tek bir sesle bildirdiği için öğenin anlamını aktarmaya devam ederken her açıklamayı mümkün olduğunca kısa tutmak önemlidir.

Not: Genel olarak, bir grubun alt öğelerinin metinlerini toplayarak bir grup için içerik açıklaması oluşturmaktan kaçınmalısınız. Bu durumda grup açıklaması zayıflar ve bir alt grubun metni değiştiğinde grubun açıklaması görünür metinle eşleşmeyebilir.

Bir listede veya ızgara bağlamında ekran okuyucu, bir listenin veya ızgara öğesinin alt metin düğümlerinin metnini birleştirebilir. Bu duyuruda değişiklik yapmaktan kaçınmanızı öneririz.

İç içe yerleştirilmiş gruplar

Uygulamanızın arayüzü çok boyutlu bilgiler sunuyorsa (ör. festival etkinliklerinin günlük listesi) iç grup kapsayıcılarında android:screenReaderFocusable özelliğini kullanın. Bu etiketleme şeması, ekranın içeriğini keşfetmek için gereken duyuru sayısı ile her bir duyurunun uzunluğu arasında iyi bir denge sağlar.

Aşağıdaki kod snippet'inde daha büyük gruplardaki grupları etiketlemek için bir yöntem gösterilmektedir:

<!-- In response to a single user interaction, accessibility services
     announce the events for a single stage only. -->
<ConstraintLayout
    android:id="@+id/festival_event_table" ... >
    <ConstraintLayout
        android:id="@+id/stage_a_event_column"
        android:screenReaderFocusable="true">

        <!-- UI elements that describe the events on Stage A. -->

    </ConstraintLayout>
    <ConstraintLayout
        android:id="@+id/stage_b_event_column"
        android:screenReaderFocusable="true">

        <!-- UI elements that describe the events on Stage B. -->

    </ConstraintLayout>
</ConstraintLayout>

Metin içinde başlıklar

Bazı uygulamalar, ekranda görünen metin gruplarını özetlemek için başlıklar kullanır. Belirli bir View öğesi bir başlığı temsil ediyorsa öğenin android:accessibilityHeading özelliğini true değerine ayarlayarak öğenin erişilebilirlik hizmetleriyle ilgili amacını belirtebilirsiniz.

Erişilebilirlik hizmetlerini kullananlar, paragraflar arasında veya kelimeler arasında gezinmek yerine başlıklar arasında gezinmeyi seçebilir. Bu esneklik, metinde gezinme deneyimini iyileştirir.

Erişilebilirlik bölmesi başlıkları

Android 9 (API düzeyi 28) ve sonraki sürümlerde, ekranın bölmeleri için erişilebilirlik dostu başlıklar sağlayabilirsiniz. Erişilebilirlik amacıyla bölmeler, bir pencerenin içeriği gibi görsel olarak farklı bir bölümüdür. Erişilebilirlik hizmetlerinin bir bölmenin pencereye benzer davranışını anlayabilmesi için uygulamanızın bölmelerine açıklayıcı başlıklar verin. Erişilebilirlik hizmetleri, bir bölmenin görünümü veya içeriği değiştiğinde kullanıcılara daha ayrıntılı bilgiler sağlayabilir.

Bölmenin başlığını belirtmek için aşağıdaki snippet'te gösterildiği gibi android:accessibilityPaneTitle özelliğini kullanın:

<!-- Accessibility services receive announcements about content changes
     that are scoped to either the "shopping cart view" section (top) or
     "browse items" section (bottom) -->
<MyShoppingCartView
     android:id="@+id/shoppingCartContainer"
     android:accessibilityPaneTitle="@string/shoppingCart" ... />

<MyShoppingBrowseView
     android:id="@+id/browseItemsContainer"
     android:accessibilityPaneTitle="@string/browseProducts" ... />

Dekoratif öğeler

Kullanıcı arayüzünüzde yalnızca görsel boşluk veya görsel görünüm amaçlı olan bir öğe varsa android:importantForAccessibility özelliğini "no" olarak ayarlayın.

Erişilebilirlik işlemleri ekleyin

Erişilebilirlik hizmetleri kullanıcılarının uygulamanızdaki tüm kullanıcı akışlarını kolayca gerçekleştirmesine izin vermek önemlidir. Örneğin, bir kullanıcı listedeki bir öğeyi kaydırabiliyorsa bu işlem erişilebilirlik hizmetleriyle de gösterilebilir. Böylece kullanıcılar, aynı kullanıcı akışını tamamlamanın alternatif bir yolunu elde ederler.

Tüm işlemleri erişilebilir hale getir

TalkBack, Sesli Erişim veya Anahtar Erişimi kullanıcıları, uygulama içindeki belirli kullanıcı akışlarını tamamlamak için alternatif yollara ihtiyaç duyabilir. Sürükleyip bırakma veya kaydırma gibi hareketlerle ilişkili işlemler için uygulamanız, işlemleri erişilebilirlik hizmeti kullanıcılarının erişebileceği şekilde gösterebilir.

Uygulama, erişilebilirlik işlemlerini kullanarak kullanıcıların bir işlemi tamamlamaları için alternatif yollar sağlayabilir.

Örneğin, uygulamanız kullanıcıların bir öğeyi kaydırmasına izin veriyorsa aşağıdaki gibi özel bir erişilebilirlik işlemiyle de bu işlevi sunabilirsiniz:

Kotlin

ViewCompat.addAccessibilityAction(
    // View to add accessibility action
    itemView,
    // Label surfaced to user by an accessibility service
    getText(R.id.archive)
) { _, _ ->
    // Same method executed when swiping on itemView
    archiveItem()
    true
}

Java

ViewCompat.addAccessibilityAction(
    // View to add accessibility action
    itemView,
    // Label surfaced to user by an accessibility service
    getText(R.id.archive),
    (view, arguments) -> {
        // Same method executed when swiping on itemView
        archiveItem();
        return true;
    }
);

With the custom accessibility action implemented, users can access the action through the actions menu.

Make available actions understandable

When a view supports actions such as touch & hold, an accessibility service such as TalkBack announces it as "Double tap and hold to long press."

This generic announcement doesn't give the user any context about what a touch & hold action does.

To make this announcement more descriptive, you can replace the accessibility action’s announcement like so:

Kotlin

ViewCompat.replaceAccessibilityAction(
    // View that contains touch & hold action
    itemView,
    AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_LONG_CLICK,
    // Announcement read by TalkBack to surface this action
    getText(R.string.favorite),
    null
)

Java

ViewCompat.replaceAccessibilityAction(
    // View that contains touch & hold action
    itemView,
    AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_LONG_CLICK,
    // Announcement read by TalkBack to surface this action
    getText(R.string.favorite),
    null
);

This results in TalkBack announcing "Double tap and hold to favorite," helping users understand the purpose of the action.

Extend system widgets

Note: When you design your app's UI, use or extend system-provided widgets that are as far down Android's class hierarchy as possible. System-provided widgets that are far down the hierarchy already have most of the accessibility capabilities your app needs. It's easier to extend these system-provided widgets than to create your own from the more generic View, ViewCompat, Canvas, and CanvasCompat classes.

If you must extend View or Canvas directly, which might be necessary for a highly customized experience or a game level, see Make custom views more accessible.

This section uses the example of implementing a special type of Switch called TriSwitch while following best practices around extending system widgets. A TriSwitch object works similarly to a Switch object, except that each instance of TriSwitch allows the user to toggle among three possible states.

Extend from far down the class hierarchy

The Switch object inherits from several framework UI classes in its hierarchy:

View
↳ TextView
  ↳ Button
    ↳ CompoundButton
      ↳ Switch

Yeni TriSwitch sınıfının doğrudan Switch sınıfından genişletmesi en iyi seçenektir. Böylece Android erişilebilirlik çerçevesi, TriSwitch sınıfının ihtiyaç duyduğu erişilebilirlik özelliklerinin çoğunu sağlar:

  • Erişilebilirlik işlemleri: Erişilebilirlik hizmetlerinin, bir TriSwitch nesnesinde gerçekleştirilen her olası kullanıcı girişini nasıl emüle edebileceğiyle ilgili sistem bilgileri. (Şu kaynaktan devralındı: View.)
  • Erişilebilirlik etkinlikleri: Ekran yenilendiğinde veya güncellendiğinde TriSwitch nesnesinin görünümünün mümkün olan her şekilde değişebileceği tüm erişilebilirlik hizmetleriyle ilgili bilgiler. (Şu kaynaktan devralındı: View.)
  • Özellikler: her TriSwitch nesnesiyle ilgili ayrıntılar (görüntülediği metnin içeriği gibi). (Şu kaynaktan devralındı: TextView.)
  • Durum bilgisi: Bir TriSwitch nesnesinin mevcut durumunun açıklaması (ör. "işaretlendi" veya "işareti kaldırıldı"). (Şu kaynaktan devralındı: CompoundButton.)
  • Durumun metin açıklaması: Her bir durumun temsil ettiği metin temelli açıklama. (Şu kaynaktan devralındı: Switch.)

Switch ve üst sınıflarının davranışı, TriSwitch nesneleri için hemen hemen aynıdır. Dolayısıyla, uygulamanızda olası durum sayısını ikiden üçe çıkarmaya odaklanabilirsiniz.

Özel etkinlikler tanımlama

Bir sistem widget'ını genişlettiğinizde muhtemelen kullanıcıların söz konusu widget'la etkileşimde bulunma şekline ilişkin bir özelliği değiştirirsiniz. Erişilebilirlik hizmetlerinin, uygulamanızın widget'ını kullanıcı doğrudan widget'la etkileşimde bulunuyormuş gibi güncelleyebilmesi için bu etkileşim değişikliklerini tanımlamak önemlidir.

Genel bir kural olarak, geçersiz kıldığınız her görüntülemeye dayalı geri arama için ViewCompat.replaceAccessibilityAction() değerini geçersiz kılarak ilgili erişilebilirlik işlemini yeniden tanımlamanız gerekir. Uygulamanızın testlerinde, ViewCompat.performAccessibilityAction() yöntemini çağırarak yeniden tanımlanan bu işlemlerin davranışını doğrulayabilirsiniz.

Bu ilke, TriSwitch nesneleri için nasıl çalışır?

Sıradan bir Switch nesnesinin aksine, TriSwitch nesnesine dokunulduğunda üç olası durum döndürülür. Bu nedenle, ilgili ACTION_CLICK erişilebilirlik işleminin güncellenmesi gerekir:

Kotlin

class TriSwitch(context: Context) : Switch(context) {
    // 0, 1, or 2
    var currentState: Int = 0
        private set

    init {
        updateAccessibilityActions()
    }

    private fun updateAccessibilityActions() {
        ViewCompat.replaceAccessibilityAction(this, ACTION_CLICK,
            action-label) {
            view, args -> moveToNextState()
        })
    }

    private fun moveToNextState() {
        currentState = (currentState + 1) % 3
    }
}

Java

public class TriSwitch extends Switch {
    // 0, 1, or 2
    private int currentState;

    public int getCurrentState() {
        return currentState;
    }

    public TriSwitch() {
        updateAccessibilityActions();
    }

    private void updateAccessibilityActions() {
        ViewCompat.replaceAccessibilityAction(this, ACTION_CLICK,
            action-label, (view, args) -> moveToNextState());
    }

    private void moveToNextState() {
        currentState = (currentState + 1) % 3;
    }
}

Renk dışında işaretler kullanın

Renk körlüğü olan kullanıcılara yardımcı olmak için uygulamanızın ekranlarındaki kullanıcı arayüzü öğelerini ayırt etmek amacıyla renk dışında işaretler kullanın. Bu teknikler farklı şekil veya boyutlar kullanmayı, metin ya da görsel desenler sağlamayı veya öğelerdeki farkları işaretlemek için ses veya dokunma tabanlı (dokunsal) geri bildirim eklemeyi içerebilir.

Şekil 1'de bir etkinliğin iki sürümü gösterilmektedir. Bir sürüm, iş akışındaki iki olası işlemi ayırt etmek için yalnızca renk kullanır. Diğer sürüm, iki seçenek arasındaki farkları vurgulamak için rengin yanı sıra şekilleri ve metni de ekleme en iyi uygulamayı kullanır:

Şekil 1. Yalnızca renk (solda) ve renk, şekil ve metin (sağ) kullanarak kullanıcı arayüzü öğeleri oluşturma örnekleri.

Medya içeriğini daha erişilebilir hale getirme

Video klip veya ses kaydı gibi medya içeriği barındıran bir uygulama geliştiriyorsanız, bu materyali anlama konusunda farklı erişilebilirlik ihtiyaçları olan kullanıcıları desteklemeye çalışın. Özellikle aşağıdakileri yapmanızı öneririz:

  • Kullanıcıların medya içeriğini duraklatmasına veya durdurmasına, ses düzeyini değiştirmesine ve altyazıları (altyazılar) açıp kapatmasına olanak tanıyan kontroller ekleyin.
  • Video, bir iş akışını tamamlamak için hayati önem taşıyan bilgiler sunuyorsa aynı içeriği transkript gibi alternatif bir biçimde sunun.

Ek kaynaklar

Uygulamanızı daha erişilebilir hale getirme hakkında daha fazla bilgi edinmek için aşağıdaki ek kaynaklara bakın:

Codelab uygulamaları

Blog yayınları