Uygulamalar geliştirin

Aşağıdaki materyal uygulama geliştiricileri içindir.

Uygulama desteğinizi döner hale getirmek için şunları yapmanız GEREKİR:

  1. İlgili etkinlik düzenine bir FocusParkingView yerleştirin.
  2. Odaklanabilen (veya odaklanamayan) görünümlerden emin olun.
  3. FocusParkingView dışındaki tüm odaklanılabilir görünümlerinizi sarmak için FocusArea s'yi kullanın.

Ortamınızı rotary özellikli uygulamalar geliştirecek şekilde ayarladıktan sonra, bu görevlerin her biri aşağıda ayrıntılı olarak açıklanmaktadır.

Döner denetleyiciyi ayarlama

Döner özellikli uygulamalar geliştirmeye başlamadan önce bir döner denetleyiciye veya bir yedek parçaya ihtiyacınız vardır. Aşağıda açıklanan seçeneklere sahipsiniz.

Emülatör

source build/envsetup.sh && lunch car_x86_64-userdebug
m -j
emulator -wipe-data -no-snapshot -writable-system

Ayrıca aosp_car_x86_64-userdebug kullanabilirsiniz.

Benzetilmiş döner denetleyiciye erişmek için:

  1. Araç çubuğunun altındaki üç noktaya dokunun:

    Taklit edilmiş döner denetleyiciye erişim
    Şekil 1. Erişim taklitli döner denetleyici
  2. Genişletilmiş kontroller penceresinde Araba döner seçeneğini seçin:

    Araba dönerini seçin
    Şekil 2. Araba dönerini seçin

USB klavye

  • Android Automotive OS (AAOS) çalıştıran cihazınıza bir USB klavye takın. Bu, bazı durumlarda ekran klavyesinin görünmesini engeller.
  • Bir userdebug veya eng yapısı kullanın.
  • Anahtar olay filtrelemeyi etkinleştirin:
    adb shell settings put secure android.car.ROTARY_KEY_EVENT_FILTER 1
    
  • Her eyleme karşılık gelen anahtarı bulmak için aşağıdaki tabloya bakın:
    Anahtar Döner eylem
    Q Saat yönünün tersine çevirin
    e Saat yönünde döndür
    A Sola sürükle
    D Sağa sürükle
    K Yukarı it
    S Aşağı it
    F veya Virgül Orta düğme
    R veya Esc Geri butonu

ADB komutları

Döner giriş olaylarını enjekte etmek için car_service komutlarını kullanabilirsiniz. Bu komutlar, Android Automotive OS (AAOS) çalıştıran cihazlarda veya bir emülatörde çalıştırılabilir.

car_service komutları Döner giriş
adb shell cmd car_service inject-rotary Saat yönünün tersine çevirin
adb shell cmd car_service inject-rotary -c true Saat yönünde döndür
adb shell cmd car_service inject-rotary -dt 100 50 Birden çok kez saat yönünün tersine döndür (100 ms önce ve 50 ms önce)
adb shell cmd car_service inject-key 282 Sola sürükle
adb shell cmd car_service inject-key 283 Sağa sürükle
adb shell cmd car_service inject-key 280 Yukarı it
adb shell cmd car_service inject-key 281 Aşağı it
adb shell cmd car_service inject-key 23 Ortadaki düğmeye tıklama
adb shell input keyevent inject-key 4 Geri düğmesine tıklayın

OEM döner denetleyici

Döner kontrol cihazı donanımınız çalışır durumda olduğunda bu en gerçekçi seçenektir. Özellikle hızlı dönüşü test etmek için kullanışlıdır.

OdaklanmaPark Görünümü

FocusParkingView Araç Kullanıcı Arayüzü Kitaplığı'ndaki (araba-ui-kütüphanesi) şeffaf bir görünümdür. RotaryService bunu döner kontrol cihazı navigasyonunu desteklemek için kullanır. FocusParkingView düzendeki ilk odaklanılabilir görünüm olmalıdır. Tüm FocusArea dışına yerleştirilmelidir. Her pencerede bir FocusParkingView bulunmalıdır. Zaten FocusParkingView içeren car-ui-library temel düzenini kullanıyorsanız başka bir FocusParkingView eklemenize gerek yoktur. Aşağıda RotaryPlayground FocusParkingView örneği gösterilmektedir.

<FrameLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="match_parent">
   <com.android.car.ui.FocusParkingView
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"/>
   <FrameLayout
       android:layout_width="match_parent"
       android:layout_height="match_parent"/>
</FrameLayout>

