Uygulama Geliştirme

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

Uygulama desteğinizi döner hale getirmek için şunları YAPMALISINIZ:

  1. Bir koyun FocusParkingView ilgili etkinlik düzeninde.
  2. Odaklanabilir olan (veya olmayan) görünümlerden emin olun.
  3. Kullanım FocusArea ler hariç tüm odaklanabilir görünümleri, etrafına sarmak için FocusParkingView .

Döner özellikli uygulamalar geliştirmek için ortamınızı ayarladıktan sonra, bu görevlerin her biri aşağıda ayrıntılı olarak açıklanmıştır.

Döner bir kontrolör kurun

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

öykünücü

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

Ayrıca kullanabilirsiniz aosp_car_x86_64-userdebug .

Öykünülmüş döner denetleyiciye erişmek için:

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

    Öykünülmüş döner denetleyiciye erişim
    Şekil 1. Erişim döner düğmeyi taklit
  2. Genişletilmiş kontroller penceresinde Araç döner seçin:

    Araba döner seçin
    Şekil 2. Araç döner

USB Klavye

  • Seahawk'ınıza bir USB klavye takın (bazı durumlarda bu, ekran klavyesinin görünmesini engelleyebilir).
  • Bir kullan userdebug veya eng yapı.
  • 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
    NS Sağa sürükle
    W yukarı itmek
    S Aşağı itmek
    F veya Virgül orta düğme
    R veya Esc Geri düğmesi

ADB komutları

