550

私は非常に簡単なことをする必要があります-ソフトウェアキーボードが表示されているかどうかを調べます。これはAndroidで可能ですか?

4

45 に答える 45

691

新しい回答 が2012年1月25日に追加されました

以下の回答を書いた後、誰かがViewTreeObserverとその友人、バージョン1からSDKに潜んでいるAPIの存在を教えてくれました。

カスタムレイアウトタイプを必要とするのではなく、はるかに簡単な解決策は、アクティビティのルートビューに既知のIDを与えることです。たとえば@+id/activityRoot、GlobalLayoutListenerをViewTreeObserverにフックし、そこからアクティビティのビュールートとウィンドウサイズのサイズの差分を計算します。

final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();
        if (heightDiff > dpToPx(this, 200)) { // if more than 200 dp, it's probably a keyboard...
            // ... do something here
        }
     }
});

次のようなユーティリティを使用する:

public static float dpToPx(Context context, float valueInDp) {
    DisplayMetrics metrics = context.getResources().getDisplayMetrics();
    return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, valueInDp, metrics);
}

簡単!

注: アプリケーションはAndroidマニフェストでこのフラグを設定する必要がありますandroid:windowSoftInputMode="adjustResize"。そうしないと、上記のソリューションは機能しません。

元の回答

はい、それは可能ですが、本来あるべきよりもはるかに困難です。

キーボードがいつ表示されたり消えたりするかを気にする必要がある場合(これは非常に頻繁です)、私が行うことは、最上位のレイアウトクラスをオーバーライドするものにカスタマイズすることですonMeasure()。基本的なロジックは、レイアウト自体がウィンドウの総面積よりも大幅に少ない場合は、ソフトキーボードが表示されている可能性があるということです。

import android.app.Activity;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.widget.LinearLayout;

/*
 * LinearLayoutThatDetectsSoftKeyboard - a variant of LinearLayout that can detect when 
 * the soft keyboard is shown and hidden (something Android can't tell you, weirdly). 
 */

public class LinearLayoutThatDetectsSoftKeyboard extends LinearLayout {

    public LinearLayoutThatDetectsSoftKeyboard(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public interface Listener {
        public void onSoftKeyboardShown(boolean isShowing);
    }
    private Listener listener;
    public void setListener(Listener listener) {
        this.listener = listener;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int height = MeasureSpec.getSize(heightMeasureSpec);
        Activity activity = (Activity)getContext();
        Rect rect = new Rect();
        activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
        int statusBarHeight = rect.top;
        int screenHeight = activity.getWindowManager().getDefaultDisplay().getHeight();
        int diff = (screenHeight - statusBarHeight) - height;
        if (listener != null) {
            listener.onSoftKeyboardShown(diff>128); // assume all soft keyboards are at least 128 pixels high
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);       
    }

    }

次に、アクティビティクラスで...

public class MyActivity extends Activity implements LinearLayoutThatDetectsSoftKeyboard.Listener {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ...
        LinearLayoutThatDetectsSoftKeyboard mainLayout = (LinearLayoutThatDetectsSoftKeyboard)findViewById(R.id.main);
        mainLayout.setListener(this);
        ...
    }


    @Override
    public void onSoftKeyboardShown(boolean isShowing) {
        // do whatever you need to do here
    }

    ...
}
于 2011-01-19T15:42:11.990 に答える
310

うまくいけば、これは誰かを助けるでしょう。

Reuben Scrattonが提供した新しい答えは素晴らしく、非常に効率的ですが、実際には、windowSoftInputModeをadjustResizeに設定した場合にのみ機能します。これをadjustPanに設定した場合でも、彼のコードスニペットを使用してキーボードが表示されているかどうかを検出することはできません。これを回避するために、上記のコードにこの小さな変更を加えました。

final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
    Rect r = new Rect();
    //r will be populated with the coordinates of your view that area still visible.
    activityRootView.getWindowVisibleDisplayFrame(r);
   
    int heightDiff = activityRootView.getRootView().getHeight() - r.height();
    if (heightDiff > 0.25*activityRootView.getRootView().getHeight()) { // if more than 25% of the screen, its probably a keyboard...
        ... do something here
    }
 }
}); 
于 2012-02-02T06:45:31.817 に答える
57

それはコンピューターの観点からは永遠に続いていますが、この質問はまだ信じられないほど関連性があります!

だから私は上記の答えを取り、それらを少し組み合わせて洗練しました...

public interface OnKeyboardVisibilityListener {


    void onVisibilityChanged(boolean visible);
}

public final void setKeyboardListener(final OnKeyboardVisibilityListener listener) {
    final View activityRootView = ((ViewGroup) getActivity().findViewById(android.R.id.content)).getChildAt(0);

    activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

        private boolean wasOpened;

        private final int DefaultKeyboardDP = 100;

        // From @nathanielwolf answer...  Lollipop includes button bar in the root. Add height of button bar (48dp) to maxDiff
        private final int EstimatedKeyboardDP = DefaultKeyboardDP + (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? 48 : 0);

        private final Rect r = new Rect();

        @Override
        public void onGlobalLayout() {
            // Convert the dp to pixels.
            int estimatedKeyboardHeight = (int) TypedValue
                    .applyDimension(TypedValue.COMPLEX_UNIT_DIP, EstimatedKeyboardDP, activityRootView.getResources().getDisplayMetrics());

            // Conclude whether the keyboard is shown or not.
            activityRootView.getWindowVisibleDisplayFrame(r);
            int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
            boolean isShown = heightDiff >= estimatedKeyboardHeight;

            if (isShown == wasOpened) {
                Log.d("Keyboard state", "Ignoring global layout change...");
                return;
            }

            wasOpened = isShown;
            listener.onVisibilityChanged(isShown);
        }
    });
}

私のために働く:)

注:DefaultKeyboardDPがデバイスに適合しない ことに気付いた場合は、値を試して、値を確認するためにコメントを投稿してください...最終的にはすべてのデバイスに適合する正しい値を取得します。

詳細については、サイボーグの実装を確認してください

于 2013-09-24T21:58:44.187 に答える
51

回答が遅れて申し訳ありませんが、リスナーやその他の便利なことを通知するオープン/クローズイベントを処理するための小さなヘルパークラスを作成しました。誰かがそれを役立つと思うかもしれません。