FocusParkingView ihtiyaç duymanızın nedenleri şunlardır:

  1. Odak başka bir pencerede ayarlandığında Android odağı otomatik olarak temizlemez. Önceki penceredeki odağı temizlemeye çalışırsanız Android, o penceredeki bir görünüme yeniden odaklanır ve bu da iki pencerenin aynı anda odaklanmasına neden olur. Her pencereye FocusParkingView eklemek bu sorunu çözebilir. Bu görünüm şeffaftır ve varsayılan odak vurgusu devre dışıdır, böylece odaklanmış olsun ya da olmasın kullanıcı tarafından görülmez. Odaklamayı alabilir, böylece RotaryService odak vurgusunu kaldırmak için odağı onun üzerine park edebilir.
  2. Geçerli pencerede yalnızca bir FocusArea varsa, kontrol ünitesinin FocusArea döndürülmesi, RotaryService odağı sağdaki görünümden soldaki görünüme (veya tam tersi) taşımasına neden olur. Bu görünümü her pencereye eklemek sorunu çözebilir. RotaryService odak hedefinin FocusParkingView olduğunu belirlediğinde, odağı hareket ettirmeyerek sarmalamayı önlediği noktada bir sarmanın meydana gelmek üzere olduğunu belirleyebilir.
  3. Döner kontrol bir uygulamayı başlattığında, Android her zaman FocusParkingView olan ilk odaklanılabilir görünüme odaklanır. FocusParkingView odaklanılacak en uygun görünümü belirler ve ardından odağı uygular.

Odaklanabilir görünümler

RotaryService telefonların fiziksel klavyeleri ve D-pad'leri olduğu zamanlara dayanan, Android çerçevesinin mevcut görüntüleme odağı konseptini temel alır. Mevcut android:nextFocusForward özelliği, döner kullanım için yeniden tasarlandı (bkz. FocusArea özelleştirmesi ), ancak android:nextFocusLeft , android:nextFocusRight , android:nextFocusUp ve android:nextFocusDown böyle değildir.

RotaryService yalnızca odaklanılabilir görüşlere odaklanır. Button gibi bazı görünümler genellikle odaklanabilir. TextView ve ViewGroup gibi diğerleri genellikle değildir. Tıklanabilir görünümler otomatik olarak odaklanabilir ve görünümler, bir tıklama dinleyicisine sahip olduklarında otomatik olarak tıklanabilir. Bu otomatik mantık istenen odaklanılabilirlikle sonuçlanırsa görünümün odaklanabilirliğini açıkça ayarlamanız gerekmez. Otomatik mantık istenen odaklanılabilirliği sağlayamazsa, android:focusable niteliğini true veya false olarak ayarlayın veya görünümün odaklanabilirliğini View.setFocusable(boolean) ile programlı olarak ayarlayın. RotaryService buna odaklanabilmesi için, bir görünümün aşağıdaki gereksinimleri karşılaması ZORUNLUDUR:

  • Odaklanabilir
  • Etkinleştirilmiş
  • Görünür
  • Genişlik ve yükseklik için sıfır olmayan değerlere sahip olun

Bir görünüm, örneğin odaklanabilir ancak devre dışı bırakılmış bir düğme gibi tüm bu gereksinimleri karşılamıyorsa, kullanıcı ona odaklanmak için döner kontrolü kullanamaz. Devre dışı bırakılan görünümlere odaklanmak istiyorsanız, görünümün nasıl göründüğünü, Android'in devre dışı olarak kabul etmesi gerektiğini belirtmeden kontrol etmek için android:state_enabled yerine özel bir durum kullanmayı düşünün. Uygulamanız, dokunulduğunda görünümün neden devre dışı bırakıldığını kullanıcıya bildirebilir. Bir sonraki bölümde bunun nasıl yapılacağı açıklanmaktadır.

Özel durum

Özel bir durum eklemek için:

  1. Görünümünüze özel bir özellik eklemek için. Örneğin, CustomView görünüm sınıfına state_rotary_enabled özel durumu eklemek için şunu kullanın:
    <declare-styleable name="CustomView">
        <attr name="state_rotary_enabled" format="boolean" />
    </declare-styleable>
    
  2. Bu durumu izlemek için görünümünüze erişimci yöntemleriyle birlikte bir örnek değişkeni ekleyin:
    private boolean mRotaryEnabled;
    public boolean getRotaryEnabled() { return mRotaryEnabled; }
    public void setRotaryEnabled(boolean rotaryEnabled) {
        mRotaryEnabled = rotaryEnabled;
    }
    
  3. Görünümünüz oluşturulduğunda özelliğinizin değerini okumak için:
    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomView);
    mRotaryEnabled = a.getBoolean(R.styleable.CustomView_state_rotary_enabled);
    
  4. Görünüm sınıfınızda onCreateDrawableState() yöntemini geçersiz kılın ve ardından uygun olduğunda özel durumu ekleyin. Örneğin:
    @Override
    protected int[] onCreateDrawableState(int extraSpace) {
        if (mRotaryEnabled) extraSpace++;
        int[] drawableState = super.onCreateDrawableState(extraSpace);
        if (mRotaryEnabled) {
            mergeDrawableStates(drawableState, { R.attr.state_rotary_enabled });
        }
        return drawableState;
    }
    
  5. Görünümünüzün tıklama işleyicisinin durumuna bağlı olarak farklı performans göstermesini sağlayın. Örneğin, tıklama işleyicisi hiçbir şey yapmayabilir veya mRotaryEnabled false olduğunda bir uyarı görüntüleyebilir.
  6. Düğmenin devre dışı görünmesini sağlamak için görünümünüzün arka planında çizilebilir, android:state_enabled yerine app:state_rotary_enabled kullanın. Henüz sahip değilseniz şunu eklemeniz gerekir:
    xmlns:app="http://schemas.android.com/apk/res-auto"
    
  7. Görünümünüz herhangi bir düzende devre dışı bırakıldıysa, android:enabled="false" app:state_rotary_enabled="false" ile değiştirin ve ardından yukarıdaki gibi app ad alanını ekleyin.
  8. Görünümünüz program aracılığıyla devre dışı bırakıldıysa, setEnabled() çağrılarını setRotaryEnabled() çağrılarıyla değiştirin.

