Last active
October 8, 2020 09:51
-
-
Save TemMax/4f4931208e6b39b8c49f6e6ca751e006 to your computer and use it in GitHub Desktop.
Keyboard-aware FrameLayout that fits when keyboard is opened. 100 dp is a magic dimension. Waiting for WindowInsets update with Android 11
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
var isUpdatePaddingWhenKeyboardShowed = true | |
init { | |
doOnApplyWindowInsets { _, insets, initialPadding -> | |
if (isUpdatePaddingWhenKeyboardShowed) { | |
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 | |
}) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment