ちょっと優しい入力項目

18
ちょっと優しい 入力項目 2014/1/15 @sakebook http://sakebook.blogspot.com https://github.com/sakebook

Upload: shinya-sakemoto

Post on 24-May-2015

2.416 views

Category:

Technology


3 download

DESCRIPTION

Potatotips#3で発表したAndroidのTips。

TRANSCRIPT

Page 1: ちょっと優しい入力項目

ちょっと優しい 入力項目

2014/1/15 @sakebook

http://sakebook.blogspot.com https://github.com/sakebook

Page 2: ちょっと優しい入力項目

こういうときありますよね

enterを押すとどうなるか?

Page 3: ちょっと優しい入力項目

2行になっちゃいます

よくある回避方法・SingleLine属性を設定

<EditText android:id=“@+id/edittext_1" android:layout_width="match_parent" android:layout_height="wrap_content" android:singleLine="true" android:hint=“@string/do_not_enter“/>

Page 4: ちょっと優しい入力項目

複数ある場合はどうするか?

・SingleLine属性を設定

「4」の位置に移動してしまう! 「2」の位置に移動させたい。。

Page 5: ちょっと優しい入力項目

複数ある場合はどうするか?

・SingleLine属性を設定

・NextFocusを指定

・OnEditorActionListener を設定

Page 6: ちょっと優しい入力項目

複数ある場合はどうするか?

・SingleLine属性を設定・NextFocusDownを指定

<EditText android:id=“@+id/edittext_1" android:layout_width="match_parent" android:layout_height="wrap_content" android:singleLine="true" android:nextFocusDown=“@+id/edittext_2” android:hint=“@string/do_not_enter“/>

Page 7: ちょっと優しい入力項目

複数ある場合はどうするか?

・OnEditorActionListener を設定

