web-dev-qa-db-ja.com

EditTextの外側をクリックした後にAndroidでソフトキーボードを隠すには?

わかりました誰もがあなたが実装する必要があるキーボードを隠すことを知っています:

InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);

しかしここで大事なのは、ユーザーがEditTextやsoftKeyboard以外の場所に触れたり選択したりしたときにキーボードを非表示にする方法です。

私は私の親のActivityonTouchEvent()を使用しようとしましたが、それはユーザーが他のビューの外側に触れてスクロールビューがない場合にのみ有効です。

私はタッチ、クリック、フォーカスリスナーを実装することに成功しました。

タッチイベントを傍受するために私自身のスクロールビューを実装しようとさえしましたが、クリックされたビューではなくイベントの座標しか取得できません。

これを行う標準的な方法はありますか? iPhoneでは、本当に簡単でした。

314
htafoya

次のスニペットは単にキーボードを隠します。

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 'の代わりにこのクラスを拡張します。

542
Navneeth G

これを実現するには、次の手順を実行します。

  1. 次の属性を追加して、親ビュー(アクティビティのコンテンツビュー)をクリック可能およびフォーカス可能にします。

        Android:clickable="true" 
        Android:focusableInTouchMode="true" 
    
  2. HideKeyboard()メソッドを実装する

        public void hideKeyboard(View view) {
            InputMethodManager inputMethodManager =(InputMethodManager)getSystemService(Activity.INPUT_METHOD_SERVICE);
            inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
        }
    
  3. 最後に、あなたのedittextのonFocusChangeListenerを設定してください。

        edittext.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                if (!hasFocus) {
                    hideKeyboard(v);
                }
            }
        });
    

以下のコメントの1つで指摘されているように、これは親ビューがScrollViewの場合はうまくいかないかもしれません。そのような場合、clickableとfocusableInTouchModeはScrollViewのすぐ下のビューに追加されるかもしれません。

251
vida

私はその受け入れられた答えを少し複雑に感じます。

これが私の解決策です。メインレイアウトにOnTouchListenerを追加してください。

findViewById(R.id.mainLayout).setOnTouchListener(this)

そして、onTouchメソッドに以下のコードを入れてください。

InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);

こうすれば、すべてのビューを繰り返す必要がなくなります。

55
roepit

私はキーボードを隠すもう一つの解決策を得ました:

InputMethodManager imm = (InputMethodManager) getSystemService(
    Activity.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);

ここでは、showFlagの位置にHIDE_IMPLICIT_ONLYを、hiddenFlagの位置に0を渡します。ソフトキーボードを強制的に閉じます。

37
Saurabh Pareek

さて、私は問題をいくらか解決することに成功しました、私は私の活動の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をクリックしたときに隠れて表示されます。

それでも、よりクリーンで短いソリューションは大歓迎です

16
htafoya

OnFocusChangeListener を使用してください。

例えば:

editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (!hasFocus) {
            hideKeyboard();
        }
    }
});

更新:あなたはまたあなたの活動の中でonTouchEvent()をオーバーライドしてタッチの座標をチェックすることができます。座標がEditTextの外側にある場合は、キーボードを隠します。

13
Sergey Glotov

これを行うには、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);
}

そして私はそれをテストしました、完璧に動作します!

12
Jishi Chen

任意の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;
}

そしてそれがあなたがする必要があるすべてです

11
piavgh

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);
}
11
sumit sonawane

私はこのスレッドがかなり古く、正しい答えが有効であるように思われ、そこに多くの有効な解決策があることを私は知っています、しかし私は以下に述べるアプローチは効率と優雅に関して追加の利益があるかもしれません。

すべてのアクティビティにこの動作が必要なので、クラスActivityから継承したクラスCustomActivityを作成し、 "フック"しました。 dispatchTouchEvent関数。主に2つの条件があります。

  1. フォーカスが変更されず、誰かが現在の入力フィールドの外側をタップしている場合は、IMEを閉じます。
  2. フォーカスが変更され、次にフォーカスされている要素がどの種類の入力フィールドのインスタンスでもない場合は、IMEを閉じます。

これは私の結果です:

@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);
}
8
fje

もっと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> 

それで全部です。 この繰り返しの場合を処理するためにコントローラ(フラグメントまたはアクティビティ)を修正する必要はありません。

7
Phil

私はこれを達成した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;
    }
});
7

Htafoya製のdispatchTouchEventを呼び出す方法が好きでしたが、

  • 私はタイマーの部分を理解していませんでした(なぜダウンタイムの測定が必要なのかわかりませんか?)
  • 私は全てのEditTextを全てのview-changeで登録/登録解除するのは好きではありません(複雑な階層の中ではかなりのviewchangeやedittextがあるかもしれません)

だから、私はこのやや簡単な解決策を作った:

@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つの入力コンポーネントを切り替えたことを示しているので、そのようにします。

6
Christian R.

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を親レイアウトに設定するだけです。

5
Charles Woodson

これは、sjeが提起した問題に対処するための、fjeの答えに対する別のバリ​​エーションです。

ここでの考え方は、アクティビティのdispatchTouchEventname__メソッドでdownアクションとupアクションの両方を処理することです。下のアクションでは、現在フォーカスされているビュー(もしあれば)とタッチがその中にあるかどうかをメモしておき、後で両方の情報を保存します。

アップアクションでは、私たちは最初に別の見方が潜在的に焦点を合わせることを可能にするために派遣します。その後、現在フォーカスされているビューが最初にフォーカスされているビューで、そのビューの内側に下方向のタッチがある場合は、キーボードを開いたままにします。