Odak Alanı

Gezinmeyi kolaylaştırmak ve diğer uygulamalarla tutarlı olmak amacıyla odaklanabilir görünümleri bloklara bölmek için FocusAreas kullanın. Örneğin, uygulamanızda bir araç çubuğu varsa araç çubuğu, uygulamanızın geri kalanından ayrı bir FocusArea olmalıdır. Sekme çubukları ve diğer gezinme öğeleri de uygulamanın geri kalanından ayrılmalıdır. Büyük listelerin genellikle kendi FocusArea olmalıdır. Değilse, kullanıcıların bazı görünümlere erişmek için listenin tamamını döndürmeleri gerekir.

FocusArea , araç kullanıcı arayüzü kitaplığında LinearLayout bir alt sınıfıdır. Bu özellik etkinleştirildiğinde FocusArea , alt öğelerinden birine odaklanıldığında bir vurgu çizer. Daha fazla bilgi edinmek için bkz. Odak vurgusunu özelleştirme .

Düzen dosyasında bir gezinme bloğu oluştururken, bu blok için kapsayıcı olarak bir LinearLayout kullanmayı düşünüyorsanız bunun yerine FocusArea kullanın. Aksi takdirde bloğu FocusArea sarın.

Bir FocusArea başka bir FocusArea YERLEŞTİRMEYİN . Bunu yapmak tanımsız gezinme davranışına yol açar. Tüm odaklanılabilir görünümlerin bir FocusArea içinde yuvalandığından emin olun.

RotaryPlayground bir FocusArea örneği aşağıda gösterilmektedir:

<com.android.car.ui.FocusArea
       android:layout_margin="16dp"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:orientation="vertical">
       <EditText
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:singleLine="true">
       </EditText>
   </com.android.car.ui.FocusArea>

FocusArea şu şekilde çalışır:

  1. Döndürme ve itme eylemlerini gerçekleştirirken, RotaryService görünüm hiyerarşisinde FocusArea örneklerini arar.
  2. Bir rotasyon olayı alındığında, RotaryService odağı aynı FocusArea alabilecek başka bir Görünüme taşır.
  3. Bir dürtme olayı alındığında, RotaryService odağı başka bir (genellikle bitişik) FocusArea alabilecek başka bir görünüme taşır.

Mizanpajınıza herhangi bir FocusAreas eklemezseniz kök görünüm, örtülü bir odak alanı olarak değerlendirilir. Kullanıcı uygulamada gezinmek için dürtülemez. Bunun yerine, diyaloglar için yeterli olabilecek tüm odaklanılabilir görünümler arasında geçiş yapacaklardır.

Odak Alanı özelleştirmesi

Döner gezinmeyi özelleştirmek için iki standart Görünüm özelliği kullanılabilir:

  • android:nextFocusForward uygulama geliştiricilerinin bir odak alanındaki dönüş sırasını belirlemesine olanak tanır. Bu, klavyede gezinme için Sekme sırasını kontrol etmek için kullanılan özniteliğin aynısıdır. Bir döngü oluşturmak için bu özelliği KULLANMAYIN . Bunun yerine, bir döngü oluşturmak için app:wrapAround (aşağıya bakın) kullanın.
  • android:focusedByDefault uygulama geliştiricilerinin penceredeki varsayılan odak görünümünü belirlemesine olanak tanır. Bu özelliği ve app:defaultFocus (aşağıya bakın) aynı FocusArea içinde KULLANMAYIN .