import android.graphics.Rect;
import android.view.View;
import android.view.ViewTreeObserver;

import java.util.LinkedList;
import java.util.List;

public class SoftKeyboardStateWatcher implements ViewTreeObserver.OnGlobalLayoutListener {

    public interface SoftKeyboardStateListener {
        void onSoftKeyboardOpened(int keyboardHeightInPx);
        void onSoftKeyboardClosed();
    }

    private final List<SoftKeyboardStateListener> listeners = new LinkedList<SoftKeyboardStateListener>();
    private final View activityRootView;
    private int        lastSoftKeyboardHeightInPx;
    private boolean    isSoftKeyboardOpened;

    public SoftKeyboardStateWatcher(View activityRootView) {
        this(activityRootView, false);
    }

    public SoftKeyboardStateWatcher(View activityRootView, boolean isSoftKeyboardOpened) {
        this.activityRootView     = activityRootView;
        this.isSoftKeyboardOpened = isSoftKeyboardOpened;
        activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(this);
    }

    @Override
    public void onGlobalLayout() {
        final Rect r = new Rect();
        //r will be populated with the coordinates of your view that area still visible.
        activityRootView.getWindowVisibleDisplayFrame(r);

        final int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
        if (!isSoftKeyboardOpened && heightDiff > 100) { // if more than 100 pixels, its probably a keyboard...
            isSoftKeyboardOpened = true;
            notifyOnSoftKeyboardOpened(heightDiff);
        } else if (isSoftKeyboardOpened && heightDiff < 100) {
            isSoftKeyboardOpened = false;
            notifyOnSoftKeyboardClosed();
        }
    }

    public void setIsSoftKeyboardOpened(boolean isSoftKeyboardOpened) {
        this.isSoftKeyboardOpened = isSoftKeyboardOpened;
    }

    public boolean isSoftKeyboardOpened() {
        return isSoftKeyboardOpened;
    }

    /**
     * Default value is zero {@code 0}.
     *
     * @return last saved keyboard height in px
     */
    public int getLastSoftKeyboardHeightInPx() {
        return lastSoftKeyboardHeightInPx;
    }

    public void addSoftKeyboardStateListener(SoftKeyboardStateListener listener) {
        listeners.add(listener);
    }

    public void removeSoftKeyboardStateListener(SoftKeyboardStateListener listener) {
        listeners.remove(listener);
    }

    private void notifyOnSoftKeyboardOpened(int keyboardHeightInPx) {
        this.lastSoftKeyboardHeightInPx = keyboardHeightInPx;

        for (SoftKeyboardStateListener listener : listeners) {
            if (listener != null) {
                listener.onSoftKeyboardOpened(keyboardHeightInPx);
            }
        }
    }

    private void notifyOnSoftKeyboardClosed() {
        for (SoftKeyboardStateListener listener : listeners) {
            if (listener != null) {
                listener.onSoftKeyboardClosed();
            }
        }
    }
}

使用例:

final SoftKeyboardStateWatcher softKeyboardStateWatcher 
    = new SoftKeyboardStateWatcher(findViewById(R.id.activity_main_layout);

// Add listener
softKeyboardStateWatcher.addSoftKeyboardStateListener(...);
// then just handle callbacks
于 2013-10-14T05:53:19.090 に答える
35

高密度デバイスでソフトキーボードの可視性を誤って検出しないようにするためのいくつかの改善点:

  1. 高さの差のしきい値は、 128ピクセルではなく、128dpとして定義する必要があります。メトリックとグリッドについては、 Googleのデザインドキュメント を参照してください。タッチオブジェクトの場合は48 dpが快適なサイズで、ボタンの場合は32dpが最小です。一般的なソフトキーボードには4行のキーボタンが含まれている必要があるため、キーボードの最小の高さは 32 dp * 4 = 128 dpである必要があります。つまり、しきい値サイズはデバイス密度を掛けてピクセルに転送する必要があります。xxxhdpiデバイス(密度4)の場合、ソフトキーボードの高さのしきい値は128 * 4=512ピクセルである必要があります。

  2. ルートビューとその表示領域の高さの差:
    ルートビューの高さ-ステータスバーの高さ-表示されるフレームの高さ=ルートビューの下部-表示されるフレームの下部。ステータスバーの高さはルートビューの表示されるフレームの上部に等しいためです。

    private final String TAG = "TextEditor";
    private TextView mTextEditor;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_editor);
        mTextEditor = (TextView) findViewById(R.id.text_editor);
        mTextEditor.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                isKeyboardShown(mTextEditor.getRootView());
            }
        });
    }
    
    private boolean isKeyboardShown(View rootView) {
        /* 128dp = 32dp * 4, minimum button height 32dp and generic 4 rows soft keyboard */
        final int SOFT_KEYBOARD_HEIGHT_DP_THRESHOLD = 128;
    
        Rect r = new Rect();
        rootView.getWindowVisibleDisplayFrame(r);
        DisplayMetrics dm = rootView.getResources().getDisplayMetrics();
        /* heightDiff = rootView height - status bar height (r.top) - visible frame height (r.bottom - r.top) */
        int heightDiff = rootView.getBottom() - r.bottom;
        /* Threshold size: dp to pixels, multiply with display density */
        boolean isKeyboardShown = heightDiff > SOFT_KEYBOARD_HEIGHT_DP_THRESHOLD * dm.density;
    
        Log.d(TAG, "isKeyboardShown ? " + isKeyboardShown + ", heightDiff:" + heightDiff + ", density:" + dm.density
                + "root view height:" + rootView.getHeight() + ", rect:" + r);
    
        return isKeyboardShown;
    }
    
于 2014-10-02T00:00:01.387 に答える
26

うわー、私たちは良いニュースのAndroidオタクを持っています。そして、古いやり方に別れを告げる時が来ました。まず、これらのメソッド/クラスを読んで理解するための公式リリースノートを追加します。次に、これらのすばらしいメソッド/クラスを確認します。

速報:これらのクラス/メソッドがリリースされるまで、これらをリリースアプリに追加しないでください

キーボードの視認性を確認する方法

val insets = ViewCompat.getRootWindowInsets(view)
val isKeyboardVisible = insets.isVisible(Type.ime())

他のいくつかのユーティリティ

キーボードの高さを取得する方法

