お久しぶりです。y_a_s_です。
今日は珍しく開発メモを。
プラットフォームはAndroid。
突然ですが、ソフトウェアキーボードってあるじゃないですか。
スマートフォンとかで、文字を打つときに下からニュっと出てくるアレ。
Androidアプリを作ってた時に思ったのですが、こいつ意外と気まぐれですよね。
出てきて欲しい時に出てこないのに、別に今必要じゃないという時に出てきてしまう。
そんな気まぐれさに嫌気がさしてしまいました。
そんな気まぐれさに嫌気がさしてしまいました。
どうにかこれを、バックボタンを押したり、テキストエディットなどをタップしたりせず、自由に扱えないかと調べてみました。
調査時の画面は以下の通りです。
res/layout/main.xml
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical" >
- <Button
- android:id="@+id/button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="Button" />
- <EditText
- android:id="@+id/edit"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"/>
- </LinearLayout>
まずは表示状態のソフトウェアキーボードを、ボタンを押して非表示にする方法。
非表示にするには、 InputMethodManager を利用します。
- InputMethodManager inputMethodMgr = (InputMethodManager)
- getSystemService(Context.INPUT_METHOD_SERVICE);
- inputMethodMgr.hideSoftInputFromWindow(view.getWindowToken(),0);
これだけです。まあ簡単。
コードはこちら。
- public class SoftweraKeyboardTestActivity extends Activity
- {
- @Override
- public void onCreate(Bundle savedInstanceState)
- {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- // ボタンを押したとき
- findViewById(R.id.button).setOnClickListener(new View.OnClickListener()
- {
- @Override
- public void onClick(View v)
- {
- // ソフトウェアキーボードを非表示
- InputMethodManager inputMethodMgr = (InputMethodManager)
- getSystemService(Context.INPUT_METHOD_SERVICE);
- inputMethodMgr.hideSoftInputFromWindow(v.getWindowToken(),0);
- }
- });
- }
- }
ソフトウェアキーボードを表示させるには、画面上のテキストエディットをタップしてました。
コンセプト全否定ですが、ここでは非表示にすることが目的なので御容赦を。
実際の利用には、テキストエディットのフォーカスをクリアして、フォーカスが変更された時に呼び出される onFocusChange() 内で設定した方いいと思います。
次に、Activity起動時に表示されてしまうソフトウェアキーボードを表示させない方法。
これも簡単で、setContentView の前に、下の一文を追加するだけです。
- getWindow().setSoftInputMode(
- WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
問題は、非表示状態のソフトウェアキーボードをボタンを押した時に表示させる方法。
表示させる場合にも InputMethodManager を利用します。
- InputMethodManager inputMethodMgr = (InputMethodManager)
- getSystemService(Context.INPUT_METHOD_SERVICE);
- inputMethodMgr.showSoftInput(view, InputMethodManager.SHOW_FORCED);
これだけ見ると非表示と大して変わらないようにも見えますが、これが罠でした。
結論から言うと、これだけではソフトウェアキーボードは表示できません。
表示させるためには、 showSoftInput の第1引数に渡す、編集可能な View にフォーカスが乗っていなければならないとのこと。
- view.setFocusable(true); // フォーカス可能に設定
- view.requestFocus() ; // フォーカスを当てる
しかもこのフォーカス、動的に乗せようとしても、すぐには乗ってると認識してくれないようです。
駄目だ、やはり自由に扱おうだなんて無理だったのか……。
そう諦めかけたとき、天啓が。
そう諦めかけたとき、天啓が。
あれ、Activity起動時に表示されるんだったら……?
- view.setVisibility(View.INVISIBLE); // ビューを非表示に設定
- view.setVisibility(View.VISIBLE); // ビューを表示に設定
- view.setFocusable(true); // フォーカス可能に設定
- view.requestFocus() ; // フォーカスを当てる
これでフォーカスが認識されました。
正直できると思いませんでした。
正直できると思いませんでした。
以下、ソフトウェアキーボードを表示させるコードです。
- public class SoftweraKeyboardTestActivity extends Activity
- {
- EditText edit;
- @Override
- public void onCreate(Bundle savedInstanceState)
- {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- edit = (EditText)findViewById(R.id.edit);
- findViewById(R.id.button).setOnClickListener(new View.OnClickListener()
- {
- @Override
- public void onClick(View v)
- {
- view.setVisibility(View.INVISIBLE); // ビューを非表示に設定
- view.setVisibility(View.VISIBLE); // ビューを表示に設定
- view.setFocusable(true); // フォーカス可能に設定
- view.requestFocus() ; // フォーカスを当てる
- }
- });
- {
- {
- // ソフトウェアキーボードを表示する
- InputMethodManager inputMethodMgr = (InputMethodManager)
- getSystemService(Context.INPUT_METHOD_SERVICE);
- inputMethodMgr.showSoftInput(v, InputMethodManager.SHOW_FORCED);
- }
- });
- }
- }
最後に、ボタンを押すたびにソフトウェアキーボードの表示と非表示を切り替えるサンプルを。
- public class SoftweraKeyboardTestActivity extends Activity
- {
- EditText edit;
- boolean isShownKeyboard ;
- @Override
- public void onCreate(Bundle savedInstanceState)
- {
- super.onCreate(savedInstanceState);
- getWindow().setSoftInputMode(
- WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
- setContentView(R.layout.main);
- edit = (EditText)findViewById(R.id.edit);
- isShownKeyboard = true;
- // ボタンを押したとき
- findViewById(R.id.button).setOnClickListener(new View.OnClickListener()
- {
- @Override
- public void onClick(View v)
- {
- if(isShownKeyboard)
- {
- isShownKeyboard = false ;
- v.setVisibility(View.INVISIBLE); // ビューを非表示に設定
- v.setVisibility(View.VISIBLE); // ビューを表示に設定
- v.setFocusable(true); // フォーカス可能に設定
- v.requestFocus() ; // フォーカスを当てる
- }
- else
- {
- isShownKeyboard = true;
- edit.clearFocus(); // フォーカスをクリア
- }
- }
- });
- edit.setOnFocusChangeListener(new View.OnFocusChangeListener()
- {
- public void onFocusChange(View v, boolean hasFocus)
- {
- InputMethodManager inputMethodMgr = (InputMethodManager)
- getSystemService(Context.INPUT_METHOD_SERVICE);
- if(hasFocus) // フォーカスを受け取ったとき
- {
- // ソフトキーボードを表示する
- inputMethodMgr.showSoftInput(v, InputMethodManager.SHOW_FORCED);
- }
- else
- {
- // ソフトキーボードを閉じる
- inputMethodMgr.hideSoftInputFromWindow(v.getWindowToken(),0);
- }
- }
- });
- }
- }
p.s.
ここまで書いて、ようやくクラス名の「ソフトウェア」の綴りが "Software" じゃなくて "Softwera" になってることに気がつきました。orz