FocusArea ayrıca döner gezinmeyi özelleştirmek için bazı nitelikleri de tanımlar. Örtülü odak alanları bu niteliklerle özelleştirilemez.

  1. ( Android 11 QPR3, Android 11 Araba, Android 12 )
    app:defaultFocus odaklanılabilir bir alt görünümün kimliğini belirtmek için kullanılabilir; kullanıcı bu FocusArea öğesine dokunduğunda odaklanılması gerekir.
  2. ( Android 11 QPR3, Android 11 Araba, Android 12 )
    app:defaultFocusOverridesHistory bu FocusArea başka bir görünüme odaklanıldığını belirtmek için geçmişle birlikte yukarıda belirtilen görünümün odaklanmasını sağlamak için true olarak ayarlanabilir.
  3. ( Android 12 )
    Kullanıcı belirli bir yönde dürtüklendiğinde odaklanılması gereken odaklanılabilir alt görünümün kimliğini belirtmek için app:nudgeLeftShortcut , app:nudgeRightShortcut , app:nudgeUpShortcut ve app:nudgeDownShortcut öğelerini kullanın. Daha fazla bilgi edinmek için aşağıdaki dürtme kısayollarına ilişkin içeriğe bakın.

    ( Android 11 QPR3, Android 11 Car, Android 12'de kullanımdan kaldırıldı ) app:nudgeShortcut ve app:nudgeShortcutDirection yalnızca bir dürtme kısayolunu destekledi.

  4. ( Android 11 QPR3, Android 11 Araba, Android 12 )
    Bu FocusArea döndürmenin sarılmasını sağlamak için app:wrapAround true olarak ayarlanabilir. Bu genellikle görünümler daire veya oval şeklinde düzenlendiğinde kullanılır.
  5. ( Android 11 QPR3, Android 11 Araba, Android 12 )
    Bu FocusArea vurgunun dolgusunu ayarlamak için app:highlightPaddingStart , app:highlightPaddingEnd , app:highlightPaddingTop , app:highlightPaddingBottom , app:highlightPaddingHorizontal ve app:highlightPaddingVertical kullanın.
  6. ( Android 11 QPR3, Android 11 Araba, Android 12 )
    Bir itme hedefi bulmak amacıyla bu FocusArea algılanan sınırlarını ayarlamak için app:startBoundOffset , app:endBoundOffset , app:topBoundOffset , app:bottomBoundOffset , app:horizontalBoundOffset ve app:verticalBoundOffset kullanın.
  7. ( Android 11 QPR3, Android 11 Araba, Android 12 )
    Verilen yönlerde bitişik bir FocusArea (veya alanların) kimliğini açıkça belirtmek için app:nudgeLeft , app:nudgeRight , app:nudgeUp ve app:nudgeDown kullanın. Varsayılan olarak kullanılan geometrik arama istenen hedefi bulamadığında bunu kullanın.

Dürtme genellikle Odak Alanları arasında gezinir. Ancak dürtme kısayollarıyla, dürtme bazen ilk önce bir FocusArea içinde gezinir, böylece kullanıcının bir sonraki FocusArea gitmek için iki kez dürtme yapması gerekebilir. Aşağıdaki örnekte olduğu gibi, FocusArea uzun bir liste ve onu takip eden bir Kayan Eylem Düğmesi içerdiğinde, kaydırma kısayolları kullanışlıdır:

Kısayolu sürükle
Şekil 3. Sürükleme kısayolu

Dürtme kısayolu olmasaydı, kullanıcının FAB'a ulaşmak için tüm listeyi döndürmesi gerekecekti.

Odak vurgulama özelleştirmesi

Yukarıda belirtildiği gibi, RotaryService Android çerçevesinin mevcut görüş odağı konsepti üzerine kurulmuştur. Kullanıcı dönüp dürttüğünde, RotaryService odağı hareket ettirerek bir görünüme odaklanır ve diğerinin odağını kaldırır. Android'de bir görünüme odaklanıldığında görünüm:

  • Kendi odak vurgusunu belirlemiş olan Android, görünümün odak vurgusunu çizer.
  • Bir odak vurgusu belirtmez ve varsayılan odak vurgusu devre dışı bırakılmaz; Android, görünüm için varsayılan odak vurgusunu çizer.

Dokunma için tasarlanan uygulamalar genellikle uygun odak vurgularını belirtmez.

Varsayılan odak vurgusu Android çerçevesi tarafından sağlanır ve OEM tarafından geçersiz kılınabilir. Uygulama geliştiricileri, kullandıkları tema Theme.DeviceDefault öğesinden türetildiğinde bunu alır.

Tutarlı bir kullanıcı deneyimi için mümkün olduğunda varsayılan odak vurgusunu kullanın. Özel şekilli (örneğin, yuvarlak veya hap şeklinde) bir odak vurgulamasına ihtiyacınız varsa veya Theme.DeviceDefault öğesinden türetilmemiş bir tema kullanıyorsanız, kendi odak vurgunuzu belirlemek için car-ui-library kaynaklarını kullanın. her görünüm.

Bir görünüm için özel bir odak vurgusu belirlemek üzere, görünümün arka plan veya ön plan çizilebilirliğini, görünüme odaklanıldığında farklılık gösteren bir çizilebilir olarak değiştirin. Genellikle arka planı değiştirirsiniz. Aşağıdaki çizilebilir kare görünüm için arka plan olarak kullanıldığında yuvarlak odaklı bir vurgu oluşturur:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
   <item android:state_focused="true" android:state_pressed="true">
      <shape android:shape="oval">
         <solid android:color="@color/car_ui_rotary_focus_pressed_fill_color"/>
         <stroke
            android:width="@dimen/car_ui_rotary_focus_pressed_stroke_width"
            android:color="@color/car_ui_rotary_focus_pressed_stroke_color"/>
      </shape>
   </item>
   <item android:state_focused="true">
      <shape android:shape="oval">
         <solid android:color="@color/car_ui_rotary_focus_fill_color"/>
         <stroke
            android:width="@dimen/car_ui_rotary_focus_stroke_width"
            android:color="@color/car_ui_rotary_focus_stroke_color"/>
      </shape>
   </item>
   <item>
      <ripple...>
         ...
      </ripple>
   </item>
</selector>

( Android 11 QPR3, Android 11 Car, Android 12 ) Yukarıdaki örnekteki kalın kaynak referansları, car-ui-library tarafından tanımlanan kaynakları tanımlar. OEM, belirledikleri varsayılan odak vurgusuyla tutarlı olacak şekilde bunları geçersiz kılar. Bu, kullanıcı özel odak vurgusu olan bir görünüm ile varsayılan odak vurgusu olan bir görünüm arasında gezindiğinde odak vurgu renginin, kontur genişliğinin vb. değişmemesini sağlar. Son öğe dokunmak için kullanılan bir dalgalanmadır. Kalın kaynaklar için kullanılan varsayılan değerler aşağıdaki gibi görünür:

Kalın kaynaklar için varsayılan değerler
Şekil 4. Kalın kaynaklar için varsayılan değerler

Ek olarak, aşağıdaki örnekte olduğu gibi, bir düğmeye kullanıcının dikkatini çekmek için düz bir arka plan rengi verildiğinde, özel odak vurgulaması çağrılır. Bu, odak vurgusunun görülmesini zorlaştırabilir. Bu durumda ikincil renkleri kullanarak özel bir odak vurgusu belirtin:

Düz arka plan rengi
  • ( Android 11 QPR3, Android 11 Araba, Android 12 )
    car_ui_rotary_focus_fill_secondary_color
    car_ui_rotary_focus_stroke_secondary_color
  • ( Android 12 )
    car_ui_rotary_focus_pressed_fill_secondary_color
    car_ui_rotary_focus_pressed_stroke_secondary_color

Örneğin:

Odaklanmış, basılmamışOdaklanmış, basılmış
Odaklanmış, basılmamış Odaklanmış, basılmış

Döner kaydırma

Uygulamanız RecyclerView kullanıyorsa bunun yerine CarUiRecyclerView kullanmanız GEREKİR. Bu, bir OEM'in özelleştirmesinin tüm CarUiRecyclerView için geçerli olması nedeniyle kullanıcı arayüzünüzün diğerleriyle tutarlı olmasını sağlar.

Listenizdeki öğelerin tümü odaklanabiliyorsa başka bir şey yapmanıza gerek yoktur. Döner gezinme, odağı listedeki öğeler arasında hareket ettirir ve yeni odaklanılan öğeyi görünür hale getirmek için liste kaydırılır.

( Android 11 QPR3, Android 11 Araba, Android 12 )
Odaklanabilen ve odaklanamayan öğelerin bir karışımı varsa veya tüm öğeler odaklanılamazsa, döner kaydırmayı etkinleştirebilirsiniz; bu, kullanıcının döner denetleyiciyi kullanarak odaklanamayan öğeleri atlamadan listede kademeli olarak ilerlemesine olanak tanır. Döner kaydırmayı etkinleştirmek için app:rotaryScrollEnabled niteliğini true olarak ayarlayın.

( Android 11 QPR3, Android 11 Araba, Android 12 )
CarUiUtils setRotaryScrollEnabled() yöntemiyle, av CarUiRecyclerView dahil herhangi bir kaydırılabilir görünümde döner kaydırmayı etkinleştirebilirsiniz. Bunu yaparsanız şunları yapmanız gerekir:

  • Odaklanabilir alt görünümlerinden hiçbiri görünür olmadığında odaklanılabilmesi için kaydırılabilir görünümü odaklanabilir hale getirin,
  • Kaydırılabilir görünümün odaklanmış gibi görünmemesi için setDefaultFocusHighlightEnabled(false) öğesini çağırarak kaydırılabilir görünümdeki varsayılan odak vurgusunu devre dışı bırakın,
  • setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS) çağrılarak kaydırılabilir görünümün alt öğelerinden önce odaklanıldığından emin olun.
  • Kaydırılacak mesafeyi ve yönü (işaret boyunca) belirtmek için SOURCE_ROTARY_ENCODER ve AXIS_VSCROLL veya AXIS_HSCROLL ile MotionEvents'i dinleyin.