Sen kullanabilirsiniz car_service döner giriş işlemlerini enjekte etmek komutları. Bu komutlar bir Seahawk veya bir öykünücü üzerinde ç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 Saat yönünün tersine birkaç kez döndürün (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ı itmek
adb shell cmd car_service inject-key 281 Aşağı itmek
adb shell cmd car_service inject-key 23 Orta düğme tıklaması
adb shell input keyevent inject-key 4 Geri düğmesi tıklaması

OEM döner kontrolör

Döner denetleyici donanımınız hazır ve çalışır durumdayken, bu en gerçekçi seçenektir. Özellikle hızlı dönüşü test etmek için kullanışlıdır.

OdakPark Görünümü

FocusParkingView saydam görünümüdür Araç UI Library (araba-ui-kütüphane) . RotaryService döner denetleyici navigasyon desteklemek için kullanır. FocusParkingView düzeninde ilk odaklanabilir görünümü olmalıdır. Her şey dışında yerleştirilmelidir FocusArea s. Her pencere bir olması gerekir FocusParkingView . Zaten bir içeriyor araba ui-kitaplığı temel düzenini kullanıyorsanız FocusParkingView , başka eklemek gerekmez FocusParkingView . Bir örnek aşağıda gösterilmektedir FocusParkingView içinde RotaryPlayground .

<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>

Burada bir ihtiyaç nedenleri şunlardır FocusParkingView :

  1. Odak başka bir pencerede ayarlandığında Android odağı otomatik olarak temizlemez. Önceki pencerede odağı temizlemeye çalışırsanız, Android o penceredeki bir görünüme yeniden odaklanır ve bu, aynı anda iki pencereye odaklanmaya neden olur. Bir ekleme FocusParkingView her pencere için bu sorunu çözebilirsiniz. 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ünmez. Böylece odak alabilir RotaryService odak vurguyu silmek için üzerine odağı park edebilirsiniz.
  2. Sadece bir tane ise FocusArea kontrolörü döner geçerli pencerede, FocusArea neden RotaryService sol (ve tersi) ile görünüme sağdaki görünümden odağı taşımak için. Bu görünümü her pencereye eklemek sorunu çözebilir. Ne zaman RotaryService odak hedefi olduğunu belirleyen FocusParkingView , bir-etrafında sarma, aynı tarihte odağı hareket etmeyerek etrafı sarılan önler işaret oluşmak üzeredir belirleyebilir.
  3. Döner kontrol başlattı bir uygulama, Android her zaman ilk odaklanabilir görünümü, odaklanır zaman FocusParkingView . FocusParkingView odaklanmak için en uygun görünümü belirler ve sonra odağı uygular.

Odaklanabilir görünümler

RotaryService Android çerçevenin üzerine inşa mevcut telefonlar fiziksel klavyeler ve D-yastıkları vardı ne zaman geri kalma, görünüm odak kavramı. Varolan android:nextFocusForward özniteliği (bkz döner amacıyla değiştirdikleri edilir FocusArea özelleştirme ), ancak android:nextFocusLeft , android:nextFocusRight , android:nextFocusUp ve android:nextFocusDown değildir.

RotaryService sadece odaklanabilir görünümleri üzerine odaklanmaktadır. Gibi bazı görünümler, Button s, genellikle odaklanabilir. Diğerleri gibi TextView s ve ViewGroup s, genellikle değildir. Tıklanabilir görünümler otomatik olarak odaklanabilir ve tıklama dinleyicileri olduğunda görünümler otomatik olarak tıklanabilir. Bu otomatik mantık istenen odaklanabilirliği sağlıyorsa, görünümün odaklanabilirliğini açıkça ayarlamanız gerekmez. Otomatik mantık istenen focusability neden yoksa, set android:focusable için niteliğini true veya false ile, veya programlı set görünümün focusability View.setFocusable(boolean) . For RotaryService Üzerinde durulması, bir görünüm aşağıdaki gereksinimleri karşılaması gerekir:

  • Odaklanabilir
  • Etkinleştirilmiş
  • Gözle görülü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ı buna odaklanmak için döner kontrolü kullanamaz. Eğer engelli görünümlerinde odağı istiyorsanız, yerine özel bir durumu kullanmayı düşünün android:state_enabled denetime bakış Android devre dışı düşünmelisiniz belirten olmadan nasıl göründüğü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. Bir eklemek için özel özellik görünümünüze. Örneğin, bir ekleme state_rotary_enabled özel durumunu CustomView : Görünüm sınıfı, kullanım
    <declare-styleable name="CustomView">
        <attr name="state_rotary_enabled" format="boolean" />
    </declare-styleable>
    
  2. Bu durumu izlemek için, erişimci yöntemleri ile birlikte görünümünüze 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 senin özelliğin 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ünüzü sınıfında, geçersiz onCreateDrawableState() yöntemini ve sonra özel zaman devlet, uygun 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 olabilir veya ne zaman bir tost açılır olabilir mRotaryEnabled olduğu false .
  6. Düğmesi görünümün arka plan çekilebilir içinde, özürlü görünmesini sağlamak için, kullanım app:state_rotary_enabled yerine android:state_enabled . Zaten yoksa, eklemek gerekir:
    xmlns:app="http://schemas.android.com/apk/res-auto"
    
  7. Görünümünüzü herhangi düzenleri devre dışı bırakılmışsa, yerine android:enabled="false" ile app:state_rotary_enabled="false" ve ardından eklemek app yukarıdaki gibi, ad.
  8. Görüşünüz programlı devre dışı ise, çağrı yerine setEnabled() çağrıları ile setRotaryEnabled() .

Odak Alanı

Kullanım FocusAreas daha kolay gezinme yapmak ve diğer uygulamalarla tutarlı olması için bloklar halinde odaklanabilir görüşlerini bölme. Uygulamanız bir araç çubuğu varsa Örneğin, araç çubuğu ayrı olmalıdır FocusArea uygulamanızın geri kalanından. Sekme çubukları ve diğer gezinme öğeleri de uygulamanın geri kalanından ayrılmalıdır. Büyük listeleri genellikle kendi sahip olmalıdır FocusArea . Değilse, kullanıcıların bazı görünümlere erişmek için tüm listeyi döndürmesi gerekir.

FocusArea bir alt sınıfıdır LinearLayout araba ui-kütüphanede. Bu özellik etkinleştirildiğinde, bir FocusArea onun soyundan biri odaklandığında vurgulamak çekecektir. Daha fazla bilgi için bkz Odak vurgulamak özelleştirme .

Bir kullanmayı düşünüyorsanız, düzen dosyasında bir navigasyon bloğu oluştururken LinearLayout bu blok için bir kap gibi bir kullanma FocusArea yerine. Aksi takdirde, bir de blok sarın FocusArea .

İç içe bir yapın FocusArea başka FocusArea . Bunu yapmak, tanımsız gezinme davranışına yol açacaktır. Tüm odaklanabilir görünümleri içinde yuvalanmış emin olun FocusArea .

Bir örnek olarak FocusArea içinde RotaryPlayground aşağıda gösterilmiştir:

<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 şöyle çalışır:

  1. Döndürme taşıma ve eylemler dürtmek zaman RotaryService örnekleri arar FocusArea görünümü hiyerarşisinde.
  2. Bir rotasyon olayı alırken, RotaryService hamle aynı odağı alabilir başka View odak FocusArea .
  3. Bir dürtme etkinliği, alırken RotaryService bir (tipik olarak bitişik) odak sunar Başka bir görünüme hareket odak FocusArea .

Eğer herhangi bir dahil etmezseniz FocusAreas mizanpajınızda kök görünümü örtük bir odak alanı olarak kabul edilir. Kullanıcı, uygulamada gezinmek için dürtemez. Bunun yerine, diyaloglar için yeterli olabilecek tüm odaklanabilir görünümler arasında döneceklerdir.

FocusArea özelleştirmesi

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

  • android:nextFocusForward uygulama geliştiricilerinin Odak alanında rotasyon sırasını belirlemenizi sağlar. Bu, klavye gezintisi 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, kullanım app:wrapAround (aşağıya bakınız) bir döngü oluşturmak için.
  • android:focusedByDefault uygulama geliştiricilerinin penceresindeki varsayılan odak görünümü belirlemenizi sağlar. Bu özellik ve KULLANMAYIN app:defaultFocus (aşağıya bakınız) aynı yer FocusArea .

FocusArea ayrıca bazı döner navigasyon özelleştirmek niteliklerini tanımlar. Örtülü odak alanları bu niteliklerle özelleştirilemez.

  1. (Android 11 QPR3, Android 11 Araba, Android 12)
    app:defaultFocus odaklanmalıdır bir odaklanabilir soyundan bakış kimliğini belirtmek için kullanılır bu kullanıcı dürtmeler FocusArea .
  2. (Android 11 QPR3, Android 11 Araba, Android 12)
    app:defaultFocusOverridesHistory ayarlanabilir true bile bu başka görünümü göstermek için tarihi ile eğer almak odak yukarıda belirtilen görünümü yapmak FocusArea odaklanmış edilmişti.
  3. (Android 12)
    Kullanım app:nudgeLeftShortcut , app:nudgeRightShortcut , app:nudgeUpShortcut ve app:nudgeDownShortcut odaklanmalıdır bir odaklanabilir soyundan bakış kimliğini belirtmek için zaman belirli bir yönde kullanıcı dürtmeler. Daha fazla bilgi edinmek için, içeriği görmek dürtme kısayolları aşağıda.

    (Android 11 Android 12'de kaldırılmış QPR3, Android 11 Araba,) app:nudgeShortcut ve app:nudgeShortcutDirection tek dürtme kısayol destekledi.

  4. (Android 11 QPR3, Android 11 Araba, Android 12)
    Bu etrafında sarmak için rotasyon etkinleştirmek için FocusArea , app:wrapAround ayarlanabilir true . Bu genellikle görünümler bir daire veya oval olarak düzenlendiğinde kullanılır.
  5. (Android 11 QPR3, Android 11 Araba, Android 12)
    Bu vurgunun dolgu ayarlamak için FocusArea , kullanım app:highlightPaddingStart , app:highlightPaddingEnd , app:highlightPaddingTop , app:highlightPaddingBottom , app:highlightPaddingHorizontal ve app:highlightPaddingVertical .
  6. (Android 11 QPR3, Android 11 Araba, Android 12)
    Bu algılanan sınırları ayarlamak için FocusArea bir dürtme hedef, kullanımı bulmak için app:startBoundOffset , app:endBoundOffset , app:topBoundOffset , app:bottomBoundOffset , app:horizontalBoundOffset ve app:verticalBoundOffset .
  7. (Android 11 QPR3, Android 11 Araba, Android 12)
    Açık bir şekilde, bitişik kimliğini belirtmek için FocusArea verilen yönde, kullanım içinde (ya da alanları) app:nudgeLeft , app:nudgeRight , app:nudgeUp ve app:nudgeDown . Varsayılan olarak kullanılan geometrik arama istenen hedefi bulamadığında bunu kullanın.

Dürtme genellikle FocusAreas arasında gezinir. Ama içinde bazen ilk Navigates'ten itelenirken dürtme kısayolları ile FocusArea kullanıcı daha gitmesini iki kez dürtmek gerekebilir böylece FocusArea . Bir zaman kısayollar yararlıdır Nudge FocusArea bir takip eden uzun bir listesini içerir Yüzer Eylem Düğmesi Örneğin aşağıda olduğu gibi:

Kısayolu sürükle
Şekil 3. Sıkışma kısayol

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

Odak vurgulama özelleştirmesi

Yukarıda belirtildiği gibi, RotaryService görünümü odak Android çerçevenin mevcut konsepti üzerine inşa. Ne zaman kullanıcı döndüğü ve dürtmeler, RotaryService bir görünüm odaklama ve başka unfocusing, odak etrafta hareket eder. Android'de, bir görünüme odaklanıldığında, görünüm:

  • kendi odak vurgusunu belirledi, Android görünümün odak vurgusunu çiziyor.
  • 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 tasarlanmış 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. Kullandıkları tema türetilmiştir zaman Uygulama geliştiricileri bunu almak Theme.DeviceDefault .

Tutarlı bir kullanıcı deneyimi için, mümkün olduğunda varsayılan odak vurgusuna güvenin. Eğer türetilmiş bir tema kullanıyorsanız bir özel şekilli (örneğin, yuvarlak veya hap şeklinde) odak vurgu gerekiyorsa veya Theme.DeviceDefault , için kendi odak vurgu belirtmek için kaynaklar araba ui-kütüphane kullanma her görünüm.

Bir görünüm için özel bir odak vurgusu belirtmek için, görünümün çizilebilir arka planını veya ön planını, görünüme odaklanıldığında farklılık gösteren bir çizilebilir olarak değiştirin. Tipik olarak, arka planı değiştirirsiniz. Aşağıdaki çizilebilir, kare bir görünüm için arka plan olarak kullanılırsa, yuvarlak bir odak vurgusu üretir:

<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 Araba, Android 12) numunede Kalın kaynak referansları yukarıdaki araba ui-kütüphaneye tarafından tanımlanan kaynakları belirlemek. OEM, belirttikleri varsayılan odak vurgusu ile tutarlı olması için bunları geçersiz kılar. Bu, kullanıcı özel odak vurgulu bir görünüm ile varsayılan odak vurgulu bir görünüm arasında gezinirken odak vurgu renginin, kontur genişliğinin vb. değişmemesini sağlar. Son öğe, dokunma 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
Cesur kaynaklar için Şekil 4. varsayılan değerler

Ek olarak, aşağıdaki örnekte olduğu gibi, bir düğmeye kullanıcının dikkatine sunmak için düz bir arka plan rengi verildiğinde özel bir odak vurgusu çağrılır. Bu, odak vurgusunun görülmesini zorlaştırabilir. Bu durumda, ikincil renkler kullanarak özel odak vurgu 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 kullanıyorsa RecyclerView ler, kullanmak GEREKEN CarUiRecyclerView yerine s. Bir OEM özelleştirme herkes için geçerlidir, çünkü UI başkaları ile tutarlı Bu olmasını sağlar CarUiRecyclerView s.

Listenizdeki öğelerin tümü odaklanabilirse, 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 kılmak 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 odaklanamıyorsa, döner kaydırmayı etkinleştirebilirsiniz; bu, kullanıcının döner denetleyiciyi kullanarak odaklanamayan öğeleri atlamadan listede kademeli olarak kaydırmasını sağlar. Döner kaydırmayı etkinleştirmek için set app:rotaryScrollEnabled için niteliğini true .

(Android 11 QPR3, Android 11 Araba, Android 12)
AV de dahil olmak üzere herhangi bir kaydırılabilir görünümde döner kaydırmayı etkinleştirebilir CarUiRecyclerView ile setRotaryScrollEnabled() yöntemin CarUiUtils . Bunu yaparsanız, yapmanız gerekenler:

  • Kaydırılabilir görünümü, odaklanabilir alt görünümlerinin hiçbiri görünür olmadığında odaklanabilmesi için odaklanabilir yapın,
  • Arayarak kaydırılabilir görünümünde varsayılan odak vurgu devre dışı bırakın setDefaultFocusHighlightEnabled(false) öylesine kaydırılabilir görünümü odaklı olmak görünmüyor,
  • Kaydırılabilir görünüm arayarak onun neslinden önce odaklanmış olduğundan emin olun setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS) .
  • İle MotionEvents dinleyin SOURCE_ROTARY_ENCODER ve ya AXIS_VSCROLL veya AXIS_HSCROLL kaydırmak için mesafe ve (iğaretiyle) yönünü gösterir.

