LoginSignup
5
5

More than 5 years have passed since last update.

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

Posted at

はじめに

やっほー
早速だけど、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つかっておりますです。

5
5
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5