((EditText)view.findViewById(R.id.edittext_1)).setOnEditorActionListener(new OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { //SingleLineを設定したときはeventがnull if (event == null) { if (actionId == EditorInfo.IME_ACTION_NEXT) { }else if (actionId == EditorInfo.IME_ACTION_DONE) { //対象のViewより下にFocusできる物がなければこちら //「7」「8」「9」 } return false; }else { if (event.getAction() == KeyEvent.ACTION_DOWN) { return false; } } return true; } });

Page 8: ちょっと優しい入力項目

複数ある場合はどうするか?

((EditText)view.findViewById(R.id.edittext_1)).setOnEditorActionListener(new OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { //SingleLineを設定したときはeventがnull if (event == null) { if (actionId == EditorInfo.IME_ACTION_NEXT) { }else if (actionId == EditorInfo.IME_ACTION_DONE) { //対象のViewより下にFocusできる物がなければこちら //「7」「8」「9」 } return false; }else { if (event.getAction() == KeyEvent.ACTION_DOWN) { return false; } } return true; } });

なんでkeyEventがnullになるの? !

onKeyListenerじゃだめなの?

・OnEditorActionListener を設定

Page 9: ちょっと優しい入力項目

private int doKeyDown(int keyCode, KeyEvent event, KeyEvent otherEvent) { if (!isEnabled()) { return 0; } ! switch (keyCode) { case KeyEvent.KEYCODE_ENTER: mEnterKeyIsDown = true; if (event.hasNoModifiers()) { // When mInputContentType is set, we know that we are // running in a "modern" cupcake environment, so don't need // to worry about the application trying to capture // enter key events. if (mInputContentType != null) { // If there is an action listener, given them a // chance to consume the event. if (mInputContentType.onEditorActionListener != null && mInputContentType.onEditorActionListener.onEditorAction( this, EditorInfo.IME_NULL, event)) { mInputContentType.enterDown = true; // We are consuming the enter key for them. return -1; } } ! // If our editor should move focus when enter is pressed, or // this is a generated event from an IME action button, then // don't let it be inserted into the text. if ((event.getFlags() & KeyEvent.FLAG_EDITOR_ACTION) != 0 || shouldAdvanceFocusOnEnter()) { if (mOnClickListener != null) { return 0; } return -1; } } break;

TextView.javaOnKeyListener

KeyDown

Page 10: ちょっと優しい入力項目

@Override public boolean onKeyUp(int keyCode, KeyEvent event) { if (!isEnabled()) { return super.onKeyUp(keyCode, event); } ! switch (keyCode) { ~~ case KeyEvent.KEYCODE_ENTER: mEnterKeyIsDown = false; if (event.hasNoModifiers()) { if (mInputContentType != null && mInputContentType.onEditorActionListener != null && mInputContentType.enterDown) { mInputContentType.enterDown = false; if (mInputContentType.onEditorActionListener.onEditorAction( this, EditorInfo.IME_NULL, event)) { return true; } } ! if ((event.getFlags() & KeyEvent.FLAG_EDITOR_ACTION) != 0 || shouldAdvanceFocusOnEnter()) { /* * If there is a click listener, just call through to * super, which will invoke it. * * If there isn't a click listener, try to advance focus, * but still call through to super, which will reset the * pressed state and longpress state. (It will also * call performClick(), but that won't do anything in * this case.) */ ~~ } return super.onKeyUp(keyCode, event); } break;

TextView.javaOnKeyListener

onKeyListenerでは EditorActionが2回呼ばれる

Overrideすると、OnEditorActionが呼ばれない

KeyUp

Page 11: ちょっと優しい入力項目

private int doKeyDown(int keyCode, KeyEvent event, KeyEvent otherEvent) { if (!isEnabled()) { return 0; } ! switch (keyCode) { case KeyEvent.KEYCODE_ENTER: mEnterKeyIsDown = true; if (event.hasNoModifiers()) { // When mInputContentType is set, we know that we are // running in a "modern" cupcake environment, so don't need // to worry about the application trying to capture // enter key events. if (mInputContentType != null) { // If there is an action listener, given them a // chance to consume the event. if (mInputContentType.onEditorActionListener != null && mInputContentType.onEditorActionListener.onEditorAction( this, EditorInfo.IME_NULL, event)) { mInputContentType.enterDown = true; // We are consuming the enter key for them. return -1; } } ! // If our editor should move focus when enter is pressed, or // this is a generated event from an IME action button, then // don't let it be inserted into the text. if ((event.getFlags() & KeyEvent.FLAG_EDITOR_ACTION) != 0 || shouldAdvanceFocusOnEnter()) { if (mOnClickListener != null) { return 0; } return -1; } } break;

TextView.javaOnKeyListener

KeyDown

Page 12: ちょっと優しい入力項目

private boolean shouldAdvanceFocusOnEnter() { if (mInput == null) { return false; } ! if (mSingleLine) { return true; } ! if ((mInputType & EditorInfo.TYPE_MASK_CLASS) == EditorInfo.TYPE_CLASS_TEXT) { int variation = mInputType & EditorInfo.TYPE_MASK_VARIATION; if (variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS || variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_SUBJECT) { return true; } } ! return false; }

TextView.java

SingleLineを 設定しているとtrueを返す

ShouldAdvanceFocusOnEnter

Page 13: ちょっと優しい入力項目

private int doKeyDown(int keyCode, KeyEvent event, KeyEvent otherEvent) { if (!isEnabled()) { return 0; } ! switch (keyCode) { case KeyEvent.KEYCODE_ENTER: mEnterKeyIsDown = true; if (event.hasNoModifiers()) { // When mInputContentType is set, we know that we are // running in a "modern" cupcake environment, so don't need // to worry about the application trying to capture // enter key events. if (mInputContentType != null) { // If there is an action listener, given them a // chance to consume the event. if (mInputContentType.onEditorActionListener != null && mInputContentType.onEditorActionListener.onEditorAction( this, EditorInfo.IME_NULL, event)) { mInputContentType.enterDown = true; // We are consuming the enter key for them. return -1; } } ! // If our editor should move focus when enter is pressed, or // this is a generated event from an IME action button, then // don't let it be inserted into the text. if ((event.getFlags() & KeyEvent.FLAG_EDITOR_ACTION) != 0 || shouldAdvanceFocusOnEnter()) { if (mOnClickListener != null) { return 0; } return -1; } } break;

TextView.javaOnKeyListener

enterがreturnされるので eventがnullになる

KeyDown

Page 14: ちょっと優しい入力項目

public void onEditorAction(int actionCode) { final InputContentType ict = mInputContentType; if (ict != null) { if (ict.onEditorActionListener != null) { if (ict.onEditorActionListener.onEditorAction(this, actionCode, null)) { return; } } // This is the handling for some default action. // Note that for backwards compatibility we don't do this // default handling if explicit ime options have not been given, // instead turning this into the normal enter key codes that an // app may be expecting. if (actionCode == EditorInfo.IME_ACTION_NEXT) { View v = focusSearch(FOCUS_FORWARD); if (v != null) { if (!v.requestFocus(FOCUS_FORWARD)) { throw new IllegalStateException("focus search returned a view " + "that wasn't able to take focus!"); } } return; ! } else if (actionCode == EditorInfo.IME_ACTION_PREVIOUS) { View v = focusSearch(FOCUS_BACKWARD); if (v != null) { if (!v.requestFocus(FOCUS_BACKWARD)) { throw new IllegalStateException("focus search returned a view " + "that wasn't able to take focus!"); } } return; ! } else if (actionCode == EditorInfo.IME_ACTION_DONE) { InputMethodManager imm = InputMethodManager.peekInstance(); if (imm != null && imm.isActive(this)) { imm.hideSoftInputFromWindow(getWindowToken(), 0); } clearFocus(); return; } }

TextView.java

Focus移動の メソッドを呼ぶ

OnEditorAction

OnEditorActionを 呼ぶことでFocus移動

Page 15: ちょっと優しい入力項目

複数ある場合はどうするか?

((EditText)view.findViewById(R.id.edittext_1)).setOnEditorActionListener(new OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { //SingleLineを設定したときはeventがnull if (event == null) { if (actionId == EditorInfo.IME_ACTION_NEXT) { }else if (actionId == EditorInfo.IME_ACTION_DONE) { //対象のViewより下にFocusできる物がなければこちら //「7」「8」「9」 } return false; }else { if (event.getAction() == KeyEvent.ACTION_DOWN) { return false; } } return true; } });

NextFocusdown

NextFocusForward

・OnEditorActionListener を設定

Page 16: ちょっと優しい入力項目

まとめ• OnKeyListenerでは改行不可およびEnterのハンドリングが実装できる

• テキストボックスを変更したい場合はSingleLine + NextFocus + OnEditorActionを合わせて使おう

• NextFocusは対象のViewの位置によって指定する属性が異なる

• actionIdは対象のViewの位置によって値が異なる。EditorInfoの定数を比較に用いる

Page 17: ちょっと優しい入力項目

こんな感じで、 テキストエリアを

隠さずユーザに入力させる ことができます

ちょっとだけ 優しい!

Page 18: ちょっと優しい入力項目

以上