Döner kaydırma bir etkinleştirildiğinde CarUiRecyclerView ve hiçbir odaklanabilir görünümleri bulunduğu bir alanda kullanıcı döndükçe kaydırma çubuğu odaklanmıştır göstermek için sanki kaydırma, mavi griden değiştirir. İsterseniz benzer bir efekt uygulayabilirsiniz.

MotionEvent'ler, kaynak dışında faredeki 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, ortadaki düğmeye basıldığında işlem yapılır, 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, ortadaki düğmeye basabilir, alarm ses düzeyini ayarlamak için denetleyiciyi döndürebilir ve ardından navigasyona dönmek için Geri düğmesine basabilir. . Bu doğrudan değiştirme (DM) modu olarak anılır. Bu modda, döner kontrolör gezinmek yerine doğrudan görünümle etkileşim kurmak için kullanılır.

DM'yi iki yoldan biriyle uygulayın. Yalnızca kol dönüş ve cevap vermekte işlemek istediğiniz görünüme gerekiyorsa ACTION_SCROLL_FORWARD ve ACTION_SCROLL_BACKWARD AccessibilityEvent uygun lar, basit mekanizma kullanır. Aksi takdirde, gelişmiş mekanizma kullanır.

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

Basit mekanizma

(Android 11 QPR3, Android 11 Araba, Android 12)
Uygulamanız çağırmalıdır DirectManipulationHelper.setSupportsRotateDirectly(View view, boolean enable) . RotaryService kullanıcı DM modunda olduğunu ve bir görünümü odaklanmış durumdayken kullanıcı Merkezi düğmesine bastığında DM moduna girdiğinde tanır. DM modunda, rotasyonlar gerçekleştirdiğinizde ACTION_SCROLL_FORWARD veya ACTION_SCROLL_BACKWARD ve çıkışlar DM modu kullanıcı Geri düğmesine bastığında. Basit mekanizma, DM moduna girerken ve çıkarken görünümün seçili durumunu değiştirir.

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

