我想根据是否显示虚拟键盘来改变布局。我已经搜索了API和各种博客,但似乎找不到任何有用的东西。

这可能吗?

谢谢!


当前回答

如果你想从你的活动中处理IMM(虚拟)键盘窗口的显示/隐藏,你需要子类化你的布局并覆盖onMesure方法(这样你就可以确定你的布局的测量宽度和测量高度)。之后,通过setContentView()将子类布局设置为Activity的主视图。现在您将能够处理IMM显示/隐藏窗口事件。也许这听起来很复杂,但事实并非如此。代码如下:

main。xml

   <?xml version="1.0" encoding="utf-8"?>
   <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="horizontal" >
        <EditText
             android:id="@+id/SearchText" 
             android:text="" 
             android:inputType="text"
             android:layout_width="fill_parent"
             android:layout_height="34dip"
             android:singleLine="True"
             />
        <Button
             android:id="@+id/Search" 
             android:layout_width="60dip"
             android:layout_height="34dip"
             android:gravity = "center"
             />
    </LinearLayout>

现在在布局的Activity声明子类中(main.xml)

    public class MainSearchLayout extends LinearLayout {

    public MainSearchLayout(Context context, AttributeSet attributeSet) {
        super(context, attributeSet);
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        inflater.inflate(R.layout.main, this);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        Log.d("Search Layout", "Handling Keyboard Window shown");

        final int proposedheight = MeasureSpec.getSize(heightMeasureSpec);
        final int actualHeight = getHeight();

        if (actualHeight > proposedheight){
            // Keyboard is shown

        } else {
            // Keyboard is hidden
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

您可以从代码中看到,我们在子类构造函数中为Activity扩展布局

inflater.inflate(R.layout.main, this);

现在只需设置Activity的子类布局的内容视图。

public class MainActivity extends Activity {

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        MainSearchLayout searchLayout = new MainSearchLayout(this, null);

        setContentView(searchLayout);
    }

    // rest of the Activity code and subclassed layout...

}

其他回答

桑德,我相信你是想展示被软键盘挡住的视野。试试这个http://android-developers.blogspot.com/2009/04/updating-applications-for-on-screen.html。

我所做的是创建一个简单的绑定来隐藏视图时,键盘是可见的。 解决方案基于当前AndroidX实现的WindowInsetsCompat,仍处于beta (AndroidX核心1.5)-源代码

private fun isKeyboardVisible(insets: WindowInsets): Boolean {
    val insetsCompat = WindowInsetsCompat.toWindowInsetsCompat(insets)
    val systemWindow = insetsCompat.systemWindowInsets
    val rootStable = insetsCompat.stableInsets
    if (systemWindow.bottom > rootStable.bottom) {
        // This handles the adjustResize case on < API 30, since
        // systemWindow.bottom is probably going to be the IME
        return true
    }
    return false
}

@BindingAdapter("goneWhenKeyboardVisible")
fun View.goneWhenKeyboardVisible(enabled: Boolean) {
    if (enabled) {
        setOnApplyWindowInsetsListener { view, insets ->
            visibility = if (isKeyboardVisible(insets)) GONE else VISIBLE
            insets
        }
    } else {
        setOnApplyWindowInsetsListener(null)
        visibility = VISIBLE
    }
}

用法:

<FrameLayout
                android:id="@+id/bottom_toolbar"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:goneWhenKeyboardVisible="@{true}"
                />

不确定是否有人发布这篇文章。发现这个解决方案简单易用!SoftKeyboard类在gi.github.com上。但是当键盘弹出/隐藏事件回调时,我们需要一个处理程序来正确地在UI上做事情:

/*
Somewhere else in your code
*/
RelativeLayout mainLayout = findViewById(R.layout.main_layout); // You must use your root layout
InputMethodManager im = (InputMethodManager) getSystemService(Service.INPUT_METHOD_SERVICE);

/*
Instantiate and pass a callback
*/
SoftKeyboard softKeyboard;
softKeyboard = new SoftKeyboard(mainLayout, im);
softKeyboard.setSoftKeyboardCallback(new SoftKeyboard.SoftKeyboardChanged()
{

    @Override
    public void onSoftKeyboardHide() 
    {
        // Code here
        new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                    // Code here will run in UI thread
                    ...
                }
            });
    }

    @Override
    public void onSoftKeyboardShow() 
    {
        // Code here
        new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                    // Code here will run in UI thread
                    ...
                }
            });

    }   
});

尽管本页上投票最多的解决方案说,有一个setWindowInsetsAnimationCallback的ViewCompat版本一直工作到Android 21。

所以现在,这个解决方案的方法一直适用于21。

来源:https://developer.android.com/reference/androidx/core/view/ViewCompat setWindowInsetsAnimationCallback (android.view.View androidx.core.view.WindowInsetsAnimationCompat.Callback)

这可能不是最有效的解决方案。但这对我每次都有效……我调用这个函数每当我需要听软键盘。

boolean isOpened = false;

public void setListenerToRootView() {
    final View activityRootView = getWindow().getDecorView().findViewById(android.R.id.content);
    activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {

            int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();
            if (heightDiff > 100) { // 99% of the time the height diff will be due to a keyboard.
                Toast.makeText(getApplicationContext(), "Gotcha!!! softKeyboardup", 0).show();

                if (isOpened == false) {
                    //Do two things, make the view top visible and the editText smaller
                }
                isOpened = true;
            } else if (isOpened == true) {
                Toast.makeText(getApplicationContext(), "softkeyborad Down!!!", 0).show();
                isOpened = false;
            }
        }
    });
}

注意: 如果用户使用浮动键盘,这种方法将导致问题。