【めっちゃ口語】adjustNothingでもSoftwareKeyboardがせり上がった分だけ何かしたいんじゃ!ってときにやること

はじめに

やっほー
早速だけど、SoftwareInputModeって有るじゃん?
adjustPanだとかadjustResizeだとか
…なんかキーボードがビュッって出たらシュッと縮んだりするじゃん。EditTextがキーボードの裏に隠れない!素敵!

便利なんだけどさ

俺がやりたいのは背景は縮めたくないの!でもキーボードの位置は上にずらしたいの!
ってな感じだったのよ。Instagramのライブ配信のコメント欄みたいなアレ!アレがやりたいの!
adjustNoneが良いの!

…でもキーボードが出た/出ないって取れないんだってね。で、そういうのを検知するにはViewの大きさを監視してサイズに変更があったらキーボードが出てる!と判断するらしいじゃん?

adjustNoneってそういったリサイズイベントとってくれるのかなぁ?って思ったのよ。

PopUpWindowが有るじゃない!

https://developer.android.com/reference/android/widget/PopupWindow.html
コヤツ、SoftwareInputModeがセットできる!
ということはActivityとは別のSoftwareInputModeがセットできるって事だよね?…だよね?

というわけで

こんな感じに

KeyboardHeightProvider.kt
/**
 * ソフトウェアキーボードの高さを計算するやつ
 */
typealias KeyBoardHeightChangedListener = (keyboardHeight: Int) -> Unit

@SuppressLint("InflateParams")
class KeyboardHeightProvider(private val activity: Activity) : PopupWindow() {

    private val measurementView: View by lazy {
        LayoutInflater.from(activity).inflate(R.layout.view_mesurement, null, false)
    }
    private val parentView: View by lazy {
        activity.findViewById<View>(android.R.id.content)
    }

    private var listener: KeyBoardHeightChangedListener? = null

    init {
        softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE or
                WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE
        inputMethodMode = INPUT_METHOD_NEEDED
        contentView = measurementView
        width = 0
        height = WindowManager.LayoutParams.MATCH_PARENT
        measurementView.viewTreeObserver.addOnGlobalLayoutListener {
            calcHeight()
        }
    }

    fun listen(listener: KeyBoardHeightChangedListener) {
        this.listener = listener
    }

    fun start() {
        if (!isShowing && parentView.windowToken != null) {
            showAtLocation(parentView, Gravity.NO_GRAVITY, 0, 0)
        }
    }

    fun stop() {
        dismiss()
        listener = null
    }

    private fun calcHeight() {
        val point = Point()
        activity.windowManager.defaultDisplay.getSize(point)
        val rect = Rect()
        measurementView.getWindowVisibleDisplayFrame(rect)
        listener?.invoke(point.y - rect.bottom)
    }

}
view_mesurement.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="0dp"
    android:layout_height="match_parent" />

こうして使えBA☆

MainActivity.kt
import android.os.Bundle
import android.support.constraint.ConstraintSet
import android.support.v7.app.AppCompatActivity
import com.example.self.edu.firestorechatsample.KeyboardHeightProvider
import com.example.self.edu.firestorechatsample.R
import kotlinx.android.synthetic.main.activity_entory.*

class MainActivity : AppCompatActivity() {

    private val keyboardHeightProvider: KeyboardHeightProvider by lazy {
        KeyboardHeightProvider(this)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        root_container.post {
            keyboardHeightProvider.start()
        }
    }

    override fun onResume() {
        super.onResume()
        keyboardHeightProvider.listen {
            // EditTextをズラしてる
            ConstraintSet().run {
                clone(root_container)
                setMargin(R.id.message, ConstraintSet.BOTTOM, it)
                applyTo(root_container)
            }
        }
    }

    override fun onPause() {
        keyboardHeightProvider.stop()
        super.onPause()
    }

}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/root_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.self.edu.firestorechatsample.view.EntryActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="わーい"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"/>

    <EditText
        android:id="@+id/message"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:hint="メッセージ"
        android:lines="1"
        android:maxLines="1"
        android:layout_marginStart="8dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/send"
        app:layout_constraintHorizontal_chainStyle="spread_inside"/>

    <Button
        android:id="@+id/send"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:text="送信"
        app:layout_constraintTop_toTopOf="@+id/message"
        app:layout_constraintStart_toEndOf="@+id/message"
        app:layout_constraintBottom_toBottomOf="@+id/message"
        app:layout_constraintEnd_toEndOf="parent" />

</android.support.constraint.ConstraintLayout>
manifest.xml
<activity android:name=".view.MainActivity"
    android:windowSoftInputMode="adjustNothing">

captcha.gif

あ、そうそう KotlinAndroidExtensionsつかっておりますです。

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.