Gelişmiş mekanizma

Olduğunda, uygulama belirler RotaryService girer ve çıkar modu DM. Tutarlı bir kullanıcı deneyimi için, DM görünümü odaklıyken Ortadaki düğmeye basmak, DM moduna girmeli ve Geri düğmesi DM modundan çıkmalıdır. Ortadaki düğme ve/veya dürtme 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 Araba, Android 12) bir dinler GEREKİR KEYCODE_DPAD_CENTER DM moduna girmek ve dinlemek için olayı KEYCODE_BACK çağırarak, çıkış DM moduna olay DirectManipulationHelper.enableDirectManipulationMode() her durumda. Bu olayları dinlemek için aşağıdakilerden birini yapın:
    • Bir Kayıt OnKeyListener .
    • veya,
    • Bunu geçersiz sonra görünümü genişletmek ve dispatchKeyEvent() metodu.
  2. Dürtme olaylarını dinlemek OLMALIDIR ( KEYCODE_DPAD_UP , KEYCODE_DPAD_DOWN , KEYCODE_DPAD_LEFT veya KEYCODE_DPAD_RIGHT ) görünüm nudges işlemek gerekiyorsa.
  3. Dinlemek GEREKEN MotionEvent ler ve rotasyon sayısı elde AXIS_SCROLL görünümü kol dönüş istiyorsa. Bunu yapmanın birkaç yolu vardır:
    1. Bir Kayıt OnGenericMotionListener .
    2. Görünümünü genişletmek ve geçersiz dispatchTouchEvent() metodu.
  4. DM modunda takılıp kalmamak için, görünümün ait olduğu Fragment veya Activity etkileşimli olmadığında DM modundan çıkılmalıdır.
  5. Görünümün DM modunda olduğunu belirtmek için görsel bir ipucu SAĞLAMALIDIR.

