Implement setSystemBarsBehavior for pre 30 SDK
Test: WindowInsetsControllerCompatActivityTest#systemBarsBehavior_swipe
Test:
WindowInsetsControllerCompatActivityTest#systemBarsBehavior_transient
Test: WindowInsetsControllerCompatActivityTest#systemBarsBehavior_touch
Bug: 173203649
Change-Id: I062c841f0e4201fddfcf1489dbfaff605bebbdb6
(cherry picked from commit 480d10395d28bf22e9f4539f4b992a344628779b)
diff --git a/core/core/src/androidTest/java/androidx/core/view/WindowInsetsAnimationCompatActivityTest.kt b/core/core/src/androidTest/java/androidx/core/view/WindowInsetsAnimationCompatActivityTest.kt
index cc0fb65..ed40508 100644
--- a/core/core/src/androidTest/java/androidx/core/view/WindowInsetsAnimationCompatActivityTest.kt
+++ b/core/core/src/androidTest/java/androidx/core/view/WindowInsetsAnimationCompatActivityTest.kt
@@ -24,6 +24,7 @@
import androidx.core.test.R
import androidx.core.view.WindowInsetsAnimationCompat.Callback.DISPATCH_MODE_CONTINUE_ON_SUBTREE
import androidx.core.view.WindowInsetsAnimationCompat.Callback.DISPATCH_MODE_STOP
+import androidx.core.view.WindowInsetsCompat.Type.statusBars
import androidx.core.view.WindowInsetsCompat.Type.systemBars
import androidx.test.core.app.ActivityScenario
import androidx.test.espresso.Espresso.onIdle
@@ -50,6 +51,8 @@
private lateinit var scenario: ActivityScenario<WindowInsetsCompatActivity>
+ private var barsShown = true
+
@Before
public fun setup() {
scenario = ActivityScenario.launch(WindowInsetsCompatActivity::class.java)
@@ -59,28 +62,30 @@
scenario.onActivity {
WindowCompat.setDecorFitsSystemWindows(it.window, false)
WindowCompat.getInsetsController(it.window, it.window.decorView)!!.show(systemBars())
+ barsShown = true
}
onIdle()
}
@Test
- public fun add_remove_listener() {
+ public fun add_both_listener() {
assumeNotCuttlefish()
val container = scenario.withActivity { findViewById(R.id.container) }
var applyInsetsCalled = false
var insetsAnimationCallbackCalled = false
- var latch = CountDownLatch(2)
+ val insetsLatch = CountDownLatch(1)
+ val animationLatch = CountDownLatch(1)
val animationCallback = createCallback(
>
insetsAnimationCallbackCalled = true
- latch.countDown()
+ animationLatch.countDown()
}
)
val insetListener: (v: View, insets: WindowInsetsCompat) -> WindowInsetsCompat =
{ _, insetsCompat ->
applyInsetsCalled = true
- latch.countDown()
+ insetsLatch.countDown()
insetsCompat
}
@@ -88,7 +93,8 @@
ViewCompat.setOnApplyWindowInsetsListener(container, insetListener)
ViewCompat.setWindowInsetsAnimationCallback(container, animationCallback)
triggerInsetAnimation(container)
- latch.await(4, TimeUnit.SECONDS)
+ animationLatch.await(4, TimeUnit.SECONDS)
+ insetsLatch.await(4, TimeUnit.SECONDS)
assertTrue(
"The WindowInsetsAnimationCallback has not been called",
insetsAnimationCallbackCalled
@@ -97,16 +103,36 @@
"onApplyWindowInsetsListener has not been called",
applyInsetsCalled
)
- resetBars(container)
+ }
- // Remove the applyWindowInsets listener and check that the animation callback is still
- // called
- applyInsetsCalled = false
- insetsAnimationCallbackCalled = false
- latch = CountDownLatch(1)
+ @Test
+ public fun remove_insets_listener() {
+ assumeNotCuttlefish()
+
+ val container = scenario.withActivity { findViewById(R.id.container) }
+ var applyInsetsCalled = false
+ var insetsAnimationCallbackCalled = false
+ val insetsLatch = CountDownLatch(1)
+ val animationLatch = CountDownLatch(1)
+ val animationCallback = createCallback(
+ >
+ insetsAnimationCallbackCalled = true
+ animationLatch.countDown()
+ }
+ )
+ val insetListener: (v: View, insets: WindowInsetsCompat) -> WindowInsetsCompat =
+ { _, insetsCompat ->
+ applyInsetsCalled = true
+ insetsLatch.countDown()
+ insetsCompat
+ }
+
+ // Check that both ApplyWindowInsets and the Animation Callback are called
+ ViewCompat.setOnApplyWindowInsetsListener(container, insetListener)
+ ViewCompat.setWindowInsetsAnimationCallback(container, animationCallback)
ViewCompat.setOnApplyWindowInsetsListener(container, null)
triggerInsetAnimation(container)
- latch.await(4, TimeUnit.SECONDS)
+ animationLatch.await(4, TimeUnit.SECONDS)
assertFalse(
"onApplyWindowInsetsListener should NOT have been called",
applyInsetsCalled
@@ -115,18 +141,35 @@
"The WindowInsetsAnimationCallback has not been called",
insetsAnimationCallbackCalled
)
+ }
- resetBars(container)
+ @Test
+ public fun remove_animation_listener() {
+ assumeNotCuttlefish()
- // Add an applyWindowInsets listener and remove the animation callback and check if the
- // listener is called
- applyInsetsCalled = false
- insetsAnimationCallbackCalled = false
- latch = CountDownLatch(1)
+ val container = scenario.withActivity { findViewById(R.id.container) }
+ var applyInsetsCalled = false
+ var insetsAnimationCallbackCalled = false
+ val insetsLatch = CountDownLatch(1)
+ val animationLatch = CountDownLatch(1)
+ val animationCallback = createCallback(
+ >
+ insetsAnimationCallbackCalled = true
+ animationLatch.countDown()
+ }
+ )
+ val insetListener: (v: View, insets: WindowInsetsCompat) -> WindowInsetsCompat =
+ { _, insetsCompat ->
+ applyInsetsCalled = true
+ insetsLatch.countDown()
+ insetsCompat
+ }
+
ViewCompat.setOnApplyWindowInsetsListener(container, insetListener)
+ ViewCompat.setWindowInsetsAnimationCallback(container, animationCallback)
ViewCompat.setWindowInsetsAnimationCallback(container, null)
triggerInsetAnimation(container)
- latch.await(4, TimeUnit.SECONDS)
+ insetsLatch.await(4, TimeUnit.SECONDS)
assertTrue("onApplyWindowInsetsListener has not been called", applyInsetsCalled)
assertFalse(
"The WindowInsetsAnimationCallback should NOT have been called",
@@ -182,13 +225,13 @@
private fun triggerInsetAnimation(container: View) {
scenario.onActivity {
- ViewCompat.getWindowInsetsController(container)!!.hide(systemBars())
- }
- }
-
- private fun resetBars(container: View) {
- scenario.onActivity {
- ViewCompat.getWindowInsetsController(container)!!.show(systemBars())
+ if (barsShown) {
+ ViewCompat.getWindowInsetsController(container)!!.hide(statusBars())
+ barsShown = false
+ } else {
+ ViewCompat.getWindowInsetsController(container)!!.show(statusBars())
+ barsShown = true
+ }
}
}
@@ -200,7 +243,8 @@
var applyInsetsCalled3 = false
var insetsAnimationCallbackCalled1 = false
var insetsAnimationCallbackCalled2 = false
- val latch = CountDownLatch(2)
+ val insetsLatch = CountDownLatch(1)
+ val animationLatch = CountDownLatch(1)
val animationCallback1 = createCallback(
>
insetsAnimationCallbackCalled1 = true
@@ -209,7 +253,7 @@
val animationCallback2 = createCallback(
>
insetsAnimationCallbackCalled2 = true
- latch.countDown()
+ animationLatch.countDown()
}
)
val insetListener1: (v: View, insets: WindowInsetsCompat) -> WindowInsetsCompat =
@@ -227,7 +271,7 @@
val insetListener3: (v: View, insets: WindowInsetsCompat) -> WindowInsetsCompat =
{ _, insetsCompat ->
applyInsetsCalled3 = true
- latch.countDown()
+ insetsLatch.countDown()
insetsCompat
}
@@ -238,7 +282,8 @@
ViewCompat.setWindowInsetsAnimationCallback(container, animationCallback2)
ViewCompat.setOnApplyWindowInsetsListener(container, insetListener3)
triggerInsetAnimation(container)
- latch.await(5, TimeUnit.SECONDS)
+ animationLatch.await(5, TimeUnit.SECONDS)
+ insetsLatch.await(5, TimeUnit.SECONDS)
assertFalse(
"The WindowInsetsAnimationCallback #1 should have not been called",
insetsAnimationCallbackCalled1
@@ -268,24 +313,26 @@
val container = scenario.withActivity { findViewById(R.id.container) }
var applyInsetsCalled = false
var insetsAnimationCallbackCalled = false
- var latch = CountDownLatch(2)
+ val insetsLatch = CountDownLatch(1)
+ val animationLatch = CountDownLatch(1)
val animationCallback = createCallback(
>
insetsAnimationCallbackCalled = true
- latch.countDown()
+ animationLatch.countDown()
}
)
val insetListener: (v: View, insets: WindowInsetsCompat) -> WindowInsetsCompat =
{ _, insetsCompat ->
applyInsetsCalled = true
- latch.countDown()
+ insetsLatch.countDown()
insetsCompat
}
ViewCompat.setWindowInsetsAnimationCallback(container, animationCallback)
ViewCompat.setOnApplyWindowInsetsListener(container, insetListener)
triggerInsetAnimation(container)
- latch.await(4, TimeUnit.SECONDS)
+ animationLatch.await(4, TimeUnit.SECONDS)
+ insetsLatch.await(4, TimeUnit.SECONDS)
assertTrue(
"The WindowInsetsAnimationCallback has not been called",
insetsAnimationCallbackCalled
@@ -395,10 +442,6 @@
childListenerCalledCount
)
- // Then we do the same but without consuming the insets in the parent, so the child
- // listener should be called.
- resetBars(container)
-
>
val dispatchCallback = createCallback(
>
diff --git a/core/core/src/androidTest/java/androidx/core/view/WindowInsetsControllerCompatActivityTest.kt b/core/core/src/androidTest/java/androidx/core/view/WindowInsetsControllerCompatActivityTest.kt
index 667fc08..ca37b0c 100644
--- a/core/core/src/androidTest/java/androidx/core/view/WindowInsetsControllerCompatActivityTest.kt
+++ b/core/core/src/androidTest/java/androidx/core/view/WindowInsetsControllerCompatActivityTest.kt
@@ -71,11 +71,13 @@
}
// Close the IME if it's open, so we start from a known scenario
onView(withId(R.id.edittext)).perform(closeSoftKeyboard())
- ViewCompat.getWindowInsetsController(container)!!.systemBarsBehavior =
- WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
- // Needed on API 23 to report the nav bar insets
- scenario.withActivity { this.window.addFlags(FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) }
+ scenario.withActivity {
+ ViewCompat.getWindowInsetsController(container)!!.systemBarsBehavior =
+ WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
+ // Needed on API 23 to report the nav bar insets
+ this.window.addFlags(FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
+ }
}
/**
@@ -260,6 +262,55 @@
}
}
+ @Test
+ @SdkSuppress(maxSdkVersion = 29) // Flag deprecated in 30+
+ public fun systemBarsBehavior_swipe() {
+ scenario.onActivity {
+ windowInsetsController.systemBarsBehavior =
+ WindowInsetsControllerCompat.BEHAVIOR_SHOW_BARS_BY_SWIPE
+ }
+ val decorView = scenario.withActivity { window.decorView }
+ val sysUiVis = decorView.systemUiVisibility
+ assertEquals(
+ View.SYSTEM_UI_FLAG_IMMERSIVE,
+ sysUiVis and View.SYSTEM_UI_FLAG_IMMERSIVE
+ )
+ assertEquals(0, sysUiVis and View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
+ }
+
+ @Test
+ @SdkSuppress(maxSdkVersion = 29) // Flag deprecated in 30+
+ public fun systemBarsBehavior_transient() {
+ scenario.onActivity {
+ windowInsetsController.systemBarsBehavior =
+ WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
+ }
+ val decorView = scenario.withActivity { window.decorView }
+ val sysUiVis = decorView.systemUiVisibility
+ assertEquals(
+ View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
+ sysUiVis and View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
+ )
+ assertEquals(0, sysUiVis and View.SYSTEM_UI_FLAG_IMMERSIVE)
+ }
+
+ @Test
+ public fun systemBarsBehavior_touch() {
+ scenario.onActivity {
+ windowInsetsController.systemBarsBehavior =
+ WindowInsetsControllerCompat.BEHAVIOR_SHOW_BARS_BY_TOUCH
+ }
+ val decorView = scenario.withActivity { window.decorView }
+ val sysUiVis = decorView.systemUiVisibility
+ assertEquals(
+ 0,
+ sysUiVis and (
+ View.SYSTEM_UI_FLAG_IMMERSIVE
+ or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
+ )
+ )
+ }
+
private fun assumeNotCuttlefish() {
// TODO: remove this if b/159103848 is resolved
assumeFalse(
diff --git a/core/core/src/main/java/androidx/core/view/ViewCompat.java b/core/core/src/main/java/androidx/core/view/ViewCompat.java
index 5e30e5f..e63c616 100644
--- a/core/core/src/main/java/androidx/core/view/ViewCompat.java
+++ b/core/core/src/main/java/androidx/core/view/ViewCompat.java
@@ -2606,7 +2606,7 @@
* Provide original {@link WindowInsetsCompat} that are dispatched to the view hierarchy.
* The insets are only available if the view is attached.
* <p>
- * On devices running API 22 and below, this method always returns null.
+ * On devices running API 20 and below, this method always returns null.
*
* @return WindowInsetsCompat from the top of the view hierarchy or null if View is detached
*/
diff --git a/core/core/src/main/java/androidx/core/view/WindowInsetsAnimationCompat.java b/core/core/src/main/java/androidx/core/view/WindowInsetsAnimationCompat.java
index 80268b9..c2c1409 100644
--- a/core/core/src/main/java/androidx/core/view/WindowInsetsAnimationCompat.java
+++ b/core/core/src/main/java/androidx/core/view/WindowInsetsAnimationCompat.java
@@ -730,7 +730,7 @@
if (DEBUG) {
int allTypes = WindowInsetsCompat.Type.all();
- Log.d(TAG, String.format("lastInsets: %s\ntargetInsets: %s",
+ Log.d(TAG, String.format("lastInsets: %s\ntargetInsets: %s",
mLastInsets.getInsets(allTypes),
targetInsets.getInsets(allTypes)));
}
@@ -746,6 +746,9 @@
// We only run the animation when the some insets are animating
final int animationMask = buildAnimationMask(targetInsets, mLastInsets);
if (animationMask == 0) {
+ if (DEBUG) {
+ Log.d(TAG, "Insets applied bug no window animation to run");
+ }
return forwardToViewIfNeeded(v, insets);
}
diff --git a/core/core/src/main/java/androidx/core/view/WindowInsetsControllerCompat.java b/core/core/src/main/java/androidx/core/view/WindowInsetsControllerCompat.java
index d904b05..dd5bcd3 100644
--- a/core/core/src/main/java/androidx/core/view/WindowInsetsControllerCompat.java
+++ b/core/core/src/main/java/androidx/core/view/WindowInsetsControllerCompat.java
@@ -468,7 +468,6 @@
switch (type) {
case WindowInsetsCompat.Type.STATUS_BARS:
setSystemUiFlag(View.SYSTEM_UI_FLAG_FULLSCREEN);
- setWindowFlag(WindowManager.LayoutParams.FLAG_FULLSCREEN);
return;
case WindowInsetsCompat.Type.NAVIGATION_BARS:
setSystemUiFlag(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
@@ -511,6 +510,20 @@
@Override
void setSystemBarsBehavior(int behavior) {
+ switch (behavior) {
+ case BEHAVIOR_SHOW_BARS_BY_SWIPE:
+ unsetSystemUiFlag(View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
+ setSystemUiFlag(View.SYSTEM_UI_FLAG_IMMERSIVE);
+ break;
+ case BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE:
+ unsetSystemUiFlag(View.SYSTEM_UI_FLAG_IMMERSIVE);
+ setSystemUiFlag(View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
+ break;
+ case BEHAVIOR_SHOW_BARS_BY_TOUCH:
+ unsetSystemUiFlag(View.SYSTEM_UI_FLAG_IMMERSIVE
+ | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
+ break;
+ }
}
@Override
diff --git a/samples/Support4Demos/src/main/java/com/example/android/supportv4/view/WindowInsetsControllerPlayground.kt b/samples/Support4Demos/src/main/java/com/example/android/supportv4/view/WindowInsetsControllerPlayground.kt
index b43d49b..fb424b1 100644
--- a/samples/Support4Demos/src/main/java/com/example/android/supportv4/view/WindowInsetsControllerPlayground.kt
+++ b/samples/Support4Demos/src/main/java/com/example/android/supportv4/view/WindowInsetsControllerPlayground.kt
@@ -13,6 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+@file:Suppress("DEPRECATION")
+
package com.example.android.supportv4.view
import android.animation.Animator
@@ -36,7 +38,6 @@
import android.widget.ArrayAdapter
import android.widget.Button
import android.widget.CheckBox
-import android.widget.LinearLayout
import android.widget.Spinner
import android.widget.TextView
import android.widget.ToggleButton
@@ -49,6 +50,8 @@
import androidx.core.view.WindowInsetsAnimationControllerCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsCompat.Type.ime
+import androidx.core.view.WindowInsetsCompat.Type.navigationBars
+import androidx.core.view.WindowInsetsCompat.Type.statusBars
import androidx.core.view.WindowInsetsCompat.Type.systemBars
import androidx.core.view.WindowInsetsControllerCompat
import com.example.android.supportv4.R
@@ -71,6 +74,7 @@
private lateinit var editRow: ViewGroup
private lateinit var visibility: TextView
private lateinit var buttonsRow: ViewGroup
+ private lateinit var buttonsRow2: ViewGroup
private lateinit var fitSystemWindow: CheckBox
private lateinit var isDecorView: CheckBox
internal lateinit var info: TextView
@@ -88,6 +92,7 @@
editRow = findViewById(R.id.editRow)
visibility = findViewById(R.id.visibility)
buttonsRow = findViewById(R.id.buttonRow)
+ buttonsRow2 = findViewById(R.id.buttonRow2)
info = findViewById(R.id.info)
fitSystemWindow = findViewById(R.id.decorFitsSystemWindows)
isDecorView = findViewById(R.id.isDecorView)
@@ -109,6 +114,9 @@
isChecked = false
setOnCheckedChangeListener { _, isChecked ->
WindowCompat.setDecorFitsSystemWindows(window, isChecked)
+ if (isChecked) {
+ mRoot.setPadding(0, 0, 0, 0)
+ }
}
}
@@ -118,20 +126,8 @@
setupTypeSpinner()
setupHideShowButtons()
setupAppearanceButtons()
-
- ViewCompat.setOnApplyWindowInsetsListener(mRoot) { _: View?, insets: WindowInsetsCompat ->
- val systemBarInsets = insets.getInsets(ime() or systemBars())
- mRoot.setPadding(
- systemBarInsets.left,
- systemBarInsets.top,
- systemBarInsets.right,
- systemBarInsets.bottom
- )
- visibility.text =
- "Inset visibility: " + currentType?.let { insets.isVisible(it) }?.toString()
-
- WindowInsetsCompat.CONSUMED
- }
+ setupBehaviorSpinner()
+ setupLayoutButton()
setupIMEAnimation()
setupActionButton()
@@ -167,9 +163,8 @@
graph.minimumWidth = 300
graph.minimumHeight = 100
graph.setBackgroundColor(Color.GRAY)
- val linearLayout = info.parent as LinearLayout
- linearLayout.addView(
- graph, linearLayout.indexOfChild(isDecorView),
+ findViewById<ViewGroup>(R.id.graph_container).addView(
+ graph,
ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 200)
)
}
@@ -189,18 +184,9 @@
text = name
textOn = text
textOff = text
- setOnClickListener {
- isChecked = true
- callback(true)
-
- it.postDelayed(
- {
- isChecked = false
- callback(false)
- },
- 2000
- )
- }
+ setOnCheckedChangeListener { _, isChecked -> callback(isChecked) }
+ isChecked = true
+ callback(true)
}
)
}
@@ -294,7 +280,12 @@
insets: WindowInsetsCompat,
runningAnimations: List<WindowInsetsAnimationCompat>
): WindowInsetsCompat {
- mTransitions.forEach { it.onProgress() }
+ val systemInsets = insets.getInsets(systemBars())
+ mRoot.setPadding(
+ systemInsets.left, systemInsets.top, systemInsets.right,
+ systemInsets.bottom
+ )
+ mTransitions.forEach { it.onProgress(insets) }
return insets
}
@@ -329,6 +320,35 @@
}
}
+ private fun setupLayoutButton() {
+ arrayOf(
+ "STABLE" to View.SYSTEM_UI_FLAG_LAYOUT_STABLE,
+ "STAT" to View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
+ "NAV" to View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ ).forEach { (name, flag) ->
+ buttonsRow2.addView(
+ ToggleButton(this).apply {
+ text = name
+ textOn = text
+ textOff = text
+ setOnCheckedChangeListener { _, isChecked ->
+ val systemUiVisibility = window.decorView.systemUiVisibility
+ window.decorView.systemUiVisibility =
+ if (isChecked) systemUiVisibility or flag
+ else systemUiVisibility and flag.inv()
+ }
+ isChecked = false
+ }
+ )
+ }
+ window.decorView.systemUiVisibility = window.decorView.systemUiVisibility and (
+ View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+ or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ )
+ .inv()
+ }
+
private fun createOnTouchListener(): View.OnTouchListener {
return object : View.OnTouchListener {
private val mViewConfiguration =
@@ -433,10 +453,11 @@
private fun setupTypeSpinner() {
val types = mapOf(
- "IME" to ime(),
- "Navigation" to WindowInsetsCompat.Type.navigationBars(),
"System" to systemBars(),
- "Status" to WindowInsetsCompat.Type.statusBars()
+ "IME" to ime(),
+ "Navigation" to navigationBars(),
+ "Status" to statusBars(),
+ "All" to (systemBars() or ime())
)
findViewById<Spinner>(R.id.spn_insets_type).apply {
adapter = ArrayAdapter(
@@ -461,6 +482,37 @@
}
}
+ private fun setupBehaviorSpinner() {
+ val types = mapOf(
+ "BY TOUCH" to WindowInsetsControllerCompat.BEHAVIOR_SHOW_BARS_BY_TOUCH,
+ "BY SWIPE" to WindowInsetsControllerCompat.BEHAVIOR_SHOW_BARS_BY_SWIPE,
+ "TRANSIENT" to WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE,
+ )
+ findViewById<Spinner>(R.id.spn_behavior).apply {
+ adapter = ArrayAdapter(
+ context, android.R.layout.simple_spinner_dropdown_item,
+ types.keys.toTypedArray()
+ )
+ : AdapterView.OnItemSelectedListener {
+ override fun onNothingSelected(parent: AdapterView<*>?) {
+ }
+
+ override fun onItemSelected(
+ parent: AdapterView<*>?,
+ view: View?,
+ position: Int,
+ id: Long
+ ) {
+ if (parent != null && view != null) {
+ WindowCompat.getInsetsController(window, view)!!
+ .systemBarsBehavior = types[selectedItem]!!
+ }
+ }
+ }
+ setSelection(0)
+ }
+ }
+
inner class Transition(private val view: View) {
private var mEndBottom = 0
private var mStartBottom = 0
@@ -479,13 +531,8 @@
}
}
- fun onProgress() {
- mInsetsAnimation?.let {
- view.y = (
- mStartBottom +
- (mEndBottom - mStartBottom) * it.interpolatedFraction - view.height
- )
- }
+ fun onProgress(insets: WindowInsetsCompat) {
+ view.y = (mStartBottom + insets.getInsets(ime() or systemBars()).bottom).toFloat()
if (debug) {
Log.d(TAG, view.y.toString())
values.add(view.y)
diff --git a/samples/Support4Demos/src/main/res/layout/activity_insets_controller.xml b/samples/Support4Demos/src/main/res/layout/activity_insets_controller.xml
index 0deaab4..fab30e8b 100644
--- a/samples/Support4Demos/src/main/res/layout/activity_insets_controller.xml
+++ b/samples/Support4Demos/src/main/res/layout/activity_insets_controller.xml
@@ -52,37 +52,70 @@
</LinearLayout>
- <CheckBox
- android:id="@+id/decorFitsSystemWindows"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="setDecorFitsSystemWindows" />
+ <Spinner
+ android:id="@+id/spn_behavior"
+ android:layout_width="match_parent"
+ android:layout_height="50dp" />
- <CheckBox
- android:id="@+id/isDecorView"
+ <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:checked="true"
- android:text="On Decor View" />
+ android:orientation="horizontal">
- <TextView
- android:id="@+id/visibility"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="TextView" />
+ <CheckBox
+ android:id="@+id/decorFitsSystemWindows"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="setDecorFitsSystemWindows" />
- <TextView
- android:id="@+id/info"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="TextView" />
+ <CheckBox
+ android:id="@+id/isDecorView"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:checked="true"
+ android:text="On Decor View" />
+ </LinearLayout>
<LinearLayout
android:id="@+id/buttonRow"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ tools:layout_height="50dp"
android:orientation="horizontal" />
+ <LinearLayout
+ android:id="@+id/buttonRow2"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ tools:layout_height="50dp"
+ android:orientation="horizontal" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:orientation="horizontal">
+
+ <TextView
+ android:id="@+id/visibility"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="TextView" />
+
+ <TextView
+ android:id="@+id/info"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="TextView" />
+ </LinearLayout>
+
+ <FrameLayout
+ android:id="@+id/graph_container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ </FrameLayout>
+
<FrameLayout
android:id="@+id/scrollView"
android:layout_height="0dp"