405

キーボードを非表示にするには、実装する必要があることは誰もが知っています。

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

しかし、ここで重要なのは、ユーザーがソフトキーボード以外の場所をタッチまたは選択したときにキーボードを非表示にする方法EditTextです。

onTouchEvent()親でを使用しようとしましたActivityが、ユーザーが他のビューの外側に触れ、スクロールビューがない場合にのみ機能します。

タッチ、クリック、フォーカス リスナーを実装しようとしましたが、成功しませんでした。

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

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

4

47 に答える 47

604

次のスニペットは、単にキーボードを非表示にします。

public static void hideSoftKeyboard(Activity activity) {
    InputMethodManager inputMethodManager = 
        (InputMethodManager) activity.getSystemService(
            Activity.INPUT_METHOD_SERVICE);
    if(inputMethodManager.isAcceptingText()){
        inputMethodManager.hideSoftInputFromWindow(
                activity.getCurrentFocus().getWindowToken(),
                0
        );
    }
}

これをユーティリティクラスに入れるか、アクティビティ内で定義する場合は、アクティビティパラメータを回避するか、を呼び出しますhideSoftKeyboard(this)

最も難しい部分は、いつそれを呼び出すかです。Viewアクティビティのすべてを反復処理するメソッドを記述し、それがそのコンポーネントにinstanceof EditText登録されていないかどうかを確認すると、すべてが適切に機能します。setOnTouchListenerあなたがそれをどのように行うのか疑問に思っている場合、それは実際には非常に簡単です。これがあなたがすることです、あなたは次のような再帰的なメソッドを書きます、実際あなたはこれを使ってカスタム書体のセットアップなど何でもすることができます...これがメソッドです

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()メソッドで呼び出すことができます。

それが役に立てば幸い。

複数のアクティビティを使用する場合は、次のように親レイアウトに共通IDを定義します。 <RelativeLayout android:id="@+id/main_parent"> ... </RelativeLayout>

次に、クラスを拡張し、その中Activityで定義し、「アクティビティ」の代わりにこのクラスを拡張しますsetupUI(findViewById(R.id.main_parent))OnResume() in your program


上記の関数のKotlinバージョンは次のとおりです。

@file:JvmName("KeyboardUtils")

fun Activity.hideSoftKeyboard() {
    currentFocus?.let {
        val inputMethodManager = ContextCompat.getSystemService(this, InputMethodManager::class.java)!!
        inputMethodManager.hideSoftInputFromWindow(it.windowToken, 0)
    }
}
于 2012-07-25T18:22:03.357 に答える
320

これは、次の手順を実行することで実現できます。

  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 の場合、これは機能しない可能性があります。このような場合、クリック可能で focusableInTouchMode を ScrollView の直下のビューに追加できます。

于 2013-11-07T04:44:53.060 に答える
43

次の方法でキーボードを非表示にするもう1つの解決策があります。

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

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

于 2012-01-03T06:00:43.813 に答える
16

問題をある程度解決することができました。アクティビティで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);
}

編集: getFields() メソッドは、ビュー内のテキスト フィールドを含む配列を返す単なるメソッドです。タッチするたびにこの配列が作成されるのを避けるために、sFields という静的配列を作成しました。これは getFields() メソッドで返されます。この配列は、次のような onStart() メソッドで初期化されます。

sFields = new EditText[] {mUserField, mPasswordField};


完璧ではありません.ドラッグイベント時間はヒューリスティックにのみ基づいているため、長いクリックを実行すると非表示にならないことがあります.また、ビューごとにすべてのeditTextsを取得するメソッドを作成して終了しました. そうしないと、他の EditText をクリックしたときに、キーボードが表示または非表示になります。

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

于 2010-11-12T19:00:56.730 に答える
14

OnFocusChangeListenerを使用します。

例えば:

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

更新:アクティビティをオーバーライドonTouchEvent()して、タッチの座標を確認することもできます。座標が EditText の外側にある場合は、キーボードを非表示にします。

于 2010-11-12T14:20:01.433 に答える
14

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

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

于 2014-05-24T11:25:42.187 に答える
13

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

コトリンのバージョン:

 override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
        val ret = super.dispatchTouchEvent(ev)
        ev?.let { event ->
            if (event.action == MotionEvent.ACTION_UP) {
                currentFocus?.let { view ->
                    if (view is EditText) {
                        val touchCoordinates = IntArray(2)
                        view.getLocationOnScreen(touchCoordinates)
                        val x: Float = event.rawX + view.getLeft() - touchCoordinates[0]
                        val y: Float = event.rawY + view.getTop() - touchCoordinates[1]
                        //If the touch position is outside the EditText then we hide the keyboard
                        if (x < view.getLeft() || x >= view.getRight() || y < view.getTop() || y > view.getBottom()) {
                            val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
                            imm.hideSoftInputFromWindow(view.windowToken, 0)
                            view.clearFocus()
                        }
                    }
                }
            }
        }
        return ret
    }

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

于 2014-07-27T13:21:23.330 に答える
11

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;
    }
});
于 2012-10-12T20:01:35.683 に答える
11

このスレッドはかなり古いものであり、正しい答えは有効であり、有効な解決策がたくさんあることは承知していますが、以下に述べるアプローチには、効率と優雅さに関して追加の利点があると思います.