Bir haritayı kaydırmak ve yakınlaştırmak için DM modunu kullanan bir özel görünüm ö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(); }

Diğer örnekler bulunabilir RotaryPlayground projesi.

Etkinlik Görünümü

ActivityView kullanırken:

  • ActivityView Odaklanabilir olmamalıdır.
  • (Android 11 QPR3, Android 11 Araba, Android 11'de kaldırıldı)
    İçerikleri ActivityView içermesi gerekir FocusParkingView ilk odaklanabilir görünüm olarak, ve app:shouldRestoreFocus özelliği OLMALIDIR false .
  • İçeriği ActivityView hiçbir olmalıdır android:focusByDefault görünümleri.

Kullanıcı için, ActivityView'lerin, odak alanlarının ActivityView'leri kapsayamaması dışında gezinme üzerinde hiçbir etkisi olmamalıdır. Başka bir deyişle, içerik iç ve dışında bir olan tek bir odak alanı olamaz ActivityView . Eğer herhangi FocusAreas eklemezseniz ActivityView , görünüm hiyerarşisinin kökü ActivityView örtük odak alanı olarak kabul edilir.

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

Çoğu düğme, tıklandığında bazı işlemlere neden olur. Bunun yerine basılı tutulduğunda bazı düğmeler çalışır. Örneğin, Hızlı İleri ve Geri Sar düğmeleri genellikle basılı tutulduğunda çalışır. Böyle düğmeler, döner desteklemesi için dinlemek yapmak için KEYCODE_DPAD_CENTER KeyEvents şöyle:

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;
});