val insets = ViewCompat.getRootWindowInsets(view)
val keyboardHeight = insets.getInsets(Type.ime()).bottom

キーボードの表示/非表示の方法

val controller = view.windowInsetsController

// Show the keyboard
controller.show(Type.ime())

// Hide the keyboard
controller.hide(Type.ime())

注:WindowInsetsControllerはAPI-30で追加されているため、下位互換性のあるクラスが使用できなくなるまで待ちます。

キーボードの非表示/表示イベントを聞く方法

ViewCompat.setOnApplyWindowInsetsListener(view) { v, insets ->
    val isKeyboardVisible = insets.isVisible(Type.ime())
    if (isKeyboardVisible) {
        // Do it when keyboard is being shown
    } else {
        // Do it when keyboard is hidden
    }

    // Return the insets to keep going down this event to the view hierarchy
    insets
}
于 2020-08-26T10:38:44.947 に答える
7

これを理解するために少し時間を使用しました...いくつかのCastExceptionsを実行しましたが、layout.xmlのLinearLayoutをクラスの名前に置き換えることができることがわかりました。

このような:

<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent"
    xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/llMaster">

<com.ourshoppingnote.RelativeLayoutThatDetectsSoftKeyboard android:background="@drawable/metal_background"
    android:layout_width="fill_parent" android:layout_height="fill_parent"
    android:id="@+id/rlMaster" >
    <LinearLayout android:layout_width="fill_parent"
        android:layout_height="1dip" android:background="@drawable/line"></LinearLayout>

          ....

</com.ourshoppingnote.RelativeLayoutThatDetectsSoftKeyboard>    


</LinearLayout>

そうすれば、キャストの問題に遭遇することはありません。

...すべてのページでこれを実行したくない場合は、「AndroidのMasterPage」を使用することをお勧めします。こちらのリンクを参照してください:http: //jnastase.alner.net/archive/2011/01/08/ldquomaster-pagesrdquo-in-android.aspx

于 2011-07-09T07:39:14.743 に答える
7

キーボードを非表示にすると同時にソフト入力状態を確認する必要がある場合は、次の解決策を使用するという考え方です。

public boolean hideSoftInput() {
    InputMethodManager imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
    return imm.hideSoftInputFromWindow(mViewPager.getWindowToken(), 0);
}

非表示にする前にキーボードが表示された場合、このメソッドはtrueを返します。

于 2013-12-06T13:01:22.187 に答える
6

WifiKeyboardなどの一部のキーボードの高さがゼロであるため、要素の高さのチェックは信頼できません。

代わりに、showSoftInput()とhideSoftInput()のコールバック結果を使用して、キーボードのステータスを確認できます。完全な詳細とサンプルコードは

https://rogerkeays.com/how-to-check-if-the-software-keyboard-is-shown-in-android

于 2012-02-20T23:50:07.663 に答える
4

違いのコーディングを想定する代わりに、アプリケーションにメニューオプションがあったので、このようなことをしました。

final View root= findViewById(R.id.myrootview); 
root.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
    public void onGlobalLayout() {
        int heightDiff = root.getRootView().getHeight() - root.getHeight();

        Rect rectgle= new Rect();
        Window window= getWindow();
        window.getDecorView().getWindowVisibleDisplayFrame(rectgle);
        int contentViewTop=                     
          window.findViewById(Window.ID_ANDROID_CONTENT).getTop();
        if(heightDiff <= contentViewTop){
            //Soft KeyBoard Hidden
        }else{
            //Soft KeyBoard Shown
        }
     }
});
于 2012-09-29T09:32:11.423 に答える
4

アクティビティのdecorViewを使用して、ソフトキーボードの非表示を確認できます。

public final class SoftKeyboardUtil {
    public static final String TAG = "SoftKeyboardUtil";
    public static void observeSoftKeyBoard(Activity activity , final OnSoftKeyBoardHideListener listener){
        final View decorView = activity.getWindow().getDecorView();
        decorView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                Rect rect = new Rect();
                decorView.getWindowVisibleDisplayFrame(rect);
                int displayHight = rect.bottom - rect.top;
                int hight = decorView.getHeight();
                boolean hide = (double)displayHight / hight > 0.8 ;
                if(Log.isLoggable(TAG, Log.DEBUG)){
                    Log.d(TAG ,"DecorView display hight = "+displayHight);
                    Log.d(TAG ,"DecorView hight = "+ hight);
                    Log.d(TAG, "softkeyboard visible = " + !hide);
                }

                listener.onSoftKeyBoardVisible(!hide);

            }
        });
    }



    public interface OnSoftKeyBoardHideListener{
        void onSoftKeyBoardVisible(boolean visible);
    }
}
于 2014-01-23T05:34:17.893 に答える
4

API >= 21システムインセットを使用したソリューションもありますが、 ( )でのみ機能しAndroid Lます。BottomNavigationViewの子でありLinearLayout、キーボードが表示されたときに非表示にする必要があるとします。

> LinearLayout
  > ContentView
  > BottomNavigationView

あなたがする必要があるのはLinearLayoutそのような方法で拡張することです:

public class KeyboardAwareLinearLayout extends LinearLayout {
    public KeyboardAwareLinearLayout(Context context) {
        super(context);
    }

