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

Büyük, açılmış ekranlar ve benzersiz katlanmış durumlar, katlanabilir cihazlarda yeni kullanıcı deneyimlerine olanak tanır. Uygulamanızı katlanabilir hale getirmek için kıvrımlar ve menteşeler gibi katlanabilir cihaz penceresi özellikleri için API yüzeyi sağlayan Jetpack WindowManager kitaplığını kullanın. Uygulamanız katlanmaya duyarlı olduğunda düzeni, kıvrımlar veya menteşeler bulunan alanlara önemli içerik yerleştirmeyecek şekilde uyarlayabilir ve kıvrımları ve menteşeleri doğal ayırıcılar olarak kullanabilir.

Pencere bilgileri

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

WindowManager, Kotlin Akışları ve Java geri çağırmaları kullanarak WindowLayoutInfo verilerini toplamak için destek sağlar.

Kotlin Akışları

WindowLayoutInfo veri toplama işlemini başlatmak ve durdurmak için, yaşam döngüsü en az STARTED olduğunda repeatOnLifecycle kod bloğunun yürütüldüğü ve yaşam döngüsü STOPPED olduğunda durdurulduğu yeniden başlatılabilir yaşam döngüsüne duyarlı bir eş yordam kullanabilirsiniz. Yaşam döngüsü tekrar STARTED 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 toplayıp 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ğırma işlevleri

androidx.window:window-java bağımlılığında yer alan geri çağırma uyumluluk katmanı, Kotlin Akışı kullanmadan WindowLayoutInfo güncellemelerini toplamanızı sağlar. Yapı, WindowLayoutInfo güncellemelerini almak için geri çağırmaları kaydetmek (ve kayıt iptallerini) desteklemek üzere bir WindowInfoTracker uyarlayan WindowInfoTrackerCallbackAdapter sınıfını içeriyor. Ö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

RxJava'ı (2 veya 3 sürümü) kullanıyorsanız Kotlin Akışı kullanmadan WindowLayoutInfo güncellemeleri 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

Jetpack WindowManager'ın WindowLayoutInfo sınıfı, görüntüleme penceresinin özelliklerini DisplayFeature öğelerinden oluşan bir liste olarak kullanılabilir hale getirir.

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

  • state: Cihazın katlanmış durumu, FLAT veya HALF_OPENED
  • orientation: Katlama veya menteşenin yönü, HORIZONTAL ya da VERTICAL
  • occlusionType: Kıvrımın veya menteşenin ekranın bir kısmını gizleyip kapatmayacağı, NONE veya FULL
  • isSeparating: Ekranın veya menteşenin doğru ve yanlış olmak üzere iki mantıksal görüntüleme alanı oluşturup oluşturmadığı

HALF_OPENED özelliği olan katlanabilir cihazlar, ekran iki görüntüleme alanına ayrıldığından isSeparating değerini her zaman doğru olarak bildirir. Ayrıca, uygulama her iki ekranı da kapsıyorsa isSeparating, çift ekranlı cihazlarda her zaman geçerlidir.

FoldingFeature bounds özelliği (DisplayFeature tarihinden devralınır), katlama veya menteşe gibi 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 masa üstü modu, telefonun bir yüzeyde olduğu, menteşenin yatay konumda ve katlanabilir ekranın yarı açık olduğu gibi duruşları destekleyebilir.

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

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

Cihazın masaüstü modunda olup olmadığını belirlemek için FoldingFeature.State ve FoldingFeature.Orientation araçlarını 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ü moduna geçtiğinden emin olduktan sonra uygulama düzeninizi buna göre güncelleyin. Medya uygulamalarında bu, genellikle oynatmayı ekranın üst kısmına yerleştirmek ve eller serbest izleme veya dinleme deneyimi için konumlandırma kontrolleri ve ek içeriklerin hemen alt kısmına yerleştirilmesi anlamına gelir.

Örnekler

  • MediaPlayerActivity uygulaması: Katlanabilir video oynatıcı oluşturmak için Media3 Exoplayer ve WindowManager'ın nasıl kullanıldığını öğrenin.

  • Kamera deneyiminizi açın codelab: Fotoğraf 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 ve alt yarısındaki kontrolleri ekranın alt kısmında gösterin.

Rezervasyon modu

Bir başka benzersiz katlanabilir duruş türü ise cihazın yarım açık, menteşenin dikey olduğu kitap modudur. Kitap modu, e-kitap okumak için idealdir. İki sayfalık sayfa düzeni, ciltli kitaplar gibi açık bir katlanabilir büyük ekran üzerindeyken, kitap modu ile gerçek bir kitap okuma deneyimini yakalarsınız.

Ellerinizi kullanmadan fotoğraf çekerken farklı en boy oranları yakalamak istiyorsanız, fotoğraf için de kullanılabilir.

Kitap modunu, masa üstü modu için kullanılan tekniklerle uygulayın. Tek fark, kodun katlama özelliği yönünün yatay değil dikey olup olmadığını kontrol etmesidir:

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ında yapılan bir değişiklik nedeniyle uygulamanın görüntüleme alanı değişebilir. Örneğin, cihaz katlanmışsa veya açılmışsa, döndürüldüğünde ya da çoklu pencere modunda bir pencere yeniden boyutlandırıldığında.

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

Pencere boyutu sınıfları başlıklı makaleyi inceleyin.

Ek kaynaklar

Numuneler

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

Codelab'ler