Hangi mRunnable kendisi gecikmeden sonra çalıştırılacak bir (örneğin geri sarma gibi) işlem ve programları alır.

Dokunma modu

Kullanıcılar, bir arabadaki ana ünite ile etkileşim kurmak için döner kontrol cihazını kullanarak veya ekrana dokunarak iki şekilde bir döner kontrol cihazı kullanabilir. Döner denetleyiciyi kullanırken, odaklanabilir görünümlerden biri vurgulanacaktır. Ekrana dokunulduğunda odak vurgusu görünmez. Kullanıcı istediği zaman bu giriş modları arasında geçiş yapabilir:

  • Döner → dokunun. Kullanıcı ekrana dokunduğunda odak vurgusu kaybolur.
  • → döner seçeneğine dokunun. Kullanıcı dürttüğünde, döndürdüğünde veya ortadaki düğmeye bastığında odak vurgusu görünür.

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

Android'in mevcut kavramına Döner bindirimlerin dokunmatik modu . Sen kullanabilirsiniz View.isInTouchMode() Kullanıcının hangi giriş modu belirlemek için. Sen kullanabilirsiniz OnTouchModeChangeListener değişiklikleri işler için. Bu, kullanıcı arayüzünüzü mevcut giriş modu için özelleştirmek için kullanılabilse de, rahatsız edici olabilecekleri için büyük değişikliklerden kaçının.

