Katlanmamış büyük ekranlar ve benzersiz katlanmış durum özellikleri, katlanabilir cihazlarda yeni kullanıcı deneyimleri yaşamanızı sağlar. Uygulamanızı katlama özelliğine uygun hale getirmek için, katlama ve menteşe gibi katlanabilir cihaz pencere özellikleri için bir API yüzeyi sağlayan Jetpack WindowManager kitaplığını kullanın. Uygulamanız katlama özelliğine duyarlı olduğunda düzenini uyarlayarak önemli içeriklerin kıvrım veya menteşe alanına yerleştirilmemesine ve doğal ayırıcılar olarak kıvrım ve menteşelerin kullanılmasından kaçınabilir.
Pencere bilgileri
Jetpack WindowManager'daki WindowInfoTracker
arayüzü, pencere düzeni bilgilerini gösterir. Arayüzün windowLayoutInfo()
yöntemi, uygulamanızı katlanabilir cihazların katlama durumu hakkında bilgilendiren bir 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ını kullanarak WindowLayoutInfo
verilerinin toplanması için destek sunar.
Kotlin Akışları
WindowLayoutInfo
veri toplama işlemini başlatmak ve durdurmak için yeniden başlatılabilir, yaşam döngüsüne duyarlı bir eş yordam kullanabilirsiniz. Bu örnekte, yaşam döngüsü en az STARTED
olduğunda repeatOnLifecycle
kod bloğu yürütülür ve yaşam döngüsü STOPPED
olduğunda durdurulur. 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 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ığına dahil edilen geri çağırma uyumluluk katmanı, Kotlin Akışı kullanmadan WindowLayoutInfo
güncellemelerini toplayabilmenizi sağlar. Bu yapı, WindowLayoutInfo
güncellemelerini almak için geri çağırmaları (ve kaydın iptalini) desteklemek üzere WindowInfoTracker
'ı uyarlayan WindowInfoTrackerCallbackAdapter
sınıfını içerir. Ö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
(2
veya 3
sürümü) kullanıyorsanız Kotlin Akışı kullanmadan WindowLayoutInfo
güncellemeleri toplamak için Observable
veya Flowable
sunan 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ı, görüntüleme penceresinin özelliklerini DisplayFeature
öğeleri listesi olarak kullanılabilir hale getirir.
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
ya daVERTICAL
occlusionType
: Katlama veya menteşenin ekranın bir kısmını gizleyip gizlemediği (NONE
veyaFULL
)isSeparating
: Katlamanın veya menteşenin iki mantıksal görüntüleme alanı oluşturup oluşturmadığı (doğru ve yanlış)
HALF_OPENED
olan katlanabilir cihazlar, ekran iki görüntüleme alanına ayrıldığından her zaman isSeparating
değerini "doğru" olarak bildirir. Ayrıca, uygulama her iki ekranı da kapsıyorsa çift ekranlı cihazlarda isSeparating
her zaman doğrudur.
FoldingFeature
bounds
özelliği (DisplayFeature
kaynağından devralınmıştı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 yüzeyde durduğu, menteşenin yatay 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 uygun şekilde güncelleyin. Medya uygulamaları için bu, genellikle oynatmayı ekranın üst kısmına yerleştirmek ve ellerinizi kullanmadan görüntüleme veya dinleme deneyimi için konumlandırma kontrolleriyle ek içeriğin hemen altına yerleştirilmesi anlamına gelir.
Örnekler
MediaPlayerActivity
uygulaması: Ekrana katlama duyarlı video oynatıcı oluşturmak için Media3 Exoplayer ve WindowManager'ı nasıl kullanacağınızı öğrenin.Kamera deneyiminizi geliştirin codelab'i: 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, kontrolleri ise alt yarısında, ekranın alt kısmında gösterin.
Kitap modu
Bir diğer benzersiz katlanabilir cihaz duruşu ise cihazın yarı açık ve menteşesinin dikey olduğu kitap modudur. Kitap modu e-kitap okumak için idealdir. Ciltli kitap gibi iki sayfalık katlanabilir sayfa düzeniyle kitap modu, gerçek kitap okuma deneyimini yakalar.
Ellerinizi kullanmadan fotoğraf ç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 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 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 değişebilir.
Jetpack WindowManager WindowMetricsCalculator
sınıfı, geçerli ve maksimum pencere metriklerini almanızı sağlar. API düzeyi 30'da 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 uyumludur.
Farklı ekran boyutlarını destekleme başlıklı makalede farklı pencere boyutlarını nasıl destekleyeceğinizi öğrenebilirsiniz.
Ek kaynaklar
Sana Özel
- Jetpack WindowManager: Jetpack WindowManager kitaplığının nasıl kullanılacağını gösteren örnek
- Jetcaster: Compose ile masa üstü duruşu uygulama
Codelab uygulamaları
- Jetpack WindowManager ile katlanabilir ve çift ekranlı cihazları destekleme
- Kamera deneyiminizi geliştirin