Skip to content

Instantly share code, notes, and snippets.

@TemMax
Last active October 8, 2020 09:51

Revisions

  1. TemMax revised this gist Oct 8, 2020. 1 changed file with 5 additions and 1 deletion.
    6 changes: 5 additions & 1 deletion KeyboardAwareFrameLayout.kt
    Original file line number Diff line number Diff line change
    @@ -37,9 +37,13 @@ class SizeNotifierFrameLayout @JvmOverloads constructor(
    val isKeyboardShowed: Boolean
    get() = keyboardSize > minKeyboardSize

    var isUpdatePaddingWhenKeyboardShowed = true

    init {
    doOnApplyWindowInsets { _, insets, initialPadding ->
    updatePadding(bottom = initialPadding.bottom + insets.systemWindowInsetBottom)
    if (isUpdatePaddingWhenKeyboardShowed) {
    updatePadding(bottom = initialPadding.bottom + insets.systemWindowInsetBottom)
    }
    keyboardSize = insets.systemWindowInsetBottom
    insets
    }
  2. TemMax created this gist Jun 16, 2020.
    78 changes: 78 additions & 0 deletions KeyboardAwareFrameLayout.kt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,78 @@
    import android.content.Context
    import android.util.AttributeSet
    import android.widget.FrameLayout
    import androidx.core.view.ViewCompat
    import androidx.core.view.WindowInsetsCompat

    /**
    * Before adding this:
    * 1. In AndroidManifest in your <activity/> tag android:windowSoftInputMode="adjustResize"
    * 2. Enable "EDGE-TO-EDGE" mode in your activity -> window.decorView.systemUiVisibility = decorView.systemUiVisibility or (View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE)
    * 2.1. Set colors for status and navigation bars:
    * window.statusBarColor = [yourColor]
    * window.navigationBarColor = [yourColor]
    * 2.2. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
    * window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
    * }
    * 3. Profit
    */
    typealias KeyboardStateListener = (isShowed: Boolean) -> Unit

    class SizeNotifierFrameLayout @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
    ) : FrameLayout(context, attrs, defStyleAttr) {

    private companion object {
    private val minKeyboardSize = Screen.dp(100)
    }

    private var keyboardStateListener: KeyboardStateListener? = null

    private var keyboardSize = 0
    set(value) {
    field = value
    keyboardStateListener?.invoke(isKeyboardShowed)
    }

    val isKeyboardShowed: Boolean
    get() = keyboardSize > minKeyboardSize

    init {
    doOnApplyWindowInsets { _, insets, initialPadding ->
    updatePadding(bottom = initialPadding.bottom + insets.systemWindowInsetBottom)
    keyboardSize = insets.systemWindowInsetBottom
    insets
    }
    }

    fun setKeyboardStateListener(listener: KeyboardStateListener?) {
    this.keyboardStateListener = listener
    }

    }

    fun View.doOnApplyWindowInsets(block: (View, insets: WindowInsetsCompat, initialPadding: Rect) -> WindowInsetsCompat) {
    val initialPadding = recordInitialPaddingForView(this)
    ViewCompat.setOnApplyWindowInsetsListener(this) { v, insets ->
    block(v, insets, initialPadding)
    }
    requestApplyInsetsWhenAttached()
    }

    private fun recordInitialPaddingForView(view: View) =
    Rect(view.paddingLeft, view.paddingTop, view.paddingRight, view.paddingBottom)

    private fun View.requestApplyInsetsWhenAttached() {
    if (isAttachedToWindow) {
    ViewCompat.requestApplyInsets(this)
    } else {
    addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener {
    override fun onViewAttachedToWindow(v: View) {
    v.removeOnAttachStateChangeListener(this)
    ViewCompat.requestApplyInsets(v)
    }

    override fun onViewDetachedFromWindow(v: View) = Unit
    })
    }
    }