    public KeyboardAwareLinearLayout(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public KeyboardAwareLinearLayout(Context context,
                                     @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public KeyboardAwareLinearLayout(Context context, AttributeSet attrs,
                                     int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
        int childCount = getChildCount();
        for (int index = 0; index < childCount; index++) {
            View view = getChildAt(index);
            if (view instanceof BottomNavigationView) {
                int bottom = insets.getSystemWindowInsetBottom();
                if (bottom >= ViewUtils.dpToPx(200)) {
                    // keyboard is shown
                    view.setVisibility(GONE);
                } else {
                    // keyboard is hidden
                    view.setVisibility(VISIBLE);
                }
            }
        }
        return insets;
    }
}

キーボードが表示されると、システムのインセットがかなり大きな.bottom値で変更されるという考え方です。

于 2018-02-15T15:38:53.647 に答える
4

これを助けることができる隠された方法があります、InputMethodManager.getInputMethodWindowVisibleHeight。しかし、なぜそれが隠されているのかわかりません。

import android.content.Context
import android.os.Handler
import android.view.inputmethod.InputMethodManager

class SoftKeyboardStateWatcher(private val ctx: Context) {
  companion object {
    private const val DELAY = 10L
  }

  private val handler = Handler()
  private var isSoftKeyboardOpened: Boolean = false

  private val height: Int
    get() {
      val imm = ctx.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
      val method = imm.javaClass.getMethod("getInputMethodWindowVisibleHeight")
      method.isAccessible = true
      return method.invoke(imm) as Int
    }

  private val task: Runnable by lazy {
    Runnable {
      start()
      if (!isSoftKeyboardOpened && height > 0) {
        isSoftKeyboardOpened = true
        notifyOnSoftKeyboardOpened(height)
      } else if (isSoftKeyboardOpened && height == 0) {
        isSoftKeyboardOpened = false
        notifyOnSoftKeyboardClosed()
      }
    }
  }

  var listener: SoftKeyboardStateListener? = null

  interface SoftKeyboardStateListener {
    fun onSoftKeyboardOpened(keyboardHeightInPx: Int)
    fun onSoftKeyboardClosed()
  }

  fun start() {
    handler.postDelayed(task, DELAY)
  }

  fun stop() {
    handler.postDelayed({
      if (!isSoftKeyboardOpened) handler.removeCallbacks(task)
    }, DELAY * 10)
  }

  private fun notifyOnSoftKeyboardOpened(keyboardHeightInPx: Int) {
    listener?.onSoftKeyboardOpened(keyboardHeightInPx)
  }

  private fun notifyOnSoftKeyboardClosed() {
    listener?.onSoftKeyboardClosed()
  }
}
于 2018-05-22T04:30:43.097 に答える
3

@Reuben_Scrattonのメソッドと@Yogeshのメソッドの組み合わせが最適であることがわかりました。それらのメソッドを組み合わせると、次のようになります。

final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
  @Override
  public void onGlobalLayout() {
    if (getResources().getConfiguration().keyboardHidden == Configuration.KEYBOARDHIDDEN_NO) { // Check if keyboard is not hidden
       // ... do something here
    }
  }
});
于 2012-01-31T21:44:16.580 に答える
3

私はReubanの回答のわずかな変形を使用しました。これは、特定の状況、特に高解像度デバイスでより役立つことが証明されました。

final View activityRootView = findViewById(android.R.id.content);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(
        new OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                int heightView = activityRootView.getHeight();
                int widthView = activityRootView.getWidth();
                if (1.0 * widthView / heightView > 3) {
                    //Make changes for Keyboard not visible
                } else {
                    //Make changes for keyboard visible
                }
            }
        });
于 2014-02-21T22:07:22.497 に答える
3

これらのソリューションはいずれも、Lollipopではそのままでは機能しません。LollipopactivityRootView.getRootView().getHeight()にはボタンバーの高さが含まれていますが、ビューの測定には含まれていません。Lollipopで動作するように、上記の最良/最も単純なソリューションを採用しました。

    final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
  @Override
  public void onGlobalLayout() {
    Rect r = new Rect();
    //r will be populated with the coordinates of your view that area still visible.
    activityRootView.getWindowVisibleDisplayFrame(r);

    int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
    Resources res = getResources();
    // The status bar is 25dp, use 50dp for assurance
    float maxDiff =
        TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, res.getDisplayMetrics());

    //Lollipop includes button bar in the root. Add height of button bar (48dp) to maxDiff
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
      float buttonBarHeight =
          TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 48, res.getDisplayMetrics());
      maxDiff += buttonBarHeight;
    }
    if (heightDiff > maxDiff) { // if more than 100 pixels, its probably a keyboard...
      ...do something here
    }
  }
});
于 2014-11-18T23:01:27.850 に答える
3

上記のソリューションのほとんどを使用しているときに、固定数を追加することを提案するバグに遭遇しました。

S4はdpiが高いため、ナビゲーションバーの高さは100ピクセルであるため、私のアプリはキーボードが常に開いていると考えています。

したがって、すべての新しい高解像度電話がリリースされているので、ハードコードされた値を使用することは長期的には良い考えではないと思います。

さまざまな画面やデバイスでテストした後、私が見つけたより良いアプローチは、パーセンテージを使用することでした。DecorViewとurアプリのコンテンツの違いを取得し、その後、その違いのパーセンテージを確認します。私が得た統計から、ほとんどのナビゲーションバー(サイズ、解像度などに関係なく)は画面の3%から5%を占めます。キーボードが開いているかのように、画面の47%から55%を占めていました。

結論として、私の解決策は、差分が10%を超えているかどうかを確認し、キーボードが開いていると想定することでした。

于 2015-06-04T02:40:04.417 に答える
3

それはコンピューターの観点からは永遠に続いていますが、この質問はまだ信じられないほど関連性があります!だから私は上記の答えを取り、それらを少し組み合わせて洗練しました...

public interface OnKeyboardVisibilityListener {
    void onVisibilityChanged(boolean visible);
}

public final void setKeyboardListener(final OnKeyboardVisibilityListener listener) {
    final View activityRootView = ((ViewGroup) getActivity().findViewById(android.R.id.content)).getChildAt(0);
    activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

        private boolean wasOpened;

    private final Rect r = new Rect();

        @Override
        public void onGlobalLayout() {
            activityRootView.getWindowVisibleDisplayFrame(r);

            int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
            boolean isOpen = heightDiff > 100;
            if (isOpen == wasOpened) {
                logDebug("Ignoring global layout change...");
                return;
            }

            wasOpened = isOpen;
            listener.onVisibilityChanged(isOpen);
        }
    });
}

わたしにはできる。

于 2016-12-16T08:24:31.220 に答える
3

これを試して:

final View activityRootView = getWindow().getDecorView().getRootView();
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        Rect r = new Rect();
        //r will be populated with the coordinates of your view that area still visible.
        activityRootView.getWindowVisibleDisplayFrame(r);

        int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
        if (heightDiff < activityRootView.getRootView().getHeight() / 4 ) { // if more than 100 pixels, its probably a keyboard...
             // ... do something here ... \\
        }
    }
});
于 2017-10-24T15:33:51.417 に答える
2

ハードコードを作成しないでください。最良の方法は、キーボード表示でEditTextにフォーカスを取得しているときにビューのサイズを変更する必要があることです。以下のコードを使用して、アクティビティのサイズ変更プロパティをマニフェストファイルに追加することができます。

