AndroidのEditText利用時のIMEのKeyEventとEditorAction (ViewPager上で利用するときの注意点)

ViewPager上でEditTextなどを表示してIMEがでた状態で、特定のボタンを押すとPageが切り替わる。とゆう話。

![ime_key_event.png](https://qiita-image-store.s3.amazonaws.com/0/112768/4f5e143d-990b-904f-33f9-69884de80431.png)

# KeyEvent

①と②の左右のArrowのアイコンのボタンは、TextViewに対して以下のようなイベントを発行する。


| Event property　| Value |Value |
| --- | --- |  --- | 
| Action | `KeyEvent.ACTION_DOWN` | ` KeyEvent.UP ` | 
| KeyCode | `KeyEvent.KEYCODE_DPAD_LEFT` | `KeyEvent.KEYCODE_DPAD_RIGHT` | 


したがって、このようにイベントをハンドリングすることができる。

```kotlin
        binding.editText.setOnKeyListener { _, _, event ->          
            if (event.action != KeyEvent.ACTION_DOWN) {
                return@setOnKeyListener false
            }            
            return@setOnKeyListener when (event.keyCode) {
                KeyEvent.KEYCODE_DPAD_LEFT -> {
                    // handle when Push left arrow icon button.
                    false
                }
                KeyEvent.KEYCODE_DPAD_RIGHT -> {
                    // handle when Push right arrow icon button.
                    false
                }
                else -> {
                    true
                }
            }
        }

```

# EditorAction

③の動きを取りたい場合は、 `EditorActionListener` を利用する

```kotlin

        binding.editText.setOnEditorActionListener { _, actionId, _ ->
            return@setOnEditorActionListener when(actionId) {
                EditorInfo.IME_ACTION_DONE -> {
                    // Handle when pushed done button(right bottom)
                     true    
                }
                else -> {                   
                    false
                }                
            }
        }
```

引数は、そのイベントを他に伝播させるかどうか。`true` にして伝播させると、次のFocusableなViewにFocusが行くようになる。

![screencapture-1542264550474.gif](https://qiita-image-store.s3.amazonaws.com/0/112768/b1c15545-c619-4ec2-fc2d-82f74861f2da.gif)


右下のアイコンは、よしなにしてくれる模様。
指定したい場合は、 `android:imeOptions="send" ` のようにする。
https://developer.android.com/reference/android/view/inputmethod/EditorInfo#imeOptions


# ViewPager上で利用するときの注意点

ココでハマった... 

ViewPagerは、KeyEventをInterceptして、ページの切り替えに利用している。
したがって、ViewPager上でEditTextを表示してIMEがでた状態で、 **左右の①か②のボタ押下するとページが切り替わる**


```java 


    /**
     * You can call this function yourself to have the scroll view perform
     * scrolling from a key event, just as if the event had been dispatched to
     * it by the view hierarchy.
     *
     * @param event The key event to execute.
     * @return Return true if the event was handled, else false.
     */
    public boolean executeKeyEvent(@NonNull KeyEvent event) {
        boolean handled = false;
        if (event.getAction() == KeyEvent.ACTION_DOWN) {
            switch (event.getKeyCode()) {
                case KeyEvent.KEYCODE_DPAD_LEFT:
                    if (event.hasModifiers(KeyEvent.META_ALT_ON)) {
                        handled = pageLeft();
                    } else {
                        handled = arrowScroll(FOCUS_LEFT);
                    }
                    break;
                case KeyEvent.KEYCODE_DPAD_RIGHT:
                    if (event.hasModifiers(KeyEvent.META_ALT_ON)) {
                        handled = pageRight();
                    } else {
                        handled = arrowScroll(FOCUS_RIGHT);
                    }
                    break;
                case KeyEvent.KEYCODE_TAB:
                    if (event.hasNoModifiers()) {
                        handled = arrowScroll(FOCUS_FORWARD);
                    } else if (event.hasModifiers(KeyEvent.META_SHIFT_ON)) {
                        handled = arrowScroll(FOCUS_BACKWARD);
                    }
                    break;
            }
        }
        return handled;
    }

```

![screencapture-1542266033868.gif](https://qiita-image-store.s3.amazonaws.com/0/112768/1d8c7134-8820-07cc-1955-fd9a6269c3c1.gif)


切り替えたくない場合は、 `setOnKeyListener`の返り値をfalseにして伝播させないようにする。