Uygulamanızın kullanıma sunulmasını sağlayın

Katlanmamış büyük ekranlar ve katlanmış benzersiz durumlar, katlanabilir cihazlarda yeni kullanıcı deneyimleri yaşamanızı sağlar. Uygulamanızı katlama ve katlama özelliğiyle uyumlu hale getirmek için, katlama ve menteşe gibi katlanabilir cihaz penceresi özellikleri için bir API yüzeyi sağlayan Jetpack WindowManager kitaplığını kullanın. Uygulamanız katlama duyarlı olduğunda, önemli içeriklerin kıvrım veya menteşe alanına yerleştirilmesini önlemek ve doğal ayırıcılar olarak kıvrımlar ve menteşeler kullanmak için düzenini uyarlayabilir.

Pencere bilgileri

Jetpack WindowManager'daki WindowInfoTracker arayüzü, pencere düzeni bilgilerini gösterir. Arayüzün windowLayoutInfo() yöntemi, uygulamanızı katlanabilir cihazın katlama durumu hakkında bilgilendiren bir WindowLayoutInfo veri akışı döndürür. WindowInfoTracker getOrCreate() yöntemi, WindowInfoTracker örneği oluşturur.

WindowManager Kotlin Akışları ve Java geri çağırmalarını kullanarak WindowLayoutInfo verilerinin toplanması için destek sunar.

Kotlin Akışları

WindowLayoutInfo veri toplama işlemini başlatmak ve durdurmak için repeatOnLifecycle kod bloğunun yaşam döngüsü en az STARTED olduğunda yürütüldüğü ve yaşam döngüsü STOPPED olduğunda durdurulduğu yeniden başlatılabilir bir yaşam döngüsüne duyarlı eş çukur kullanabilirsiniz. Yaşam döngüsü STARTED tekrar olduğunda kod bloğunun yürütülmesi otomatik olarak yeniden başlatılır. Aşağıdaki örnekte kod bloğu, WindowLayoutInfo verilerini toplar ve kullanır:

class DisplayFeaturesActivity : AppCompatActivity() {

    private lateinit var binding: ActivityDisplayFeaturesBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityDisplayFeaturesBinding.inflate(layoutInflater)
        setContentView(binding.root)

        lifecycleScope.launch(Dispatchers.Main) {
            lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
                WindowInfoTracker.getOrCreate(this@DisplayFeaturesActivity)
                    .windowLayoutInfo(this@DisplayFeaturesActivity)
                    .collect { newLayoutInfo ->
                        // Use newLayoutInfo to update the layout.
                    }
            }
        }
    }
}

Java geri çağırmaları

androidx.window:window-java bağımlılığında yer alan geri çağırma uyumluluk katmanı, bir Kotlin Akışı kullanmadan WindowLayoutInfo güncellemelerini toplayabilmenizi sağlar. Yapı WindowInfoTrackerCallbackAdapter sınıfını içerir. Bu sınıf, WindowLayoutInfo güncellemelerini almak için geri çağırmaları (ve kaydını iptal etmeyi) desteklemek üzere bir WindowInfoTracker öğesini uyarlar. Örneğin:

public class SplitLayoutActivity extends AppCompatActivity {

    private WindowInfoTrackerCallbackAdapter windowInfoTracker;
    private ActivitySplitLayoutBinding binding;
    private final LayoutStateChangeCallback layoutStateChangeCallback =
            new LayoutStateChangeCallback();

   @Override
   protected void onCreate(@Nullable Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);

       binding = ActivitySplitLayoutBinding.inflate(getLayoutInflater());
       setContentView(binding.getRoot());

       windowInfoTracker =
                new WindowInfoTrackerCallbackAdapter(WindowInfoTracker.getOrCreate(this));
   }

   @Override
   protected void onStart() {
       super.onStart();
       windowInfoTracker.addWindowLayoutInfoListener(
                this, Runnable::run, layoutStateChangeCallback);
   }

   @Override
   protected void onStop() {
       super.onStop();
       windowInfoTracker
           .removeWindowLayoutInfoListener(layoutStateChangeCallback);
   }

   class LayoutStateChangeCallback implements Consumer<WindowLayoutInfo> {
       @Override
       public void accept(WindowLayoutInfo newLayoutInfo) {
           SplitLayoutActivity.this.runOnUiThread( () -> {
               // Use newLayoutInfo to update the layout.
           });
       }
   }
}

RxJava desteği

Zaten RxJava (sürüm 2 veya 3) kullanıyorsanız Kotlin Akışı kullanmadan WindowLayoutInfo güncellemesi toplamak için Observable veya Flowable kullanmanızı sağlayan yapılardan yararlanabilirsiniz.