android:windowSoftInputMode="adjustResize"

于 2014-10-14T22:57:44.233 に答える
2

私の答えは基本的にカチの答えと同じですが、アプリ全体での使用方法をクリーンアップするために、それを素敵なヘルパークラスにラップしました。

import android.app.Activity;
import android.app.Fragment;
import android.graphics.Rect;
import android.view.View;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;

/**
 * Detects Keyboard Status changes and fires events only once for each change
 */
public class KeyboardStatusDetector {
    KeyboardVisibilityListener visibilityListener;

    boolean keyboardVisible = false;

    public void registerFragment(Fragment f) {
        registerView(f.getView());
    }

    public void registerActivity(Activity a) {
        registerView(a.getWindow().getDecorView().findViewById(android.R.id.content));
    }

    public KeyboardStatusDetector registerView(final View v) {
        v.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                Rect r = new Rect();
                v.getWindowVisibleDisplayFrame(r);

                int heightDiff = v.getRootView().getHeight() - (r.bottom - r.top);
                if (heightDiff > 100) { // if more than 100 pixels, its probably a keyboard...
                    /** Check this variable to debounce layout events */
                    if(!keyboardVisible) {
                        keyboardVisible = true;
                        if(visibilityListener != null) visibilityListener.onVisibilityChanged(true);
                    }
                } else {
                    if(keyboardVisible) {
                        keyboardVisible = false;
                        if(visibilityListener != null) visibilityListener.onVisibilityChanged(false);
                    }
                }
            }
        });

        return this;
    }

    public KeyboardStatusDetector setVisibilityListener(KeyboardVisibilityListener listener) {
        visibilityListener = listener;
        return this;
    }

    public static interface KeyboardVisibilityListener {
        public void onVisibilityChanged(boolean keyboardVisible);
    }
}

これを使用して、次のようにアプリ全体のどこでもキーボードの変更を検出できます。

    new KeyboardStatusDetector()
            .registerFragment(fragment)  //register to a fragment 
            .registerActivity(activity)  //or register to an activity
            .registerView(view)          //or register to a view
            .setVisibilityListener(new KeyboardVisibilityListener() {
                @Override
                public void onVisibilityChanged(boolean keyboardVisible) {
                    if(keyboardVisible) {
                       //Do stuff for keyboard visible
                    }else {
                       //Do stuff for keyboard hidden
                    }
                }
            });

注:「登録」呼び出しの1つのみを使用してください。それらはすべて同じように機能し、便宜上そこにあるだけです

于 2014-10-17T15:48:02.857 に答える
2

この方法は、キーボードが表示されているかどうかを確認するのに役立つと思います。

 public Boolean isSoftKeyBoardVisible(){
    InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);

    if (imm.isAcceptingText()) {
        Log.d(TAG,"Software Keyboard was shown");
        return true;
    } else {
        Log.d(TAG,"Software Keyboard was not shown");
        return false;
    }

}
于 2015-01-27T10:38:25.650 に答える
2

あなたはこれを試すことができます、私のために素晴らしい働きをします:

InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);

if (imm.isAcceptingText()) {
    //Software Keyboard was shown..
} else {
    //Software Keyboard was not shown..
}
于 2015-04-16T00:12:53.663 に答える
2

ビューページャー内のフラグメントの向きを変更するときに、キーボードの状態を維持するのに苦労していました。理由はわかりませんが、不安定なようで、標準のアクティビティとは動作が異なります。

この場合、キーボードの状態を維持するには、最初にをに追加android:windowSoftInputMode = "stateUnchanged"する必要がありますAndroidManifest.xml。ただし、これで問題全体が実際に解決されるわけではないことに気付くかもしれません。方向を変更する前にキーボードを開いていた場合、キーボードが開かなかったのです。他のすべてのケースでは、動作は正しいように見えました。

次に、ここで説明したソリューションの1つを実装する必要があります。私が見つけた最もクリーンなものはGeorgeMaisuradzeのものでした-hideSoftInputFromWindowからのブールコールバックを使用してください:

InputMethodManager imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
return imm.hideSoftInputFromWindow(mViewPager.getWindowToken(), 0);

この値をFragmentのonSaveInstanceStateメソッドに保存し、取得しましたonCreateonCreateView次に、値がの場合はキーボードを強制的にtrue表示しました(フラグメントが破棄される前にキーボードが実際に非表示になる前に表示されている場合はtrueを返します)。

于 2017-08-21T00:13:50.467 に答える
2

ドキュメントによると..https ://developer.android.com/reference/androidx/core/view/WindowInsetsCompat

リリースノートを確認して ください。https://developer.android.com/jetpack/androidx/releases/core#1.5.0-alpha02

現在のキーボードの可視性を取得するには、を使用してから関数getRootWindowInsetsを呼び出し、isVisible()IMEタイプを渡します。

val windowinsetscompat = ViewCompat.getRootWindowInsets(view)
val imeVisible = windowinsetscompat.isVisible(Type.ime())

変更のリスナーもありますOnApplyWindowInsetsListener

ViewCompat.setOnApplyWindowInsetsListener(view) { v, insets ->
    val imeVisible = insets.isVisible(Type.ime())
}
于 2020-09-04T06:14:09.913 に答える
1

これが私の解決策であり、それは機能します。ピクセルサイズを探す代わりに、コンテンツビューの高さが変更されているかどうかを確認してください。

// Scroll to the latest comment whenever the keyboard is shown
commentsContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

        private int oldHeight;

        @Override
        public void onGlobalLayout() {
            int newHeight = commentsContent.getMeasuredHeight();
            if (newHeight < oldHeight) {
                // Check for the keyboard showing in case the height difference
                // is a result of orientation change
                if (isSoftKeyboardShowing(CommentsActivity.this)) {
                    // Keyboard is showing so scroll to the latest comment
                    scrollToLatestComment();
                }
            }
            oldHeight = newHeight;
        }

    });


public static boolean isSoftKeyboardShowing(Activity activity) {
    InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
    return inputMethodManager.isActive();
}
于 2014-07-03T16:04:46.863 に答える
1

これを見つけるための直接的な方法があります。また、レイアウトを変更する必要はありません。
そのため、没入型フルスクリーンモードでも機能します。