Sorun giderme

Dokunma için tasarlanmış bir uygulamada, iç içe odaklanabilir görünümlere sahip olmak nadir değildir. Örneğin, bir olabilir FrameLayout bir yaklaşık ImageButton odaklanabilir, her ikisi de. 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öndürme için kötü bir kullanıcı deneyimine neden olabilir. Google, iyi bir kullanıcı deneyimi için dış görünümü veya iç görünümü odaklanabilir yapmanızı, ancak ikisini birden yapmamanızı önerir.

Döner kumanda ile basıldığında bir düğme veya anahtar odağı kaybederse, aşağıdaki koşullardan biri geçerli olabilir:

  • Düğmeye basıldığı için düğme veya anahtar (kısa veya süresiz olarak) devre dışı bırakılıyor. Her iki durumda da, bunu ele almanın iki yolu vardır:
    • Leave android:enabled olarak devlet true ve anlatıldığı gibi düğme veya anahtar grileştirebilir için özel bir durumu kullanmak Custom State .
    • Düğmeyi veya anahtarı çevrelemek için bir kap 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 tetikleyebilir ve yeni düğmelerin mevcut düğmelerin yerini almasına neden olabilir. Bunu ele almanın iki yolu vardır:
    • Yeni bir düğme veya anahtar oluşturmak yerine, mevcut düğme veya anahtarın simgesini ve/veya metnini ayarlayın.
    • Yukarıdaki gibi, düğmenin veya anahtarın etrafına odaklanabilir bir kap ekleyin.

DönerOyun Alanı

RotaryPlayground döner için bir referans app. Çeşitli döner özellikleri uygulamanıza nasıl entegre edeceğinizi öğrenmek için kullanın. RotaryPlayground emülatörü dahildir ve Seahawk inşa eder.

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

RotaryPlayground uygulaması gösterileri solda aşağıdaki sekmeleri:

  • Kartlar. Odaklanma alanlarında gezinmeyi, odaklanamayan öğeleri ve metin girişini atlamayı test edin.
  • 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 manipülasyon içindir.
  • Sys UI Manipülasyonu. Yalnızca basit doğrudan manipülasyon modunun desteklendiği sistem pencerelerinde doğrudan manipülasyonu destekleyen widget'ları test edin.
  • Kafes. Kaydırma ile z-desenli döner gezinmeyi test edin.
  • Bildirim. Uyarı bildirimlerini içeri ve dışarı yönlendirmeyi test edin.
  • Taslak. Odaklanabilen ve odaklanamayan bir içerik karışımında kaydırmayı test edin.
  • Web Görünümü. Bir de Bağlantılara Testi WebView .
  • Özel FocusArea . Deney FocusArea özelleştirme:
    • Etrafına sarmak.
    • android:focusedByDefault ve app:defaultFocus
    • .
    • Açık dürtme hedefleri.
    • Kısayolları sürükleyin.
    • FocusArea hiçbir odaklanabilir manzaralı.