Skip to content

Instantly share code, notes, and snippets.

@fabirt
Created August 26, 2020 15:49
Show Gist options
  • Select an option

  • Save fabirt/470040b4e7dcfa89bf4b42c1c01955fa to your computer and use it in GitHub Desktop.

Select an option

Save fabirt/470040b4e7dcfa89bf4b42c1c01955fa to your computer and use it in GitHub Desktop.
Android 11 WindowInsets API Demo
package com.example.windowinsets
import android.graphics.Insets
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.view.WindowInsets
import android.view.WindowInsetsAnimation
import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.activity_main.*
// Android 11 WindowInsets API Demo
class MainActivity : AppCompatActivity() {
companion object {
const val TAG = "MainActivityLog"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
window.setDecorFitsSystemWindows(false)
recyclerView.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, true)
recyclerView.adapter = MyAdapter()
val rootView = window.decorView.rootView
val deferringInsetsListener = RootViewDeferringInsetsCallback(
persistentInsetTypes = WindowInsets.Type.systemBars(),
deferredInsetTypes = WindowInsets.Type.ime()
)
rootView.setWindowInsetsAnimationCallback(deferringInsetsListener)
rootView.setOnApplyWindowInsetsListener(deferringInsetsListener)
editText.setWindowInsetsAnimationCallback(TranslateDeferringInsetsAnimationCallback(
view = editText,
persistentInsetTypes = WindowInsets.Type.systemBars(),
deferredInsetTypes = WindowInsets.Type.ime(),
dispatchMode = WindowInsetsAnimation.Callback.DISPATCH_MODE_CONTINUE_ON_SUBTREE
))
recyclerView.setWindowInsetsAnimationCallback(TranslateDeferringInsetsAnimationCallback(
view = recyclerView,
persistentInsetTypes = WindowInsets.Type.systemBars(),
deferredInsetTypes = WindowInsets.Type.ime()
))
}
}
class RootViewDeferringInsetsCallback(
val persistentInsetTypes: Int,
val deferredInsetTypes: Int
) : WindowInsetsAnimation.Callback(DISPATCH_MODE_CONTINUE_ON_SUBTREE), View.OnApplyWindowInsetsListener {
private var view: View? = null
private var lastWindowInsets: WindowInsets? = null
private var deferredInsets = false
override fun onProgress(
insets: WindowInsets,
runningAnimations: List<WindowInsetsAnimation>
): WindowInsets {
return insets
}
override fun onApplyWindowInsets(v: View?, windowInsets: WindowInsets?): WindowInsets {
view = v
lastWindowInsets = windowInsets
val types = when {
deferredInsets -> persistentInsetTypes
else -> persistentInsetTypes or deferredInsetTypes
}
val typeInsets = windowInsets!!.getInsets(types)
v?.setPadding(typeInsets.left, typeInsets.top, typeInsets.right, typeInsets.bottom)
return WindowInsets.CONSUMED
}
override fun onPrepare(animation: WindowInsetsAnimation) {
if (animation.typeMask and deferredInsetTypes != 0) {
deferredInsets = true
}
}
override fun onEnd(animation: WindowInsetsAnimation) {
if (deferredInsets && (animation.typeMask and deferredInsetTypes) != 0) {
deferredInsets = false
if (lastWindowInsets != null) {
view?.dispatchApplyWindowInsets(lastWindowInsets!!)
}
}
}
}
class TranslateDeferringInsetsAnimationCallback(
private val view: View,
val persistentInsetTypes: Int,
val deferredInsetTypes: Int,
dispatchMode: Int = DISPATCH_MODE_STOP
) : WindowInsetsAnimation.Callback(dispatchMode) {
init {
require(persistentInsetTypes and deferredInsetTypes == 0) {
"persistentInsetTypes and deferredInsetTypes can not contain any of " +
" same WindowInsets.Type values"
}
}
override fun onProgress(
insets: WindowInsets,
runningAnimations: List<WindowInsetsAnimation>
): WindowInsets {
val typesInset = insets.getInsets(deferredInsetTypes)
val otherInset = insets.getInsets(persistentInsetTypes)
val diff = Insets.subtract(typesInset, otherInset).let {
Insets.max(it, Insets.NONE)
}
view.translationX = (diff.left - diff.right).toFloat()
view.translationY = (diff.top - diff.bottom).toFloat()
return insets
}
override fun onEnd(animation: WindowInsetsAnimation) {
view.translationX = 0f
view.translationY = 0f
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment