目的
EditText以外の部分をタップしてキーボードを閉じる処理のメモ
個人的に結構厄介な設定だと思いました。
親のレイアウトによって、設定が変わりますし、Fragment上でもさらに設定方法が変わるようです。
バージョン
- Android Studio 3.5
- Java
- Kotlin
Javaでの実装方法
まずxmlを説明します。
EditTextの他に、ダミーとなるTextView
を用意します。
そこに
android:focusable="true"
とandroid:focusableInTouchMode="true"
を設定することが必要だと思いました。
ダミー
ってなんぞ!?というと。
EditText以外の部分をタップしたときの代わりにターゲットとなるオブジェクト
のことを言っています。
伝わりづらい方はおまじないと思っても。
<TextView
android:id="@+id/view"
android:layout_width="0dp"
android:layout_height="0dp"
android:focusable="true"
android:focusableInTouchMode="true"
tools:ignore="MissingConstraints" />
<EditText
android:id="@+id/edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="100dp"
app:layout_constraintTop_toTopOf="parent" />
次にJavaコードの説明です。
Activityの場合以下のようになります。
画面外タップをonTouchEvent
で判定し、他オブジェクト(上で言ってたダミー
)にフォーカスを当てます。
キーボード非表示のhideSoftInputFromWindow
も必要です。
public class MainActivity extends AppCompatActivity {
private TextView view;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
view = findViewById(R.id.idtext);
EditText edittext = findViewById(R.id.registinheritEdit1);
edittext.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if(!hasFocus) {
//キーボード非表示
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
if (imm != null) {
imm.hideSoftInputFromWindow(v.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
}
}
});
}
@Override
public boolean onTouchEvent(MotionEvent event) {
view.requestFocus();
return super.onTouchEvent(event);
}
}
ただ、
親Layoutがdrawerlayout
やListView
とかですとonTouchEventが呼ばれないようです。
その時はdispatchTouchEvent
を利用します。
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
view.requestFocus();
return super.dispatchTouchEvent(ev);
}
Fragmentの場合
Activityの場合は上記でよいですが、
Fragmentですと、これまた別の処理が必要です。
この辺がAndroid野ややこしい所。。
FragmentでもTouchEvent
が呼ばれないようなので、
onCreateView
で、以下の設定をするべきと思いました。
view.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_MOVE){
}
return true;
}
});
挙動
挙動については以下のようになります。
kotlinでの実装
次にkotlin言語での説明です。
xmlはJavaの時と変わらずです。
ただ、kotlinの場合はFragment
だけでのメモです。
edittext.setOnFocusChangeListener { v, hasFocus ->
if (!hasFocus) {
//キーボード非表示
val imm = activity?.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(v.windowToken, InputMethodManager.HIDE_NOT_ALWAYS)
}
}
view.setOnTouchListener { v, event ->
view.requestFocus()
v?.onTouchEvent(event) ?: true
}
メモは以上です。