androidx.window:window-rxjava2 ve androidx.window:window-rxjava3 bağımlılıkları tarafından sağlanan uyumluluk katmanı, uygulamanızın WindowLayoutInfo güncellemelerini almasını sağlayan WindowInfoTracker#windowLayoutInfoFlowable() ve WindowInfoTracker#windowLayoutInfoObservable() yöntemlerini içerir. Örneğin:

class RxActivity: AppCompatActivity {

    private lateinit var binding: ActivityRxBinding

    private var disposable: Disposable? = null
    private lateinit var observable: Observable<WindowLayoutInfo>

   @Override
   protected void onCreate(@Nullable Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);

       binding = ActivitySplitLayoutBinding.inflate(getLayoutInflater());
       setContentView(binding.getRoot());

        // Create a new observable
        observable = WindowInfoTracker.getOrCreate(this@RxActivity)
            .windowLayoutInfoObservable(this@RxActivity)
   }

   @Override
   protected void onStart() {
       super.onStart();

        // Subscribe to receive WindowLayoutInfo updates
        disposable?.dispose()
        disposable = observable
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe { newLayoutInfo ->
            // Use newLayoutInfo to update the layout
        }
   }

   @Override
   protected void onStop() {
       super.onStop();

        // Dispose the WindowLayoutInfo observable
        disposable?.dispose()
   }
}

Katlanabilir ekranların özellikleri

WindowLayoutInfo Jetpack WindowManager sınıfı, bir görüntüleme penceresinin özelliklerini DisplayFeature öğelerinden oluşan bir liste halinde sunar.

FoldingFeature, aşağıdakiler de dahil olmak üzere katlanabilir ekranlar hakkında bilgi sağlayan bir DisplayFeature türüdür:

  • state: Cihazın katlanmış durumu (FLAT veya HALF_OPENED)
  • orientation: Katlamanın veya menteşenin yönü, HORIZONTAL veya VERTICAL
  • occlusionType: Katlama veya menteşenin ekranın bir kısmını gizleyip gizlemediği NONE veya FULL
  • isSeparating: Katlamanın mı yoksa menteşenin mi iki mantıksal görüntüleme alanı oluşturup oluşturmayacağı (doğru veya yanlış)

HALF_OPENED olan katlanabilir bir cihaz, ekran iki görüntüleme alanına ayrıldığından her zaman isSeparating değerini "doğru" olarak bildirir. Ayrıca, çift ekranlı cihazlarda uygulama her iki ekrana da yayıldığında isSeparating her zaman doğrudur.

FoldingFeature bounds özelliği (DisplayFeature ürününden devralınır), katlama veya menteşe gibi bir katlama özelliğinin sınırlayıcı dikdörtgenini temsil eder. Sınırlar, ekrandaki öğeleri özelliğe göre konumlandırmak için kullanılabilir.

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    ...
    lifecycleScope.launch(Dispatchers.Main) {
        lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
            // Safely collects from windowInfoRepo when the lifecycle is STARTED
            // and stops collection when the lifecycle is STOPPED
            WindowInfoTracker.getOrCreate(this@MainActivity)
                .windowLayoutInfo(this@MainActivity)
                .collect { layoutInfo ->
                    // New posture information
                    val foldingFeature = layoutInfo.displayFeatures
                        .filterIsInstance()
                        .firstOrNull()
                    // Use information from the foldingFeature object
                }

        }
    }
}

Java

private WindowInfoTrackerCallbackAdapter windowInfoTracker;
private final LayoutStateChangeCallback layoutStateChangeCallback =
                new LayoutStateChangeCallback();

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    ...
    windowInfoTracker =
            new WindowInfoTrackerCallbackAdapter(WindowInfoTracker.getOrCreate(this));
}

@Override
protected void onStart() {
    super.onStart();
    windowInfoTracker.addWindowLayoutInfoListener(
            this, Runnable::run, layoutStateChangeCallback);
}

@Override
protected void onStop() {
    super.onStop();
    windowInfoTracker.removeWindowLayoutInfoListener(layoutStateChangeCallback);
}

class LayoutStateChangeCallback implements Consumer<WindowLayoutInfo> {
    @Override
    public void accept(WindowLayoutInfo newLayoutInfo) {
        // Use newLayoutInfo to update the Layout
        List<DisplayFeature> displayFeatures = newLayoutInfo.getDisplayFeatures();
        for (DisplayFeature feature : displayFeatures) {
            if (feature instanceof FoldingFeature) {
                // Use information from the feature object
            }
        }
    }
}

Masa üstü modu

