わかりました誰もがあなたが実装する必要があるキーボードを隠すことを知っています:
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
しかしここで大事なのは、ユーザーがEditText
やsoftKeyboard以外の場所に触れたり選択したりしたときにキーボードを非表示にする方法です。
私は私の親のActivity
でonTouchEvent()
を使用しようとしましたが、それはユーザーが他のビューの外側に触れてスクロールビューがない場合にのみ有効です。
私はタッチ、クリック、フォーカスリスナーを実装することに成功しました。
タッチイベントを傍受するために私自身のスクロールビューを実装しようとさえしましたが、クリックされたビューではなくイベントの座標しか取得できません。
これを行う標準的な方法はありますか? iPhoneでは、本当に簡単でした。
次のスニペットは単にキーボードを隠します。
public static void hideSoftKeyboard(Activity activity) {
InputMethodManager inputMethodManager =
(InputMethodManager) activity.getSystemService(
Activity.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(
activity.getCurrentFocus().getWindowToken(), 0);
}
これをユーティリティクラスに含めることも、アクティビティ内で定義している場合はactivityパラメータを回避するか、hideSoftKeyboard(this)
を呼び出すこともできます。
最も厄介な部分は、それを呼び出すときです。アクティビティ内のすべてのView
を反復処理するメソッドを作成して、そのコンポーネントへのsetOnTouchListener
が登録されていない場合はinstanceof EditText
であるかどうかを確認し、すべてが適切に機能するようにします。あなたがそれを行う方法を疑問に思っているならば、それは実際には非常に簡単です。これがあなたがすることです、あなたは次のような再帰的な方法を書きます、実際にあなたはセットアップカスタム書体などのように何かをするためにこれを使うことができます...これがその方法です。
public void setupUI(View view) {
// Set up touch listener for non-text box views to hide keyboard.
if (!(view instanceof EditText)) {
view.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
hideSoftKeyboard(MyActivity.this);
return false;
}
});
}
//If a layout container, iterate over children and seed recursion.
if (view instanceof ViewGroup) {
for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
View innerView = ((ViewGroup) view).getChildAt(i);
setupUI(innerView);
}
}
}
それだけです、あなたの活動の中でsetContentView
の後にこのメソッドを呼び出すだけです。どのパラメータを渡すのか疑問に思う場合は、それが親コンテナのid
です。次のようにid
をあなたの親コンテナに割り当てます
<RelativeLayoutPanel Android:id="@+id/parent"> ... </RelativeLayout>
そしてsetupUI(findViewById(R.id.parent))
を呼び出します、それだけです。
これを効果的に使用したい場合は、拡張Activity
を作成してこのメソッドを配置し、アプリケーション内の他のすべてのアクティビティでこのアクティビティを拡張してsetupUI()
メソッドでそのonCreate()
を呼び出すことができます。
それが役に立てば幸い。
複数のアクティビティを使用する場合は、<RelativeLayout Android:id="@+id/main_parent"> ... </RelativeLayout>
のように、親レイアウトに共通のIDを定義します。
それからActivity
からクラスを拡張し、そのsetupUI(findViewById(R.id.main_parent))
内でOnResume()
を定義し、 `` Activityin your program
'の代わりにこのクラスを拡張します。
これを実現するには、次の手順を実行します。
次の属性を追加して、親ビュー(アクティビティのコンテンツビュー)をクリック可能およびフォーカス可能にします。
Android:clickable="true"
Android:focusableInTouchMode="true"
HideKeyboard()メソッドを実装する
public void hideKeyboard(View view) {
InputMethodManager inputMethodManager =(InputMethodManager)getSystemService(Activity.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
最後に、あなたのedittextのonFocusChangeListenerを設定してください。
edittext.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
hideKeyboard(v);
}
}
});
以下のコメントの1つで指摘されているように、これは親ビューがScrollViewの場合はうまくいかないかもしれません。そのような場合、clickableとfocusableInTouchModeはScrollViewのすぐ下のビューに追加されるかもしれません。
私はその受け入れられた答えを少し複雑に感じます。
これが私の解決策です。メインレイアウトにOnTouchListener
を追加してください。
findViewById(R.id.mainLayout).setOnTouchListener(this)
そして、onTouchメソッドに以下のコードを入れてください。
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
こうすれば、すべてのビューを繰り返す必要がなくなります。
私はキーボードを隠すもう一つの解決策を得ました:
InputMethodManager imm = (InputMethodManager) getSystemService(
Activity.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);
ここでは、showFlag
の位置にHIDE_IMPLICIT_ONLY
を、hiddenFlag
の位置に0
を渡します。ソフトキーボードを強制的に閉じます。
さて、私は問題をいくらか解決することに成功しました、私は私の活動のdispatchTouchEventを上書きしました、そこで私はキーボードを隠すために以下を使っています。
/**
* Called to process touch screen events.
*/
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
touchDownTime = SystemClock.elapsedRealtime();
break;
case MotionEvent.ACTION_UP:
//to avoid drag events
if (SystemClock.elapsedRealtime() - touchDownTime <= 150){
EditText[] textFields = this.getFields();
if(textFields != null && textFields.length > 0){
boolean clickIsOutsideEditTexts = true;
for(EditText field : textFields){
if(isPointInsideView(ev.getRawX(), ev.getRawY(), field)){
clickIsOutsideEditTexts = false;
break;
}
}
if(clickIsOutsideEditTexts){
this.hideSoftKeyboard();
}
} else {
this.hideSoftKeyboard();
}
}
break;
}
return super.dispatchTouchEvent(ev);
}
EDIT:getFields()メソッドは、ビュー内のテキストフィールドを含む配列を返すメソッドです。すべてのタッチでこの配列が作成されないようにするために、私はsFieldsという静的配列を作成しました。これはgetFields()メソッドで返されます。この配列は、次のようなonStart()メソッドで初期化されます。
sFields = new EditText[] {mUserField, mPasswordField};
これは完璧ではありません。ドラッグイベントの時間はヒューリスティックに基づいているだけなので、長いクリップを実行しても非表示にならないことがあります。そうでなければ、キーボードは他のEditTextをクリックしたときに隠れて表示されます。
それでも、よりクリーンで短いソリューションは大歓迎です
OnFocusChangeListener を使用してください。
例えば:
editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
hideKeyboard();
}
}
});
更新:あなたはまたあなたの活動の中でonTouchEvent()
をオーバーライドしてタッチの座標をチェックすることができます。座標がEditTextの外側にある場合は、キーボードを隠します。
これを行うには、ActivityにdispatchTouchEventを実装しました。
private EditText mEditText;
private Rect mRect = new Rect();
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
final int action = MotionEventCompat.getActionMasked(ev);
int[] location = new int[2];
mEditText.getLocationOnScreen(location);
mRect.left = location[0];
mRect.top = location[1];
mRect.right = location[0] + mEditText.getWidth();
mRect.bottom = location[1] + mEditText.getHeight();
int x = (int) ev.getX();
int y = (int) ev.getY();
if (action == MotionEvent.ACTION_DOWN && !mRect.contains(x, y)) {
InputMethodManager input = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
input.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
}
return super.dispatchTouchEvent(ev);
}
そして私はそれをテストしました、完璧に動作します!
任意のActivityでpublic boolean dispatchTouchEvent(MotionEvent event)をオーバーライドします(またはActivityのクラスを拡張します)。
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
View view = getCurrentFocus();
boolean ret = super.dispatchTouchEvent(event);
if (view instanceof EditText) {
View w = getCurrentFocus();
int scrcoords[] = new int[2];
w.getLocationOnScreen(scrcoords);
float x = event.getRawX() + w.getLeft() - scrcoords[0];
float y = event.getRawY() + w.getTop() - scrcoords[1];
if (event.getAction() == MotionEvent.ACTION_UP
&& (x < w.getLeft() || x >= w.getRight()
|| y < w.getTop() || y > w.getBottom()) ) {
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getWindow().getCurrentFocus().getWindowToken(), 0);
}
}
return ret;
}
そしてそれがあなたがする必要があるすべてです
Activityの下のコードを上書きするだけです
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (getCurrentFocus() != null) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
}
return super.dispatchTouchEvent(ev);
}
私はこのスレッドがかなり古く、正しい答えが有効であるように思われ、そこに多くの有効な解決策があることを私は知っています、しかし私は以下に述べるアプローチは効率と優雅に関して追加の利益があるかもしれません。
すべてのアクティビティにこの動作が必要なので、クラスActivityから継承したクラスCustomActivityを作成し、 "フック"しました。 dispatchTouchEvent関数。主に2つの条件があります。
これは私の結果です:
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if(ev.getAction() == MotionEvent.ACTION_UP) {
final View view = getCurrentFocus();
if(view != null) {
final boolean consumed = super.dispatchTouchEvent(ev);
final View viewTmp = getCurrentFocus();
final View viewNew = viewTmp != null ? viewTmp : view;
if(viewNew.equals(view)) {
final Rect rect = new Rect();
final int[] coordinates = new int[2];
view.getLocationOnScreen(coordinates);
rect.set(coordinates[0], coordinates[1], coordinates[0] + view.getWidth(), coordinates[1] + view.getHeight());
final int x = (int) ev.getX();
final int y = (int) ev.getY();
if(rect.contains(x, y)) {
return consumed;
}
}
else if(viewNew instanceof EditText || viewNew instanceof CustomEditText) {
return consumed;
}
final InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(viewNew.getWindowToken(), 0);
viewNew.clearFocus();
return consumed;
}
}
return super.dispatchTouchEvent(ev);
}
注意:さらにこれらの属性をルートビューに割り当てることで、すべての入力フィールドに焦点を絞り、入力フィールドがアクティビティの起動に集中できないようにします(コンテンツビューを "フォーカスキャッチャー"にします)。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final View view = findViewById(R.id.content);
view.setFocusable(true);
view.setFocusableInTouchMode(true);
}
もっとKotlin&マテリアルデザインを使った TextInputEditText (このアプローチは EditTextView と互換性があります)...
1.次の属性を追加して、親ビュー(アクティビティ/フラグメントのコンテンツビュー)をクリック可能およびフォーカス可能にします。
Android:focusable="true"
Android:focusableInTouchMode="true"
Android:clickable="true"
2.(例えばViewExtension.ktファイルの中に)すべてのViewの拡張子を作成します。
fun View.hideKeyboard(){
val inputMethodManager = context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.hideSoftInputFromWindow(this.windowToken, 0)
}
3. TextInputEditTextを継承したBaseTextInputEditTextを作成します。ビューがフォーカスされていないときにキーボードを非表示にするには、onFocusChangedメソッドを実装します。
class BaseTextInputEditText(context: Context?, attrs: AttributeSet?) : TextInputEditText(context, attrs){
override fun onFocusChanged(focused: Boolean, direction: Int, previouslyFocusedRect: Rect?) {
super.onFocusChanged(focused, direction, previouslyFocusedRect)
if (!focused) this.hideKeyboard()
}
}
あなたのXMLであなたの真新しいカスタムビューを呼ぶだけです:
<Android.support.design.widget.TextInputLayout
Android:id="@+id/textInputLayout"
...>
<com.your_package.BaseTextInputEditText
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
... />
</Android.support.design.widget.TextInputLayout>
それで全部です。 この繰り返しの場合を処理するためにコントローラ(フラグメントまたはアクティビティ)を修正する必要はありません。
私はこれを達成したAndre Luis IMのソリューションを修正しました。
私はAndre Luiz IMがしたのと同じ方法でソフトキーボードを隠すユーティリティメソッドを作成しました。
public static void hideSoftKeyboard(Activity activity) {
InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
}
しかし、パフォーマンスが悪いすべてのビューにOnTouchListenerを登録するのではなく、ルートビューだけにOnTouchListenerを登録しました。イベントが消費されるまで(デフォルトではEditTextが消費するビューの1つです)、そのイベントがルートビューに到達した場合は消費されなかったため、ソフトキーボードを閉じます。
findViewById(Android.R.id.content).setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
Utils.hideSoftKeyboard(activity);
return false;
}
});
Htafoya製のdispatchTouchEvent
を呼び出す方法が好きでしたが、
だから、私はこのやや簡単な解決策を作った:
@Override
public boolean dispatchTouchEvent(final MotionEvent ev) {
// all touch events close the keyboard before they are processed except EditText instances.
// if focus is an EditText we need to check, if the touchevent was inside the focus editTexts
final View currentFocus = getCurrentFocus();
if (!(currentFocus instanceof EditText) || !isTouchInsideView(ev, currentFocus)) {
((InputMethodManager) getApplicationContext().getSystemService(Context.INPUT_METHOD_SERVICE))
.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
return super.dispatchTouchEvent(ev);
}
/**
* determine if the given motionevent is inside the given view.
*
* @param ev
* the given view
* @param currentFocus
* the motion event.
* @return if the given motionevent is inside the given view
*/
private boolean isTouchInsideView(final MotionEvent ev, final View currentFocus) {
final int[] loc = new int[2];
currentFocus.getLocationOnScreen(loc);
return ev.getRawX() > loc[0] && ev.getRawY() > loc[1] && ev.getRawX() < (loc[0] + currentFocus.getWidth())
&& ev.getRawY() < (loc[1] + currentFocus.getHeight());
}
欠点が1つあります。
あるEditText
から別のEditText
に切り替えると、キーボードの表示と非表示が切り替わります。私の場合は、2つの入力コンポーネントを切り替えたことを示しているので、そのようにします。
Plea:解決策がないことを認識していますが、回答を真剣に受け止めてください。
問題:キーボードから離れた場所をクリックしたり、最小限のコードでテキストを編集したりするときは、ソフトキーボードを使用しないでください。
解決策:Butterknife.として知られる外部ライブラリ
一行解決策:
@OnClick(R.id.activity_signup_layout) public void closeKeyboard() { ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0); }
読みやすい解決策:
@OnClick(R.id.activity_signup_layout)
public void closeKeyboard() {
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
}
説明:アクティビティのXMLレイアウトの親IDにOnClickリスナをバインドします。これにより、(編集テキストやキーボードではなく)レイアウトをクリックすると、コードの一部が非表示になります。キーボード。
例:レイアウトファイルがR.layout.my_layoutでレイアウトIDがR.id.my_layout_idの場合、Butterknifeバインド呼び出しは次のようになります。
(@OnClick(R.id.my_layout_id)
public void yourMethod {
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
}
Butterknifeドキュメントリンク:http://jakewharton.github.io/butterknife/
Plug: ButterknifeはあなたのAndroid開発に革命をもたらします。考慮して下さい。
注意:外部ライブラリButterknifeを使わなくても同じ結果が得られます。上記のようにOnClickListenerを親レイアウトに設定するだけです。
これは、sjeが提起した問題に対処するための、fjeの答えに対する別のバリエーションです。
ここでの考え方は、アクティビティのdispatchTouchEvent
name__メソッドでdownアクションとupアクションの両方を処理することです。下のアクションでは、現在フォーカスされているビュー(もしあれば)とタッチがその中にあるかどうかをメモしておき、後で両方の情報を保存します。
アップアクションでは、私たちは最初に別の見方が潜在的に焦点を合わせることを可能にするために派遣します。その後、現在フォーカスされているビューが最初にフォーカスされているビューで、そのビューの内側に下方向のタッチがある場合は、キーボードを開いたままにします。
現在フォーカスされているビューが最初にフォーカスされているビューおよびと異なる場合はEditText
name__で、キーボードも開いたままにします。
それ以外の場合は閉じます。
つまり、要約すると、これは次のように機能します。
EditText
name__内をタッチすると、キーボードは開いたままになりますEditText
name__から別のEditText
name__に移動しても、キーボードは開いたままになります(閉じたり、再度開いたりしません)。EditText
name__の外側で別のEditText
name__ではない場所をタッチすると、キーボードが閉じます。EditText
name__を長押しして(切り取り/コピー/貼り付けボタンで)コンテキストアクションバーを表示すると、フォーカスのあるEditText
name__の外側でUPアクションが実行されても、キーボードは開いたままです。タクシー)。ただし、CABのボタンをタップするとキーボードが閉じます。それは望ましいかもしれませんしないかもしれません。あるフィールドから切り取り/コピーして別のフィールドに貼り付けたい場合は、そのようになります。同じEditText
name__に貼り付けたい場合、そうではありません。フォーカスされているEditText
name__が画面の一番下にあり、それを選択するためにいくつかのテキストをロングクリックすると、EditText
name__がフォーカスを保ち、それでキーボードは望み通りに開きます。アップアクションではなく、ダウンアクション。
private View focusedViewOnActionDown;
private boolean touchWasInsideFocusedView;
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
focusedViewOnActionDown = getCurrentFocus();
if (focusedViewOnActionDown != null) {
final Rect rect = new Rect();
final int[] coordinates = new int[2];
focusedViewOnActionDown.getLocationOnScreen(coordinates);
rect.set(coordinates[0], coordinates[1],
coordinates[0] + focusedViewOnActionDown.getWidth(),
coordinates[1] + focusedViewOnActionDown.getHeight());
final int x = (int) ev.getX();
final int y = (int) ev.getY();
touchWasInsideFocusedView = rect.contains(x, y);
}
break;
case MotionEvent.ACTION_UP:
if (focusedViewOnActionDown != null) {
// dispatch to allow new view to (potentially) take focus
final boolean consumed = super.dispatchTouchEvent(ev);
final View currentFocus = getCurrentFocus();
// if the focus is still on the original view and the touch was inside that view,
// leave the keyboard open. Otherwise, if the focus is now on another view and that view
// is an EditText, also leave the keyboard open.
if (currentFocus.equals(focusedViewOnActionDown)) {
if (touchWasInsideFocusedView) {
return consumed;
}
} else if (currentFocus instanceof EditText) {
return consumed;
}
// the touch was outside the originally focused view and not inside another EditText,
// so close the keyboard
InputMethodManager inputMethodManager =
(InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(
focusedViewOnActionDown.getWindowToken(), 0);
focusedViewOnActionDown.clearFocus();
return consumed;
}
break;
}
return super.dispatchTouchEvent(ev);
}
この単純な要件では、受け入れられた回答は少し複雑です。これは何の問題もなく私のために働いたものです。
findViewById(R.id.mainLayout).setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
return false;
}
});
そのコードが単純すぎるので、最近のレイアウトをクリック可能にするには、次のコードでフォーカス可能にしてください。
Android:id="@+id/loginParentLayout"
Android:clickable="true"
Android:focusableInTouchMode="true"
それからそのレイアウトのためのメソッドとOnClickListnerを書くので、一番上のレイアウトが触れられたときはどこでもそれはあなたがキーボードを消すためにコードを書くメソッドを呼び出すであろうどこでも。以下は両方のコードです。 // OnCreate()でこれを書く必要があります
yourLayout.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
hideKeyboard(view);
}
});
リスナーから呼び出されるメソッド: -
public void hideKeyboard(View view) {
InputMethodManager imm =(InputMethodManager)getSystemService(Activity.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
ソフトキーボードの表示/非表示方法
InputMethodManager inputMethodManager = (InputMethodManager) currentActivity.getSystemService(Context.INPUT_METHOD_SERVICE);
if (isShow) {
if (currentActivity.getCurrentFocus() == null) {
inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
} else {
inputMethodManager.showSoftInput(currentActivity.getCurrentFocus(), InputMethodManager.SHOW_FORCED);
}
} else {
if (currentActivity.getCurrentFocus() == null) {
inputMethodManager.toggleSoftInput(InputMethodManager.HIDE_NOT_ALWAYS, 0);
} else {
inputMethodManager.hideSoftInputFromInputMethod(currentActivity.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
}
私は彼らが役に立つことを願っています
私はメソッドを洗練しました、それがその目的を果たすためにそれがあなたのすべてのActivityまたはFragmentクラスからアクセスされることができるようにいくつかのUIユーティリティクラス(できれば、必ずしもそうとは限らない)に次のコードを入れます。
public static void serachAndHideSoftKeybordFromView(View view, final Activity act) {
if(!(view instanceof EditText)) {
view.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
hideSoftKeyboard(act);
return false;
}
});
}
if (view instanceof ViewGroup) {
for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
View nextViewInHierarchy = ((ViewGroup) view).getChildAt(i);
serachAndHideSoftKeybordFromView(nextViewInHierarchy, act);
}
}
}
public static void hideSoftKeyboard (Activity activity) {
InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
}
それから、例えばあなたがアクティビティからそれを呼び出す必要があると言い、次のようにそれを呼び出します。
UIutils.serachAndHideSoftKeybordFromView(findViewById(Android.R.id.content), YourActivityName.this);
通知
findViewById(Android.R.id.content)
これは私達に現在のグループのルートビューを与えます(あなたはルートビューにidを設定してはいけません).
乾杯:)
Kotlinでは、次のことができます。すべてのビューを繰り返す必要はありません。フラグメントにも機能します。
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
currentFocus?.let {
val imm: InputMethodManager = getSystemService(
Context.INPUT_METHOD_SERVICE
) as (InputMethodManager)
imm.hideSoftInputFromWindow(it.windowToken, 0)
}
return super.dispatchTouchEvent(ev)
}
あなたのアクティビティとしてstateHiddenをwindowSoftInputMode
の値にしてみてください
http://developer.Android.com/reference/Android/R.attr.html#windowSoftInputMode
例えばあなたの活動のために:
this.getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
IPhoneと同じ問題に基づいて、もっと簡単な方法があります。編集テキストが含まれているタッチイベントの背景のレイアウトをオーバーライドするだけです。アクティビティのOnCreateでこのコードを使用するだけです(login_fondoがルートレイアウトです)。
final LinearLayout llLogin = (LinearLayout)findViewById(R.id.login_fondo);
llLogin.setOnTouchListener(
new OnTouchListener()
{
@Override
public boolean onTouch(View view, MotionEvent ev) {
InputMethodManager imm = (InputMethodManager) mActivity.getSystemService(
Android.content.Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(mActivity.getCurrentFocus().getWindowToken(), 0);
return false;
}
});
これはfjeの答えを少し修正したもので、ほとんどが完全にうまくいきました。
このバージョンではACTION_DOWNを使用しているので、スクロールアクションを実行するとキーボードも閉じます。別のEditTextをクリックしない限り、イベントは伝播されません。これは、EditTextの外側をクリックしても、別のクリック可能オブジェクト上であっても、単にキーボードを閉じることを意味します。
@Override
public boolean dispatchTouchEvent(MotionEvent ev)
{
if(ev.getAction() == MotionEvent.ACTION_DOWN)
{
final View view = getCurrentFocus();
if(view != null)
{
final View viewTmp = getCurrentFocus();
final View viewNew = viewTmp != null ? viewTmp : view;
if(viewNew.equals(view))
{
final Rect rect = new Rect();
final int[] coordinates = new int[2];
view.getLocationOnScreen(coordinates);
rect.set(coordinates[0], coordinates[1], coordinates[0] + view.getWidth(), coordinates[1] + view.getHeight());
final int x = (int) ev.getX();
final int y = (int) ev.getY();
if(rect.contains(x, y))
{
super.dispatchTouchEvent(ev);
return true;
}
}
else if(viewNew instanceof EditText || viewNew instanceof CustomEditText)
{
super.dispatchTouchEvent(ev);
return true;
}
final InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(viewNew.getWindowToken(), 0);
viewNew.clearFocus();
return true;
}
}
return super.dispatchTouchEvent(ev);
}
このコードを@Overideクラスに追加するだけです。
public boolean dispatchTouchEvent(MotionEvent ev) {
View view = getCurrentFocus();
if (view != null && (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_MOVE) && view instanceof EditText && !view.getClass().getName().startsWith("Android.webkit.")) {
int scrcoords[] = new int[2];
view.getLocationOnScreen(scrcoords);
float x = ev.getRawX() + view.getLeft() - scrcoords[0];
float y = ev.getRawY() + view.getTop() - scrcoords[1];
if (x < view.getLeft() || x > view.getRight() || y < view.getTop() || y > view.getBottom())
((InputMethodManager)this.getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow((this.getWindow().getDecorView().getApplicationWindowToken()), 0);
}
return super.dispatchTouchEvent(ev);
}
さて、あなたはこのコードを使うことができます、 "mainRelativeLayout"の代わりにあなたのメインレイアウトIDを使ってください
//hide Soft keyboard on click outside the input text
findViewById(R.id.mainRelativeLayout).setOnClickListener(new
View.OnClickListener() {
@Override
public void onClick(View v) {
InputMethodManager im = (InputMethodManager)
getSystemService(INPUT_METHOD_SERVICE);
im.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(),
0);
}
});
この問題を解決するには、まずそのEdittextのsetOnFocusChangeListenerを使用します。
edittext.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
Log.d("focus", "focus loosed");
// Do whatever you want here
} else {
Log.d("focus", "focused");
}
}
});
そして、あなたがする必要があるのは、そのEdittextを含むアクティビティでdispatchTouchEventをオーバーライドすることです。
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
View v = getCurrentFocus();
if ( v instanceof EditText) {
Rect outRect = new Rect();
v.getGlobalVisibleRect(outRect);
if (!outRect.contains((int)event.getRawX(), (int)event.getRawY())) {
Log.d("focus", "touchevent");
v.clearFocus();
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
}
}
return super.dispatchTouchEvent(event);
}
これで、ユーザーが外側をクリックし、次に最初にこのdispatchTouchEventが呼び出され、次に編集テキストからフォーカスがクリアされるようになりました。
これは古いかもしれませんが、私はこれをカスタムクラスを実装することで動作させました
public class DismissKeyboardListener implements OnClickListener {
Activity mAct;
public DismissKeyboardListener(Activity act) {
this.mAct = act;
}
@Override
public void onClick(View v) {
if ( v instanceof ViewGroup ) {
hideSoftKeyboard( this.mAct );
}
}
}
public void hideSoftKeyboard(Activity activity) {
InputMethodManager imm = (InputMethodManager)
getSystemService(Activity.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);
}
ここでのベストプラクティスは、Helperクラスを作成することです。すべてのコンテナのRelative/Linear Layoutsはこれを実装する必要があります。
****注意してくださいメインのコンテナだけがこのクラスを実装するべきです(最適化のために)****
そしてそれを次のように実装します。
Parent.setOnClickListener( new DismissKeyboardListener(this) );
キーワードthisはActivity用です。だからあなたが断片化しているならあなたはgetActivity()のように使う。
---助けになれば親指を立てる…--- Ralphを元気づける---
私はこのようにしました:
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
View view = getCurrentFocus();
if (view != null && (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_MOVE) && view instanceof EditText && !view.getClass().getName().startsWith("Android.webkit.")) {
int scrcoords[] = new int[2];
view.getLocationOnScreen(scrcoords);
float x = ev.getRawX() + view.getLeft() - scrcoords[0];
float y = ev.getRawY() + view.getTop() - scrcoords[1];
if (x < view.getLeft() || x > view.getRight() || y < view.getTop() || y > view.getBottom())
hideKeyboard(this);
}
return super.dispatchTouchEvent(ev);
}
キーボードコードを隠す:
public static void hideKeyboard(Activity act) {
if(act!=null)
((InputMethodManager)act.getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow((act.getWindow().getDecorView().getApplicationWindowToken()), 0);
}
完了
@Override
public boolean onTouchEvent(MotionEvent event) {
InputMethodManager imm = (InputMethodManager)getSystemService(Context.
INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
return true;
}
アクティビティ
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
ScreenUtils.hideKeyboard(this, findViewById(Android.R.id.content).getWindowToken());
return super.dispatchTouchEvent(ev);
}
ScreenUtils
public static void hideKeyboard(Context context, IBinder windowToken) {
InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(windowToken, InputMethodManager.HIDE_NOT_ALWAYS);
}
他のアイデアはあなたのアクティビティのためのルートビューのonInterceptTouchEvent
メソッドをオーバーライドすることです。
Touchイベントは、画面上の一番手前のビュー(touchイベントが発生した場所)からonTouch
メソッドを呼び出すビューのスタックを下って、いずれかのビューがtrueを返すまでタッチイベントが消費されたことを示します。多くのビューはデフォルトでtouchイベントを消費するため(たとえば、EditText
やTextView
の場合)、イベントはアクティビティのルートビューのonTouch
メソッドに到達しません。
しかし、このトラバースを実行する前に、タッチイベントは別のパスをたどり、ルートビューからビューツリーを下って最前面のビューに到達します。この走査はonInterceptTouchEvent
を呼び出すことによって行われます。もしメソッドがtrueを返したら、それはイベントを傍受します... nahhh、しかしそれはちょっとしたトリックです、私はあなたがそれをしたくも詳細も知らないとは思いません。あなたが知る必要があるのはあなたがあなたの活動のためにルートビューでこのメソッドをオーバーライドすることができて、そして必要なときにキーボードを隠すためにそこにコードを置くことです。
キーボードを隠すためにアクティビティとフラグメントのonKey()イベントを簡単にオーバーライドできます。
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (keyCode == event.KEYCODE_ENTER) {
intiateLoginProcess();
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getWindow().getCurrentFocus()
.getWindowToken(), 0);
return true;
}
}
return false;
}
これは私にとって最も簡単な解決策です(そして私が解決しました)。
これはキーボードを隠すための方法です。
public void hideKeyboard(View view){
if(!(view instanceof EditText)){
InputMethodManager inputMethodManager=(InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(),0);
}
}
xMLファイルのデザインビューから、またはXMLファイルのテキストビューに以下のコードを記述して、アクティビティの親レイアウトのonclick属性を上記のメソッドhideKeyboard
に設定します。
Android:onClick="hideKeyboard"
あなたは以下の方法を試すことができます、それは私のためにとてもうまくいきます:)
この方法はActivityやFragmentにも適用でき、ScrollViewとも互換性があります。
ScrollViewをトップレベルのレイアウトとして配置し、その内部にLinearLayoutのid parentViewを宣言し、次のような2つの属性を追加します。
Android:id="@+id/parentView"
Android:clickable="true"
Android:focusableInTouchMode="true"
コードでは、以下のような関数を書きます。
public static void hideSoftKeyboard (Activity activity) {
InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
}
次に、ルートビューのOnFocusChangeListenerを登録し(onCreateメソッドで書き込み)、影響を受けるActivity内のすべてのEditTextを作成します。
parentLayout.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
hideSoftKeyboard(your_activity_name.this);
}
}
});
onItemClick
AutoCompleteTextView
の内側からキーボードを隠すことができました
public void onItemClick(AdapterView<?> adapterViewIn, View viewIn, int indexSelected, long arg3) {
InputMethodManager imm = (InputMethodManager) getSystemService(viewIn.getContext().INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(viewIn.getApplicationWindowToken(), 0);
// your code HERE
}
こんにちはみんな私はこの問題の簡単な解決策を持っているし、この解決策は簡単な登録やログインフォームに使用できます。私の解決策は、メインビューのios setontouchリスナーに実装したのと同じです。
activity_main.xmlでメインの相対レイアウトにIDを追加しますAndroid:id="@+id/mainlayout"
そしてあなたの活動にこのコードを追加してください
RelativeLayout mainLayout = (RelativeLayout)findViewById(R.id.mainlayout);
mainLayout.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
Log.d("Json Response", "Touch outside");
InputMethodManager inputMethodManager = (InputMethodManager) MainActivity.this.getSystemService(Activity.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(MainActivity.this.getCurrentFocus().getWindowToken(), 0);
return false;
}
});
私の解決策はあらゆる編集テキストの中で、どんな活動でも外側のクリックでキーボードを隠します。 1つずつ指定せずに
最初にレイアウトxmlのルートビューに追加します。Android:clickable = "true" Android:focusableInTouchMode = "true"
次に、キーボードを非表示にするすべてのアクティビティの親Acitvityを1つ作成し、onResume()メソッドを指定します。
@Override
protected void onResume() {
super.onResume();
//getting Root View that gets focus
View rootView =((ViewGroup)findViewById(Android.R.id.content)).
getChildAt(0);
rootView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
hideKeyboard(AbstractActivity.this);
}
}
});
}
この一般的なアクティビティ(継承力!)であなたのアクティビティを拡張すればそれがすべてです。(任意の拡張アクティビティ上の)EditTextがフォーカスを失うたびに、キーボードは隠されます。
P.S hideKeyboardメソッド:
public static void hideKeyboard(Activity context) {
InputMethodManager inputMethodManager = (InputMethodManager) context.getSystemService(Activity.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow( context.getCurrentFocus().getWindowToken(), 0);
}
context.getCurrentFocus()は特定のEditTextビューを指定する必要はありません。
私はこれをFernando Camaragoのソリューションのちょっとしたバリエーションで動かしました。私のonCreateメソッドでは、ルートビューに単一のonTouchListenerをアタッチしますが、アクティビティとしてではなくビューを引数として送信します。
findViewById(Android.R.id.content).setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
Utils.hideSoftKeyboard(v);
return false;
}
});
別のUtilsクラスでは...
public static void hideSoftKeyboard(View v) {
InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
私はこの問題を考えました。まず、setOnTouchListenerは単純な解決策ではないと思います。だから私はdispatchTouchEventが最も簡単な解決策であると信じています。
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_UP) {
View v = getCurrentFocus();
if (v instanceof EditText) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
}
}
return super.dispatchKeyEvent(event);
}
ここで重要なのはACTION_UPです。
EditTextはソフトキーボードのみを表示し、そうでなければキーボードを表示しないと仮定しました。私はAndroid5.0.1(LGのG3.cat6)でテストしました。
ドラッグチェックが必要な場合は、ロングクリック、...、上記のコメントを表示してください。