CarUiRecyclerView döner kaydırma etkinleştirildiğinde ve kullanıcı odaklanılabilir görünümlerin bulunmadığı bir alana döndüğünde, kaydırma çubuğu sanki kaydırma çubuğunun odaklandığını belirtmek istercesine griden maviye döner. İsterseniz benzer bir etki uygulayabilirsiniz.

MotionEvent'ler, kaynak haricinde fare üzerindeki kaydırma tekerleği tarafından oluşturulanlarla aynıdır.

Doğrudan manipülasyon modu

Normalde, dürtmeler ve döndürme kullanıcı arayüzünde gezinirken, Orta düğmeye basıldığında harekete geçilir, ancak bu her zaman böyle değildir. Örneğin, bir kullanıcı alarm ses düzeyini ayarlamak isterse, ses düzeyi kaydırıcısına gitmek için döner denetleyiciyi kullanabilir, Orta düğmeye basabilir, alarm ses düzeyini ayarlamak için denetleyiciyi döndürebilir ve ardından navigasyona geri dönmek için Geri düğmesine basabilir. . Buna doğrudan manipülasyon (DM) modu denir. Bu modda, döner denetleyici gezinmek yerine doğrudan görünümle etkileşimde bulunmak için kullanılır.

DM'yi iki yoldan biriyle uygulayın. Yalnızca döndürme işlemini gerçekleştirmeniz gerekiyorsa ve değiştirmek istediğiniz görünüm ACTION_SCROLL_FORWARD ve ACTION_SCROLL_BACKWARD AccessibilityEvent öğelerine uygun şekilde yanıt veriyorsa, basit mekanizmayı kullanın. Aksi takdirde gelişmiş mekanizmayı kullanın.