Uygulamanız, FoldingFeature nesnesindeki bilgileri kullanarak telefonun bir yüzeyde durduğu, menteşenin yatay bir konumda olduğu ve katlanabilir ekranın yarı açık olduğu masa üstü modu gibi duruşları destekleyebilir.

Masa üstü modu, kullanıcılara telefonu ellerinde tutmadan telefonlarını kullanma rahatlığı sunar. Masa üstü modu medya izlemek, fotoğraf çekmek ve görüntülü görüşme yapmak için idealdir.

Masaüstü modundaki video oynatıcı uygulaması

Cihazın masaüstü modunda olup olmadığını belirlemek için FoldingFeature.State ve FoldingFeature.Orientation özelliklerini kullanın:

Kotlin


fun isTableTopPosture(foldFeature : FoldingFeature?) : Boolean {
    contract { returns(true) implies (foldFeature != null) }
    return foldFeature?.state == FoldingFeature.State.HALF_OPENED &&
            foldFeature.orientation == FoldingFeature.Orientation.HORIZONTAL
}

Java


boolean isTableTopPosture(FoldingFeature foldFeature) {
    return (foldFeature != null) &&
           (foldFeature.getState() == FoldingFeature.State.HALF_OPENED) &&
           (foldFeature.getOrientation() == FoldingFeature.Orientation.HORIZONTAL);
}

Cihazın masaüstü modunda olduğunu öğrendikten sonra uygulama düzeninizi buna göre güncelleyin. Medya uygulamaları için bu, genellikle oynatmayı ekranın üst kısmına yerleştirmek ve eller serbest şekilde izleme veya dinleme deneyimi için konumlandırma kontrollerini ve ek içeriği hemen altında yerleştirmek anlamına gelir.

Örnekler

  • MediaPlayerActivity uygulaması: Ekrana duyarlı video oynatıcı oluşturmak için Media3 Exoplayer ve WindowManager'ı nasıl kullanacağınızı öğrenin.

  • Kamera deneyiminizi genişletin codelab'i: Fotoğrafçılık uygulamaları için masaüstü modunu nasıl uygulayacağınızı öğrenin. Vizörü ekranın üst yarısında, ekranın üst kısmında, kontrolleri alt yarısında, ekranın alt kısmında gösterin.

Rezervasyon modu

Katlanabilir bir diğer benzersiz duruş ise cihazın yarım açık ve menteşenin dik konumda olduğu kitap modudur. Kitap modu e-kitap okumak için idealdir. Kitap modu, büyük ekran katlanabilir cihaz üzerindeki, ciltli kitap gibi açık olan iki sayfa düzeniyle gerçek kitap okuma deneyimini yakalar.

Ellerinizi kullanmadan resim çekerken farklı bir en boy oranı yakalamak isterseniz bu özellik fotoğrafçılık için de kullanılabilir.

Kitap modunu, masaüstü modu için kullanılan tekniklerle uygulayın. Tek fark kodun, katlama özelliğinin yönünün yatay yerine dikey olup olmadığını kontrol etmesi gerektiğidir:

Kotlin

fun isBookPosture(foldFeature : FoldingFeature?) : Boolean {
    contract { returns(true) implies (foldFeature != null) }
    return foldFeature?.state == FoldingFeature.State.HALF_OPENED &&
            foldFeature.orientation == FoldingFeature.Orientation.VERTICAL
}

Java

boolean isBookPosture(FoldingFeature foldFeature) {
    return (foldFeature != null) &&
           (foldFeature.getState() == FoldingFeature.State.HALF_OPENED) &&
           (foldFeature.getOrientation() == FoldingFeature.Orientation.VERTICAL);
}

Pencere boyutu değişiklikleri

Cihaz yapılandırmasındaki bir değişiklik nedeniyle bir uygulamanın görüntüleme alanı değişebilir. Örneğin, cihaz katlandığında veya açıldığında, döndürüldüğünde ya da çoklu pencere modunda bir pencere yeniden boyutlandırıldığında görülebilir.

Jetpack WindowManager WindowMetricsCalculator sınıfı geçerli ve maksimum pencere metriklerini almanızı sağlar. API düzeyi 30'da kullanıma sunulan WindowMetrics platformu gibi WindowManager WindowMetrics da pencere sınırlarını sağlar ancak API, API düzeyi 14'e kadar geriye dönük olarak uyumludur.

Pencere boyutu sınıfları bölümünü inceleyin.

Ek kaynaklar

Numuneler

  • Jetpack WindowManager: Jetpack WindowManager kitaplığının nasıl kullanılacağını gösteren örnek
  • Jetcaster: Compose ile masa üstü duruşu uygulaması

Codelab uygulamaları