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

这可能吗?

谢谢!


当前回答

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

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

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

其他回答

我解决这个问题通过覆盖onkeyprime (int keyCode, KeyEvent事件)在我的自定义EditText。

@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
        //keyboard will be hidden
    }
}

Nebojsa Tomcic的回答对我没有帮助。我有RelativeLayout与TextView和AutoCompleteTextView里面。我需要滚动TextView到底部时,键盘显示,当它被隐藏。为了实现这一点,我重写了onLayout方法,它对我来说很好。

public class ExtendedLayout extends RelativeLayout
{
    public ExtendedLayout(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 onLayout(boolean changed, int l, int t, int r, int b)
    {
        super.onLayout(changed, l, t, r, b);

        if (changed)
        {
            int scrollEnd = (textView.getLineCount() - textView.getHeight() /
                textView.getLineHeight()) * textView.getLineHeight();
            textView.scrollTo(0, scrollEnd);
        }
    }
}

Nebojsa的解决方案几乎对我有效。当我在一个多行EditText中单击时,它知道键盘被显示出来,但是当我开始在EditText中输入时,actualHeight和proposedHeight仍然是相同的,所以它不知道键盘仍然被显示出来。我做了一个轻微的修改,以存储最大高度,它工作得很好。下面是修改后的子类:

public class CheckinLayout extends RelativeLayout {

    private int largestHeight;

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

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        final int proposedheight = MeasureSpec.getSize(heightMeasureSpec);
        largestHeight = Math.max(largestHeight, getHeight());

        if (largestHeight > proposedheight)
            // Keyboard is shown
        else
            // Keyboard is hidden

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

如果你想从你的活动中处理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...

}

基于Nebojsa Tomcic的代码,我开发了以下relativelayout子类:

import java.util.ArrayList;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.RelativeLayout;

public class KeyboardDetectorRelativeLayout extends RelativeLayout {

    public interface IKeyboardChanged {
        void onKeyboardShown();
        void onKeyboardHidden();
    }

    private ArrayList<IKeyboardChanged> keyboardListener = new ArrayList<IKeyboardChanged>();

    public KeyboardDetectorRelativeLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

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

    public KeyboardDetectorRelativeLayout(Context context) {
        super(context);
    }

    public void addKeyboardStateChangedListener(IKeyboardChanged listener) {
        keyboardListener.add(listener);
    }

    public void removeKeyboardStateChangedListener(IKeyboardChanged listener) {
        keyboardListener.remove(listener);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        final int proposedheight = MeasureSpec.getSize(heightMeasureSpec);
        final int actualHeight = getHeight();

        if (actualHeight > proposedheight) {
            notifyKeyboardShown();
        } else if (actualHeight < proposedheight) {
            notifyKeyboardHidden();
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    private void notifyKeyboardHidden() {
        for (IKeyboardChanged listener : keyboardListener) {
            listener.onKeyboardHidden();
        }
    }

    private void notifyKeyboardShown() {
        for (IKeyboardChanged listener : keyboardListener) {
            listener.onKeyboardShown();
        }
    }

}

这工作得很好… 注意,当你的活动的软输入模式设置为" windowmanager . layoutparm . soft_input_adjust_resize "时,这个解决方案才会工作