Basit mekanizma sistem pencerelerindeki tek seçenektir; uygulamalar her iki mekanizmayı da kullanabilir.

Basit mekanizma

( Android 11 QPR3, Android 11 Araba, Android 12 )
Uygulamanız DirectManipulationHelper.setSupportsRotateDirectly(View view, boolean enable) çağırmalıdır. RotaryService kullanıcının DM modunda olduğunu algılar ve kullanıcı bir görünüme odaklanmışken Ortadaki düğmeye bastığında DM moduna girer. DM modundayken, rotasyonlar ACTION_SCROLL_FORWARD veya ACTION_SCROLL_BACKWARD işlemini gerçekleştirir ve kullanıcı Geri düğmesine bastığında DM modundan çıkar. Basit mekanizma, DM moduna girerken ve çıkarken görünümün seçilen durumunu değiştirir.

Kullanıcının DM modunda olduğuna dair görsel bir ipucu sağlamak için görünümünüzün seçildiğinde farklı görünmesini sağlayın. Örneğin, android:state_selected true olduğunda arka planı değiştirin.

Gelişmiş mekanizma

Uygulama, RotaryService DM moduna ne zaman girip çıkacağını belirler. Tutarlı bir kullanıcı deneyimi için, DM görünümü odaklıyken Orta düğmeye basıldığında DM moduna girilmeli ve Geri düğmesi DM modundan çıkılmalıdır. Ortadaki düğme ve/veya itme kullanılmazsa, bunlar DM modundan çıkmanın alternatif yolları olabilir. Haritalar gibi uygulamalarda, DM moduna girmek için DM'yi temsil eden bir düğme kullanılabilir.

Gelişmiş DM modunu desteklemek için bir görünüm:

  1. ( Android 11 QPR3, Android 11 Car, Android 12 ) DM moduna girmek için bir KEYCODE_DPAD_CENTER olayını dinlemeli ve DM modundan çıkmak için bir KEYCODE_BACK olayını dinlemeli ve her durumda DirectManipulationHelper.enableDirectManipulationMode() öğesini çağırmalıdır. Bu etkinlikleri dinlemek için aşağıdakilerden birini yapın:
    • Bir OnKeyListener kaydedin.
    • veya,
    • Görünümü genişletin ve ardındandispatchKeyEvent dispatchKeyEvent() yöntemini geçersiz kılın.
  2. Görünümün dürtüklemeleri işlemesi gerekiyorsa, dürtme olaylarını ( KEYCODE_DPAD_UP , KEYCODE_DPAD_DOWN , KEYCODE_DPAD_LEFT veya KEYCODE_DPAD_RIGHT ) dinlemeniz GEREKİR.
  3. Görünüm rotasyonu işlemek istiyorsa, MotionEvent dinlemeli ve AXIS_SCROLL rotasyon sayısını almalıdır. Bunu yapmanın birkaç yolu vardır:
    1. Bir OnGenericMotionListener kaydedin.
    2. Görünümü genişletin ve dispatchTouchEvent() yöntemini geçersiz kılın.
  4. DM modunda kalmayı önlemek için, görünümün ait olduğu Parça veya Etkinlik etkileşimli olmadığında DM modundan çıkılmalıdır.
  5. Görünümün DM modunda olduğunu belirten görsel bir ipucu sağlamalıdır.

Bir haritayı kaydırmak ve yakınlaştırmak için DM modunu kullanan özel görünümün bir örneği aşağıda verilmiştir:

/** Whether this view is in DM mode. */
private boolean mInDirectManipulationMode;

/** Initializes the view. Called by the constructors. */ private void init() { setOnKeyListener((view, keyCode, keyEvent) -> { boolean isActionUp = keyEvent.getAction() == KeyEvent.ACTION_UP; switch (keyCode) { // Always consume KEYCODE_DPAD_CENTER and KEYCODE_BACK events. case KeyEvent.KEYCODE_DPAD_CENTER: if (!mInDirectManipulationMode && isActionUp) { mInDirectManipulationMode = true; DirectManipulationHelper.enableDirectManipulationMode(this, true); setSelected(true); // visually indicate DM mode } return true; case KeyEvent.KEYCODE_BACK: if (mInDirectManipulationMode && isActionUp) { mInDirectManipulationMode = false; DirectManipulationHelper.enableDirectManipulationMode(this, false); setSelected(false); } return true; // Consume controller nudge events only when in DM mode. // When in DM mode, nudges pan the map. case KeyEvent.KEYCODE_DPAD_UP: if (!mInDirectManipulationMode) return false; if (isActionUp) pan(0f, -10f); return true; case KeyEvent.KEYCODE_DPAD_DOWN: if (!mInDirectManipulationMode) return false; if (isActionUp) pan(0f, 10f); return true; case KeyEvent.KEYCODE_DPAD_LEFT: if (!mInDirectManipulationMode) return false; if (isActionUp) pan(-10f, 0f); return true; case KeyEvent.KEYCODE_DPAD_RIGHT: if (!mInDirectManipulationMode) return false; if (isActionUp) pan(10f, 0f); return true; // Don't consume other key events. default: return false; } });
// When in DM mode, rotation zooms the map. setOnGenericMotionListener(((view, motionEvent) -> { if (!mInDirectManipulationMode) return false; float scroll = motionEvent.getAxisValue(MotionEvent.AXIS_SCROLL); zoom(10 * scroll); return true; })); }
@Override public void onPause() { if (mInDirectManipulationMode) { // To ensure that the user doesn't get stuck in DM mode, disable DM mode // when the fragment is not interactive (e.g., a dialog shows up). mInDirectManipulationMode = false; DirectManipulationHelper.enableDirectManipulationMode(this, false); } super.onPause(); }

Daha fazla örneği RotaryPlayground projesinde bulabilirsiniz.

Etkinlik Görünümü

ActivityView kullanırken:

  • ActivityView odaklanabilir olmamalıdır.
  • ( Android 11 QPR3, Android 11 Araba, Android 11'de kullanımdan kaldırıldı )
    ActivityView içeriğinin ilk odaklanılabilir görünüm olarak bir FocusParkingView içermesi ZORUNLU ve app:shouldRestoreFocus niteliğinin false olması ZORUNLUDUR.
  • ActivityView içeriğinde android:focusByDefault görünümü olmamalıdır.

Kullanıcı açısından, ActivityView'lerin, odak alanlarının ActivityView'leri kapsayamaması dışında gezinme üzerinde hiçbir etkisi olmamalıdır. Başka bir deyişle, ActivityView içinde ve dışında içeriğe sahip tek bir odak alanınız olamaz. ActivityView öğenize herhangi bir FocusAreas eklemezseniz ActivityView içindeki görünüm hiyerarşisinin kökü örtülü bir odak alanı olarak kabul edilir.

Basılı tutulduğunda çalışan düğmeler

Çoğu düğme, tıklandığında bazı eylemlere neden olur. Bunun yerine bazı düğmeler basılı tutulduğunda çalışır. Örneğin, Hızlı İleri ve Geri Sarma düğmeleri genellikle basılı tutulduğunda çalışır. Bu tür düğmelerin döner desteği desteklemesi için KEYCODE_DPAD_CENTER KeyEvents aşağıdaki gibi dinleyin:

mButton.setOnKeyListener((v, keyCode, event) ->
{
    if (keyCode != KEYCODE_DPAD_CENTER) {
        return false;
    }
    if (event.getAction() == ACTION_DOWN) {
        mButton.setPressed(true);
        mHandler.post(mRunnable);
    } else {
        mButton.setPressed(false);
        mHandler.removeCallbacks(mRunnable);
    }
    return true;
});

mRunnable bir eylem (geri sarma gibi) gerçekleştirdiği ve kendisini bir gecikmeden sonra çalıştırılacak şekilde programladığı.

Dokunma modu

Kullanıcılar, bir arabadaki ana üniteyle iki şekilde etkileşim kurmak için döner denetleyiciyi kullanabilir; döner denetleyiciyi kullanarak veya ekrana dokunarak. Döner denetleyiciyi kullanırken odaklanılabilir görünümlerden biri vurgulanır. Ekrana dokunduğunuzda odak vurgusu görünmüyor. Kullanıcı istediği zaman bu giriş modları arasında geçiş yapabilir:

  • Döndürme → dokunma. Kullanıcı ekrana dokunduğunda odak vurgusu kaybolur.
  • → Döndür öğesine dokunun. Kullanıcı Ortadaki düğmeyi ittiğinde, döndürdüğünde veya bastığında odak vurgusu görünür.

Geri ve Ana Sayfa düğmelerinin giriş modu üzerinde hiçbir etkisi yoktur.

Android'in mevcut dokunmatik mod konseptinde döner bindirmeler. Kullanıcının hangi giriş modunu kullandığını belirlemek için View.isInTouchMode() kullanabilirsiniz. Değişiklikleri dinlemek için OnTouchModeChangeListener kullanabilirsiniz. Bu, kullanıcı arayüzünüzü mevcut giriş moduna göre özelleştirmek için kullanılabilse de, endişe verici olabileceğinden büyük değişikliklerden kaçının.

Sorun giderme

Dokunma için tasarlanmış bir uygulamada, iç içe odaklanabilen görünümlerin olması yaygındır. Örneğin, her ikisi de odaklanabilen ImageButton çevresinde FrameLayout olabilir. Bu, dokunmaya zarar vermez ancak kullanıcının bir sonraki etkileşimli görünüme geçmek için kontrol cihazını iki kez döndürmesi gerektiğinden dönerek kullanıcı deneyiminin kötü olmasına neden olabilir. İyi bir kullanıcı deneyimi için Google, dış görünümü veya iç görünümü odaklanabilir hale getirmenizi, ancak ikisini birden yapmamanızı önerir.

Döner denetleyici aracılığıyla basıldığında bir düğme veya anahtar odağı kaybederse aşağıdaki koşullardan biri geçerli olabilir:

  • Düğmeye basılması nedeniyle düğme veya anahtar (kısa süreli veya süresiz olarak) devre dışı bırakılıyor. Her iki durumda da bu sorunu çözmenin iki yolu vardır:
    • android:enabled durumunu true olarak bırakın ve düğmeyi grileştirmek veya Özel Durum bölümünde açıklandığı gibi geçiş yapmak için özel bir durum kullanın.
    • Düğmeyi veya anahtarı çevrelemek için bir kapsayıcı kullanın ve kapsayıcıyı düğme veya anahtar yerine odaklanabilir hale getirin. (Tıklama dinleyicisi kapsayıcıda olmalıdır.)
  • Düğme veya anahtar değiştiriliyor. Örneğin, düğmeye basıldığında veya anahtar değiştirildiğinde gerçekleştirilen eylem, mevcut eylemlerin yenilenmesini tetikleyerek yeni düğmelerin mevcut düğmelerin yerini almasına neden olabilir. Bu sorunu çözmenin iki yolu vardır:
    • Yeni bir düğme veya anahtar oluşturmak yerine mevcut düğmenin veya anahtarın simgesini ve/veya metnini ayarlayın.
    • Yukarıdaki gibi düğmenin veya anahtarın etrafına odaklanabilir bir kapsayıcı ekleyin.

DönerOyun Alanı

RotaryPlayground , rotary için bir referans uygulamasıdır. Döner özellikleri uygulamalarınıza nasıl entegre edeceğinizi öğrenmek için bunu kullanın. RotaryPlayground emülatör yapılarında ve Android Automotive OS (AAOS) çalıştıran cihazlara yönelik yapılarda bulunur.

  • RotaryPlayground deposu: packages/apps/Car/tests/RotaryPlayground/
  • Sürümler: Android 11 QPR3, Android 11 Car ve Android 12

RotaryPlayground uygulaması sol tarafta aşağıdaki sekmeleri gösterir:

  • Kartlar. Odaklanamayan öğeleri ve metin girişini atlayarak odak alanlarında gezinmeyi deneyin.
  • Doğrudan manipülasyon. Basit ve gelişmiş doğrudan manipülasyon modunu destekleyen widget'ları test edin. Bu sekme özellikle uygulama penceresinde doğrudan değişiklik yapmak içindir.
  • Sistem Kullanıcı Arayüzü Manipülasyonu. Yalnızca basit doğrudan manipülasyon modunun desteklendiği sistem pencerelerinde doğrudan manipülasyonu destekleyen test widget'ları.
  • Kafes. Kaydırma ile z-modeli döner gezinmeyi test edin.
  • Bildiri. Dikkat bildirimlerine girip çıkmayı test edin.
  • Taslak. Odaklanabilir ve odaklanamayan içeriklerin bir karışımını kaydırmayı test edin.
  • Web Görünümü. Bir WebView bağlantılar arasında gezinmeyi test edin.
  • Özel FocusArea . FocusArea özelleştirmesini test edin:
    • Etrafına sarmak.
    • android:focusedByDefault ve app:defaultFocus
    • .
    • Açık dürtme hedefleri.
    • Kısayolları sürükleyin.
    • Odaklanabilir görünümlerin olmadığı FocusArea .