すべてのアクティビティでこの動作が必要なので、クラス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);
}
于 2013-04-23T18:11:43.993 に答える
6

dispatchTouchEvent私はhtafoyaによって行われた呼び出しのアプローチが好きでしたが、:

  • タイマーの部分がわかりませんでした(ダウンタイムの測定が必要な理由がわかりませんか?)
  • すべてのビュー変更ですべての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つの入力コンポーネントを切り替えたことを示しているため、この方法が望ましいです。

于 2013-03-19T23:32:09.967 に答える
4

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

キーボードを非表示にする方法です。

public void hideKeyboard(View view){
        if(!(view instanceof EditText)){
            InputMethodManager inputMethodManager=(InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);
            inputMethodManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(),0);
        }
    }

hideKeyboardXML ファイルのデザイン ビューから、または XML ファイルのテキスト ビューで以下のコードを記述して、アクティビティの親レイアウトの onclick 属性を上記のメソッドに設定します。

android:onClick="hideKeyboard"
于 2019-06-16T14:16:12.720 に答える
3

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;
                }
            });
于 2012-07-12T08:53:32.510 に答える
3

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

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

    }

それらが役に立ったことを願っています

于 2012-08-10T18:43:37.867 に答える
2

私はメソッドを改良し、次のコードをいくつかの 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 を設定してはいけません)。

乾杯 :)

于 2016-04-22T06:46:19.320 に答える
2

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

于 2016-04-04T19:41:22.107 に答える
2

windowSoftInputModeアクティビティ値として stateHidden をオンにしてみてください

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

たとえば、アクティビティの場合:

this.getWindow().setSoftInputMode(
    WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
于 2010-11-12T15:16:20.317 に答える
2

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);
}
于 2013-03-04T16:48:53.920 に答える
2

View.onClickListener を実装し、onClick メソッドをオーバーライドして、この onclicklistener をレイアウトに設定できます。

ConstraintLayout constraintLayout;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        constraintLayout = findViewById(R.id.layout);
        constraintLayout.setOnClickListener(this);
}
@Override
    public void onClick(View v) {
        if(v.getId()==R.id.layout){
            InputMethodManager inm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
            inm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(),0);
        }
    }
于 2019-12-28T15:24:19.940 に答える
1

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

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

ここでのベスト プラクティスはヘルパー クラスを作成することであり、すべてのコンテナーの相対/線形レイアウトはこれを実装する必要があります。

**** メイン コンテナのみがこのクラスを実装する必要があることに注意してください (最適化のため) ****

次のように実装します。

Parent.setOnClickListener( new DismissKeyboardListener(this) ); 

これはActivityのキーワードです。したがって、フラグメントを使用している場合は、getActivity(); のように使用します。

---それがあなたを助けるなら、親指を立ててください... ---ラルフを応援します---

于 2014-10-17T03:10:54.533 に答える
1

さて、このコードを使用できます。「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);
        }

    });
于 2017-07-16T12:19:39.517 に答える
0

以下の方法を試すことができます。私にとってはうまくいきます:)

この方法は 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);
                }
            }
        });
于 2016-04-10T02:12:58.907 に答える
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) でテストしました。

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

于 2015-04-22T13:01:11.637 に答える
0

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

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

ただし、このトラバーサルを行う前に、タッチ イベントは別のパスをたどり、ルート ビューからビュー ツリーを下って最前面のビューに到達します。この走査は、 を呼び出すことによって行われonInterceptTouchEventます。メソッドが true を返した場合、イベントをインターセプトします... いや、でもそれはちょっとしたトリックです。あなたはそれをしたくないし、詳細を知りたくないと思います。知っておく必要があるのは、Activity のルート ビューでこのメソッドをオーバーライドし、必要に応じてキーボードを非表示にするコードを配置できることです。

于 2010-11-12T14:59:47.530 に答える
0

アクティビティとフラグメントで 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;
}
于 2014-02-13T08:14:11.037 に答える
0

非常に難しい決断。より簡単な解決策を提案します。onViewCreated では、ビュー全体に setOnClickListener を設定し、EditText からフォーカスを削除し、キーボードを削除します。

フラグメントの例。ジャバ。

@Override
public void onViewCreated(View view, Bundle savedInstanceState)
{
    super.onViewCreated(view, savedInstanceState);

    nameTextInputEditText = view.findViewById(R.id.NameTextInputEditText);

    view.setOnClickListener(v -> {
        nameTextInputEditText.clearFocus();

        InputMethodManager imm = (InputMethodManager) requireActivity().getSystemService(Activity.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
    });
}
于 2021-10-13T17:45:08.187 に答える
0

なんとかキーボードを中から隠すことができました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
}
于 2016-12-30T18:56:45.283 に答える
-1
setupUI((RelativeLayout) findViewById(R.id.activity_logsign_up_RelativeLayout));

メソッドをレイアウト ファイルに渡します。XML の共通レイアウト ファイルを選択する必要があります。キーボードの非表示はレイアウト全体で機能するためです。

public void setupUI(View view) {
        // Set up touch listener for non-text box views to hide keyboard.
        if (!(view instanceof EditText)) {
            view.setOnTouchListener(new View.OnTouchListener() {
                public boolean onTouch(View v, MotionEvent event) {
                    hideSoftKeyboard(Your Context); // Pass your context
                    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);
            }
        }
    }
于 2016-11-25T04:45:30.037 に答える