秘訣は、ソフトキーボードを非表示または表示して、その結果をキャプチャしようとすることです。
慌てる必要はありません。これは実際にはキーボードを表示または非表示にしません。状態をお願いします。

最新の状態に保つには、ハンドラーを使用して、たとえば200ミリ秒ごとに操作を繰り返すだけです。

ここに実装があります:https ://stackoverflow.com/a/27567074/2525452

于 2014-12-19T15:32:10.243 に答える
1

さまざまな解像度の問題のいくつかを理解した後、相対サイズを使用することにしました。私が気づいたように、可視状態と非表示状態の違いは約30%です。そこで、128PXを0.3に置き換えることにしました。

そして、変更を通知するためにこのクラスリスナーを追加しました。

これが私のバージョンです

import android.app.*;
import android.graphics.*;
import android.view.*;

public class SoftKeyboardState {
  public static final int HIDDEN = 0, VISIBLE = 1;
  private OnKeyboardStateChangedListener listener;
  private View decorView;

  public SoftKeyboardState(Activity activity) {
    this.decorView = activity.findViewById(android.R.id.content);
    initKeyboardListener();
  }

  private void initKeyboardListener() {
    decorView.getViewTreeObserver().addOnGlobalLayoutListener(
      new ViewTreeObserver.OnGlobalLayoutListener(){
        private final Rect windowVisibleDisplayFrame = new Rect();
        private int lastVisibleDecorViewHeight;

        @Override
        public void onGlobalLayout() {
          decorView.getWindowVisibleDisplayFrame(windowVisibleDisplayFrame);
          final int visibleDecorViewHeight = windowVisibleDisplayFrame.height();

          if (lastVisibleDecorViewHeight != 0) {
            if ((lastVisibleDecorViewHeight > visibleDecorViewHeight) && (lastVisibleDecorViewHeight / visibleDecorViewHeight >= 0.3f)) {
              // visible
              if (listener != null)listener.onKeyboardStateChanged(VISIBLE);
            } else if ((lastVisibleDecorViewHeight < visibleDecorViewHeight) && (visibleDecorViewHeight / lastVisibleDecorViewHeight >= 0.3f)) {
              // hidden
              if (listener != null)listener.onKeyboardStateChanged(HIDDEN);
            }
          }
          lastVisibleDecorViewHeight = visibleDecorViewHeight;
        }
      });
  }

  public void setOnKeyboardStateChangedListener(OnKeyboardStateChangedListener listener) {
    this.listener = listener;
  }

  public interface OnKeyboardStateChangedListener {
    public void onKeyboardStateChanged(int state);
  }
}
于 2017-11-13T08:02:25.090 に答える
1

ここでのソリューションの99%は、IME WINDOW SIZEの確率に基づいており、そのようなソリューションはどれも価値があります。

なぜなら:

  1. オーバーレイ-ユーザーアプリまたはシステムアプリから
  2. IMEには最小サイズがなく、ウィンドウサイズの100%を占める可能性があり、開発者の実装を想像するほど薄くすることができます:)
  3. モーダルウィンドウ/マルチウィンドウ
  4. そして、IPCの知識がないような多くの人がいます(例:外部ウィンドウまたはそのコンテンツ検出)

したがって、IMEであると推測することは常に間違っています-推測しないでください!!!

@ kevin-duは、IMEの高さのクエリIMMとして現在最適なソリューションですが、メソッドは非表示のAPIであるため、誤った開発の使用により、誤った「偽陰性の結果」を取得する可能性があります。

于 2019-10-05T13:46:04.470 に答える
0

int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();半透明のステータスバーモードを設定した場合、Reuben Scrattonの新しい回答(HeightDiffを計算 )はアクティビティで機能しません。

半透明のステータスバーを使用するactivityRootView.getHeight()と、ソフトキーボードが表示される天気が変わることはありません。常にアクティビティの高さとステータスバーを返します。

たとえば、Nexus 4、Android 5.0.1android:windowTranslucentStatusをtrueに設定すると、imeが開いていても、永久に1184が返されます。falseに設定android:windowTranslucentStatusすると、Heightが正しく返され、imeが非表示の場合は、1134(ステータスバーは含まれません)が返されます。imeを閉じると、おそらく5xxが返されます(imeの高さに依存します)。

天気がバグかどうかはわかりません。4.4.4と5.0.1を試してみましたが、結果は同じです。

したがって、これまでのところ、2番目に合意された答えであるKachiのソリューションは、imeの高さを計算するための最も安全な方法になります。これがコピーです:

final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new        OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
Rect r = new Rect();
//r will be populated with the coordinates of your view that area still visible.
activityRootView.getWindowVisibleDisplayFrame(r);

int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
if (heightDiff > 100) { // if more than 100 pixels, its probably a keyboard...
    ... do something here
    }
 }
}); 
于 2015-03-24T12:45:49.407 に答える
0

LayoutListenerを必要としないメソッド

私の場合、フラグメントを交換する前にキーボードの状態を保存したいと思います。からメソッド hideSoftInputFromWindowonSaveInstanceStateを呼び出します。これにより、キーボードが閉じられ、キーボードが表示されているかどうかが返されます。

この方法は簡単ですが、キーボードの状態が変わる可能性があります。

于 2015-05-26T08:24:37.193 に答える
0

このソリューションはキーボードを再び開く可能性がありますが、機能します。

InputMethodManager inputManager = ( (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE) );

private boolean isKeyboardShowing() {

    boolean isKeyboardShowing = inputManager.hideSoftInputFromWindow(irrelevantView.getWindowToken(), 0);
    if (isKeyboardShowing) {
        inputManager.showSoftInput(this.getCurrentFocus(), 0);
    }
    return isKeyboardShowing;
}
于 2015-06-23T14:49:40.223 に答える
0

これは古い投稿であることは知っていますが、これは私が知っている最も簡単なアプローチであり、テストデバイスはNexus5です。他のデバイスでは試していません。私のコードが良くないと思ったら、他の人が彼らのアプローチを共有することを願っています:)

public static boolean isKeyboardShown(Context context, View view) {
        if (context == null || view == null) {
            return false;
        }
        InputMethodManager imm = (InputMethodManager) context
                .getSystemService(Context.INPUT_METHOD_SERVICE);
        return imm.hideSoftInputFromWindow(view.getWindowToken(), 0); 
}

