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
veyaHALF_OPENED
)orientation
: Katlamanın veya menteşenin yönü,HORIZONTAL
veyaVERTICAL
occlusionType
: Katlama veya menteşenin ekranın bir kısmını gizleyip gizlemediğiNONE
veyaFULL
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.
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ı