ちょっと優しい入力項目

3,490 views
3,260 views

Published on

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

Published in: Technology
0 Comments
4 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
3,490
On SlideShare
0
From Embeds
0
Number of Embeds
1,763
Actions
Shares
0
Downloads
2
Comments
0
Likes
4
Embeds 0
No embeds

No notes for slide

ちょっと優しい入力項目

  1. 1. ちょっと優しい 入力項目 2014/1/15 @sakebook http://sakebook.blogspot.com https://github.com/sakebook
  2. 2. こういうときありますよね enterを押すとどうなるか?
  3. 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“/>
  4. 4. 複数ある場合はどうするか? ・SingleLine属性を設定 ➡ 「4」の位置に移動してしまう! 「2」の位置に移動させたい。。
  5. 5. 複数ある場合はどうするか? ・SingleLine属性を設定 + ・NextFocusを指定 + ・OnEditorActionListener を設定
  6. 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“/>
  7. 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できる物がなければこちら }); } } return false; }else { if (event.getAction() == KeyEvent.ACTION_DOWN) { return false; } } return true; //「7」「8」「9」
  8. 8. 複数ある場合はどうするか? ・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できる物がなければこちら }); } } return false; }else { if (event.getAction() == KeyEvent.ACTION_DOWN) { return false; } } return true; なんでkeyEventがnullになるの? //「7」「8」「9」 ! onKeyListenerじゃだめなの?
  9. 9. OnKeyListener TextView.java KeyDown 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 } } break; 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. ((event.getFlags() & KeyEvent.FLAG_EDITOR_ACTION) != 0 || shouldAdvanceFocusOnEnter()) { if (mOnClickListener != null) { return 0; } return -1;
  10. 10. OnKeyListener TextView.java @Override public boolean onKeyUp(int keyCode, KeyEvent event) { if (!isEnabled()) { return super.onKeyUp(keyCode, event); } ! ! KeyUp 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); onKeyListenerでは EditorActionが2回呼ばれる Overrideすると、OnEditorAction が呼ばれない } break;
  11. 11. OnKeyListener TextView.java KeyDown 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 } } break; 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. ((event.getFlags() & KeyEvent.FLAG_EDITOR_ACTION) != 0 || shouldAdvanceFocusOnEnter()) { if (mOnClickListener != null) { return 0; } return -1;
  12. 12. TextView.java ShouldAdvanceFocusOnEnter ! private boolean shouldAdvanceFocusOnEnter() { if (mInput == null) { return false; } if (mSingleLine) { return true; } ! SingleLineを 設定していると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; }
  13. 13. OnKeyListener TextView.java KeyDown 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; } } enterがreturnされるので eventがnullになる ! // // // if } } break; 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. ((event.getFlags() & KeyEvent.FLAG_EDITOR_ACTION) != 0 || shouldAdvanceFocusOnEnter()) { if (mOnClickListener != null) { return 0; } return -1;
  14. 14. TextView.java OnEditorAction public void onEditorAction(int actionCode) { final InputContentType ict = mInputContentType; if (ict != null) { if (ict.onEditorActionListener != null) { if (ict.onEditorActionListener.onEditorAction(this, actionCode, null)) { return; } } Focus移動の メソッドを呼ぶ // // // // // if ! 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. (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; OnEditorActionを ! 呼ぶことでFocus移動 } else if (actionCode == EditorInfo.IME_ACTION_DONE) { InputMethodManager imm = InputMethodManager.peekInstance(); if (imm != null && imm.isActive(this)) { imm.hideSoftInputFromWindow(getWindowToken(), 0); } clearFocus(); return; } }
  15. 15. 複数ある場合はどうするか? ・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できる物がなければこちら }); } } return false; }else { if (event.getAction() == KeyEvent.ACTION_DOWN) { return false; } } return true; NextFocusdown //「7」「8」「9」 NextFocusForward
  16. 16. まとめ • OnKeyListenerでは改行不可およびEnterの
 ハンドリングが実装できる • テキストボックスを変更したい場合は
 SingleLine + NextFocus + OnEditorActionを
 合わせて使おう • NextFocusは対象のViewの位置によって
 指定する属性が異なる • actionIdは対象のViewの位置によって
 値が異なる。EditorInfoの定数を比較に用いる
  17. 17. こんな感じで、 テキストエリアを 隠さずユーザに入力させる ことができます ちょっとだけ 優しい!
  18. 18. 以上

×