imm.hideSoftInputFromWindowはブール値を返します。

ありがとう、

于 2015-07-20T08:17:42.943 に答える
0
if (keyopen())
{
                InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY,0);            
}

上記の関数は、キーボードが表示されているかどうかを確認するために使用します。もしそうなら、私はそれを閉じます。

以下に、必要な2つの方法を示します。

まず、onCreateで実行可能なウィンドウの高さを定義します。

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

//  add to onCreate method
    Rect rectgle= new Rect();
    Window window= getWindow();
    window.getDecorView().getWindowVisibleDisplayFrame(rectgle);
    sheight= rectgle.bottom;
//

} 

次に、そのインスタンスでウィンドウの高さを取得するブールメソッドを追加します。オリジナルと一致しない場合(途中で変更していないと仮定して...)、キーボードは開いています。

public boolean keyopen()
{
    Rect rectgle= new Rect();
    Window window= getWindow();
    window.getDecorView().getWindowVisibleDisplayFrame(rectgle);
    int curheight= rectgle.bottom;

    if (curheight!=sheight)
    {
        return true;
    }
    else
    {
        return false;
    }
}

フロッツ!

于 2015-08-11T18:58:22.007 に答える
0

キーボードが非表示になっているかどうかをどれだけ正確に判断できるかを知っています。

public int getStatusBarHeight() {
    int result = 0;
    int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
    if (resourceId > 0) {
        result = getResources().getDimensionPixelSize(resourceId);
    }
    return result;
}

public int getNavigationBarHeight() {
    int result = 0;
    int resourceId = getResources().getIdentifier("navigation_bar_height", "dimen", "android");
    if (resourceId > 0) {
        result = getResources().getDimensionPixelSize(resourceId);
    }
    return result;
}

public boolean isKeyboardHidden() {
    int delta = mRootView.getRootView().getHeight() - mRootView.getHeight() - getNavigationBarHeight() - getStatusBarHeight()
            - getSupportActionBar().getHeight();
    return delta <= 0;
}

これはタブレットで機能します。ナビゲーションバーが水平に表示されている場合。

于 2015-09-30T06:15:46.637 に答える
0

キーボードが表示されている場合に返されるInputMethodManager.isActiveメソッドを使用できます。true

    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.isActive();

特定のビューでキーボードがアクティブかどうかも確認できます。

    imm.isActive(View v);
于 2016-01-15T18:00:43.853 に答える
0

Reuben ScrattonとKachiが提供するソリューションは、デバイスのピクセル密度に依存しているようです。高密度のデバイスを使用している場合、キーボードを押した状態でも高さの差が100を超える可能性があります。これを回避するには、最初の高さの違い(キーボードを下にした状態)を確認してから、現在の違いと比較します。

boolean isOpened = false;
int firstHeightDiff = -1;

public void setListenerToRootView(){
    final View activityRootView = getActivity().getWindow().getDecorView().findViewById(android.R.id.content);
    Rect r = new Rect();
    activityRootView.getWindowVisibleDisplayFrame(r);
    firstHeightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
    activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            if (isAdded()) {
                Rect r = new Rect();
                activityRootView.getWindowVisibleDisplayFrame(r);
                int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
                isOpened = heightDiff>firstHeightDiff+100;
                if (isAdded())
                    if(isOpened) {
                        //TODO stuff for when it is up
                    } else {
                        //TODO stuf for when it is down
                    }
            }
        }
    });
}
于 2016-03-11T19:07:41.400 に答える
0

ソフトキーボードが表示されているかどうかを確認するための回避策を次に示します。

  1. ActivityManager.getRunningServices(max_count_of_services);を使用して、システムで実行中のサービスを確認します。
  2. 返されたActivityManager.RunningServiceInfoインスタンスから、ソフトキーボードサービスのclientCount値を確認します。
  3. 前述のclientCountは毎回インクリメントされ、ソフトキーボードが表示されます。たとえば、clientCountが最初に1だった場合、キーボードが表示されているときは2になります。
  4. キーボードを閉じると、clientCountがデクリメントされます。この場合、1にリセットされます。

人気のあるキーボードの中には、classNamesに特定のキーワードが含まれているものがあります。

Google AOSP = IME
Swype = IME
Swiftkey = KeyboardService
Fleksy = keyboard
Adaptxt = IME (KPTAdaptxtIME)
Smart = Keyboard (SmartKeyboard)

ActivityManager.RunningServiceInfoから、ClassNamesで上記のパターンを確認します。また、ActivityManager.RunningServiceInfoのclientPackage = androidは、キーボードがシステムにバインドされていることを示します。

上記の情報を組み合わせて、ソフトキーボードが表示されているかどうかを厳密に確認することができます。

于 2016-06-01T12:52:43.440 に答える
0

このコードは非常にうまく機能します

ルートビューにこのクラスを使用します。

public class KeyboardConstraintLayout extends ConstraintLayout {

private KeyboardListener keyboardListener;
private EditText targetEditText;
private int minKeyboardHeight;
private boolean isShow;

public KeyboardConstraintLayout(Context context) {
    super(context);
    minKeyboardHeight = getResources().getDimensionPixelSize(R.dimen.keyboard_min_height);
}

public KeyboardConstraintLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
    minKeyboardHeight = getResources().getDimensionPixelSize(R.dimen.keyboard_min_height);
}

public KeyboardConstraintLayout(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    minKeyboardHeight = getResources().getDimensionPixelSize(R.dimen.keyboard_min_height);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    if (!isInEditMode()) {
        Activity activity = (Activity) getContext();
        @SuppressLint("DrawAllocation")
        Rect rect = new Rect();
        getWindowVisibleDisplayFrame(rect);

        int statusBarHeight = rect.top;
        int keyboardHeight = activity.getWindowManager().getDefaultDisplay().getHeight() - (rect.bottom - rect.top) - statusBarHeight;

        if (keyboardListener != null && targetEditText != null && targetEditText.isFocused()) {
            if (keyboardHeight > minKeyboardHeight) {
                if (!isShow) {
                    isShow = true;
                    keyboardListener.onKeyboardVisibility(true);
                }
            }else {
                if (isShow) {
                    isShow = false;
                    keyboardListener.onKeyboardVisibility(false);
                }
            }
        }
    }
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

public boolean isShowKeyboard() {
    return isShow;
}

public void setKeyboardListener(EditText targetEditText, KeyboardListener keyboardListener) {
    this.targetEditText = targetEditText;
    this.keyboardListener = keyboardListener;
}

public interface KeyboardListener {
    void onKeyboardVisibility (boolean isVisible);
}

}