現在フォーカスされているビューが最初にフォーカスされているビューおよびと異なる場合はEditTextname__で、キーボードも開いたままにします。

それ以外の場合は閉じます。

つまり、要約すると、これは次のように機能します。

  • 現在フォーカスされているEditTextname__内をタッチすると、キーボードは開いたままになります
  • フォーカスされているEditTextname__から別のEditTextname__に移動しても、キーボードは開いたままになります(閉じたり、再度開いたりしません)。
  • 現在フォーカスされているEditTextname__の外側で別のEditTextname__ではない場所をタッチすると、キーボードが閉じます。
  • EditTextname__を長押しして(切り取り/コピー/貼り付けボタンで)コンテキストアクションバーを表示すると、フォーカスのあるEditTextname__の外側でUPアクションが実行されても、キーボードは開いたままです。タクシー)。ただし、CABのボタンをタップするとキーボードが閉じます。それは望ましいかもしれませんしないかもしれません。あるフィールドから切り取り/コピーして別のフィールドに貼り付けたい場合は、そのようになります。同じEditTextname__に貼り付けたい場合、そうではありません。
  • フォーカスされているEditTextname__が画面の一番下にあり、それを選択するためにいくつかのテキストをロングクリックすると、EditTextname__がフォーカスを保ち、それでキーボードは望み通りに開きます。アップアクションではなく、ダウンアクション。

    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);
    }
    
4
Andy Dennie

この単純な要件では、受け入れられた回答は少し複雑です。これは何の問題もなく私のために働いたものです。

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;
        }
    });
4
Joohay

そのコードが単純すぎるので、最近のレイアウトをクリック可能にするには、次のコードでフォーカス可能にしてください。

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);
    }
4
swarnim dixit

ソフトキーボードの表示/非表示方法

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);    
        }

    }

私は彼らが役に立つことを願っています

3
lalosoft

私はメソッドを洗練しました、それがその目的を果たすためにそれがあなたのすべての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を設定してはいけません).

乾杯:)

2
Uzair

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)
}
2

あなたのアクティビティとしてstateHiddenをwindowSoftInputModeの値にしてみてください

http://developer.Android.com/reference/Android/R.attr.html#windowSoftInputMode

例えばあなたの活動のために:

this.getWindow().setSoftInputMode(
    WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
2
Alex Volovoy

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;
                }
            });
2
Alex R. R.

これは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);
}
1
Cadmonkey33

このコードを@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);
}
1
Haseeb Javed

さて、あなたはこのコードを使うことができます、 "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);
        }

    });
1
vinod wakade

この問題を解決するには、まずその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が呼び出され、次に編集テキストからフォーカスがクリアされるようになりました。

1
Sudhanshu Gaur

これは古いかもしれませんが、私はこれをカスタムクラスを実装することで動作させました

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を元気づける---

1
ralphgabb

私はこのようにしました:

@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);
  }

完了

1
Hiren Patel
@Override
    public boolean onTouchEvent(MotionEvent event) {
        InputMethodManager imm = (InputMethodManager)getSystemService(Context.
                INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
        return true;
    }
1
Jeffy

アクティビティ

 @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);
 }
1
icebail

他のアイデアはあなたのアクティビティのためのルートビューのonInterceptTouchEventメソッドをオーバーライドすることです。

Touchイベントは、画面上の一番手前のビュー(touchイベントが発生した場所)からonTouchメソッドを呼び出すビューのスタックを下って、いずれかのビューがtrueを返すまでタッチイベントが消費されたことを示します。多くのビューはデフォルトでtouchイベントを消費するため(たとえば、EditTextTextViewの場合)、イベントはアクティビティのルートビューのonTouchメソッドに到達しません。

しかし、このトラバースを実行する前に、タッチイベントは別のパスをたどり、ルートビューからビューツリーを下って最前面のビューに到達します。この走査はonInterceptTouchEventを呼び出すことによって行われます。もしメソッドがtrueを返したら、それはイベントを傍受します... nahhh、しかしそれはちょっとしたトリックです、私はあなたがそれをしたくも詳細も知らないとは思いません。あなたが知る必要があるのはあなたがあなたの活動のためにルートビューでこのメソッドをオーバーライドすることができて、そして必要なときにキーボードを隠すためにそこにコードを置くことです。

0
Andre Luis IM

キーボードを隠すためにアクティビティとフラグメントの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;
}
0
Ajith Memana

これは私にとって最も簡単な解決策です(そして私が解決しました)。

これはキーボードを隠すための方法です。

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"
0
NullByte08

あなたは以下の方法を試すことができます、それは私のためにとてもうまくいきます:)

この方法は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);
                }
            }
        });
0
Dang Nguyen

onItemClickAutoCompleteTextViewの内側からキーボードを隠すことができました

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
}
0
tony gil

こんにちはみんな私はこの問題の簡単な解決策を持っているし、この解決策は簡単な登録やログインフォームに使用できます。私の解決策は、メインビューの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;
            }
        });
0

私の解決策はあらゆる編集テキストの中で、どんな活動でも外側のクリックでキーボードを隠します。 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ビューを指定する必要はありません。

0
Misha Akopov

私はこれを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);
}
0
AndyMc

私はこの問題を考えました。まず、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)でテストしました。

ドラッグチェックが必要な場合は、ロングクリック、...、上記のコメントを表示してください。

0
Hogun