キーボードリスナーをアクティビティまたはフラグメントに設定します。

    rootLayout.setKeyboardListener(targetEditText, new KeyboardConstraintLayout.KeyboardListener() {
    @Override
    public void onKeyboardVisibility(boolean isVisible) {

    }
});
于 2018-05-22T16:14:02.517 に答える
0

多分これはあなたを助けるでしょう:

InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
于 2019-03-07T10:28:12.190 に答える
0

@ TacB0sSによるこの回答を参照して、Kotlinで1つのクラスを開発しました。これがお役に立てば幸いです。改善が必要な場合はお知らせください。

class KeyboardVisibilityObserver(val layRootContainer: View?, val keyboardVisibilityListener: KeyboardVisibilityListener?) {
    var isKeyboardOpen = false
        private set

    private var keyBoardObserver = object : ViewTreeObserver.OnGlobalLayoutListener {

        private val DefaultKeyboardDP = 100

        // Lollipop includes button bar in the root. Add height of button bar (48dp) to maxDiff
        private val EstimatedKeyboardDP = DefaultKeyboardDP + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) 48 else 0

        private val r = Rect()

        override fun onGlobalLayout() {
            if (layRootContainer != null) {
                // Convert the dp to pixels.
                val estimatedKeyboardHeight = TypedValue
                        .applyDimension(TypedValue.COMPLEX_UNIT_DIP, EstimatedKeyboardDP.toFloat(), layRootContainer.resources.displayMetrics).toInt()

                // Conclude whether the keyboard is shown or not.
                layRootContainer.getWindowVisibleDisplayFrame(r)
                val heightDiff = layRootContainer.rootView.height - (r.bottom - r.top)
                val isShown = heightDiff >= estimatedKeyboardHeight

                if (isShown == isKeyboardOpen) {
                    //  Log.d("Keyboard state", "Ignoring global layout change...");
                    return
                }

                isKeyboardOpen = isShown

                keyboardVisibilityListener?.onKeyboardVisibilityChanged(isKeyboardOpen)
            }
        }
    }

    init {
        layRootContainer?.viewTreeObserver?.addOnGlobalLayoutListener(keyBoardObserver)
    }

    // call this in onDestroy
    fun removeObserver(){
        layRootContainer?.viewTreeObserver?.removeOnGlobalLayoutListener(keyBoardObserver)
    }

    interface KeyboardVisibilityListener {
        fun onKeyboardVisibilityChanged(isKeyboardOpen: Boolean)
    }
}
于 2019-11-12T20:58:18.727 に答える
0

正解に加えて、フラグメント内でWebビューを使用する場合、onCreateViewの最後にこれを追加する必要がありました。

getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);

フラグメント内でWebviewを実行しているためか、API 30で新しい動作を実行しているためか、キーボードが表示されていてもフラグメントの高さが変更されないことが問題でした。

したがって、フラグメントの場合、コード全体は次のようになります。

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = super.onCreateView(inflater, container, savedInstanceState);
    //mWebView.postUrl("https://www.google.com/");
    final View activityRootView = view;
    layoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            Rect r = new Rect();
            //r will be populated with the coordinates of your view that area still visible.
            activityRootView.getWindowVisibleDisplayFrame(r);
            // This variable was created only for Debug purposes and 
            // to see the height change when clicking on a field inside mWebView
            int screenHeight = activityRootView.getRootView().getHeight();
            Log.d("onGlobalLayout", "rect: " + r.toString());
            Log.d("onGlobalLayout", "screenHeight: " + screenHeight);

            //The difference on the heights from bottom to top and on the root height
            int heightDiff = screenHeight - (r.bottom - r.top);
            Log.d("onGlobalLayout", "heightDiff: " + heightDiff);

            //I suggest to put 250 on resources to have better order
            float dpx = dpToPx(getActivity(), 250);

            if (previousHeightDiff != heightDiff) {
                if (heightDiff > dpx) {
                    isSoftKeyboardPresent = true;
                } else {
                    isSoftKeyboardPresent = false;
                }
                previousHeightDiff = heightDiff;
            }
        }
    };
    activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(layoutListener);
    getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
    return view;
}

private static float dpToPx(Context context, float valueInDp) {
    DisplayMetrics metrics = context.getResources().getDisplayMetrics();
    return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, valueInDp, metrics);
}
于 2021-02-10T22:19:19.800 に答える
0

キーボードが開くため、これはおそらく本番環境には適していません。同様の関数によって返されるブール値はAPIで指定されていないため、信頼性が低いことに注意してください。こちらのドキュメントを参照してください...

https://developer.android.com/reference/android/view/inputmethod/InputMethodManager#showSoftInput(android.view.View,%20int,%20android.os.ResultReceiver)

public boolean showSoftInput (View view, 
            int flags, 
            ResultReceiver resultReceiver)

このメソッドはResultReceiverを使用することに注意してください。結果を取得できます:RESULT_UNCHANGED_SHOWN、RESULT_UNCHANGED_HIDDEN、RESULT_SHOWN、またはRESULT_HIDDEN。RESULT_UNCHANGED_SHOWNを取得すると、キーボードが表示されていました。閉じていても閉じたままにする必要がある場合は、閉じる必要があります。

于 2021-02-28T04:21:05.550 に答える
0

View#setOnApplyWindowInsetsListenerを使用して、ウィンドウインセットコールバックを取得できます

public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
    getListenerInfo().mOnApplyWindowInsetsListener = listener;
}

//OnApplyWindowInsetsListener
public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);

そしてboolean keyboardVisible = insets.isVisible(WindowInsets.Type.ime())、可視性の状態を与えることができます。

于 2021-06-15T05:17:21.877 に答える
-3

InputMethodManagerには、ソフトキーボードに関する情報があります。次の方法でアクティビティから取得します。

((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE))

あなたはそれがあなたに何を伝えることができるかを見るためにそれで遊んでいるかもしれません。ソフト入力を表示または非表示にするために使用できます...

于 2010-01-27T23:49:46.303 に答える