參考項目KeyboardVisibilityEventandroid
一、AndroidManifest.xml中activity不設置android:windowSoftInputMode屬性或者設置爲adjustUnspecifiedgit
二、修改事後的KeyboardVisibilityEvent代碼github
public class KeyboardVisibilityEvent { private final static int KEYBOARD_VISIBLE_THRESHOLD_DP = 100; /** * Set keyboard visibility change event listener. * * @param activity Activity * @param listener KeyboardVisibilityEventListener */ public static void setEventListener(final Activity activity, final boolean isFullScreen, final KeyboardVisibilityEventListener listener) { if (activity == null) { throw new NullPointerException("Parameter:activity must not be null"); } if (listener == null) { throw new NullPointerException("Parameter:listener must not be null"); } final View activityRoot = getActivityRoot(activity); activityRoot.getViewTreeObserver().addOnGlobalLayoutListener( new ViewTreeObserver.OnGlobalLayoutListener() { private final Rect rootViewRect = new Rect(); private final int visibleThreshold = getVisibleThreshold(activity); private boolean wasOpened = false; @Override public void onGlobalLayout() { activityRoot.getWindowVisibleDisplayFrame(rootViewRect); int heightDiff = activityRoot.getRootView().getHeight() - rootViewRect.height(); if(!isFullScreen) { heightDiff -= getStatusBarHeight(activity); } boolean isOpen = heightDiff > visibleThreshold; if (isOpen == wasOpened) { // keyboard state has not changed return; } wasOpened = isOpen; listener.onVisibilityChanged(isOpen, heightDiff); } }); } /** * Determine if keyboard is visible * * @param activity Activity * @return Whether keyboard is visible or not */ public static boolean isKeyboardVisible(Activity activity) { Rect r = new Rect(); View activityRoot = getActivityRoot(activity); int visibleThreshold = getVisibleThreshold(activity); activityRoot.getWindowVisibleDisplayFrame(r); int heightDiff = activityRoot.getRootView().getHeight() - r.height(); return heightDiff > visibleThreshold; } public static int getVisibleThreshold(Context context) { return Math.round(UIUtil.convertDpToPx(context, KEYBOARD_VISIBLE_THRESHOLD_DP)); } private static View getActivityRoot(Activity activity) { return ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0); } private static int getStatusBarHeight(Context context) { int result = 0; int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android"); if (resourceId > 0) { result = context.getResources().getDimensionPixelSize(resourceId); } return result; } }
三、佈局文件ide
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <RelativeLayout android:id="@+id/rl_bottom" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="match_parent" android:layout_height="200dp" android:gravity="center_horizontal|top" android:layout_alignParentTop="true" android:text="頂部" android:textColor="#ff0000"/> <TextView android:layout_width="match_parent" android:layout_height="200dp" android:gravity="center" android:layout_centerInParent="true" android:text="中間" android:textColor="#ff0000"/> <TextView android:layout_width="match_parent" android:layout_height="200dp" android:gravity="center_horizontal|bottom" android:layout_alignParentBottom="true" android:text="底部" android:textColor="#ff0000"/> </RelativeLayout> <RelativeLayout android:id="@+id/rl_top" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/keyboard_status" android:text="@string/hello_world" android:layout_alignParentTop="true" android:layout_width="match_parent" android:gravity="center" android:textSize="30sp" android:layout_height="100dp" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#660000ff" android:gravity="center_vertical" android:orientation="horizontal"> <TextView android:id="@+id/button" android:text="點我點我" android:gravity="center" android:layout_alignParentTop="true" android:layout_width="wrap_content" android:layout_height="40dp" /> <EditText android:id="@+id/text_field" android:layout_alignParentBottom="true" android:layout_width="match_parent" android:layout_height="40dp" /> </LinearLayout> <TextView android:gravity="center" android:background="#6600ff00" android:layout_width="match_parent" android:layout_height="60dp" /> </LinearLayout> </RelativeLayout> </RelativeLayout>
四、MainActivity代碼佈局
public class MainActivity extends AppCompatActivity { TextView mKeyboardStatus; EditText mTextField; TextView button; RelativeLayout rlBottom; RelativeLayout rlTop; int mKh; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mKeyboardStatus = (TextView) findViewById(R.id.keyboard_status); mTextField = (EditText) findViewById(R.id.text_field); button = (TextView) findViewById(R.id.button); rlTop = (RelativeLayout) findViewById(R.id.rl_top); rlBottom = (RelativeLayout) findViewById(R.id.rl_bottom); KeyboardVisibilityEvent.setEventListener(this, false, new KeyboardVisibilityEventListener() { @Override public void onVisibilityChanged(boolean isOpen, int kh) { updateKeyboardStatusText(isOpen); Log.i("aaaaaaaaaaaaab", "isOpen: " + isOpen + " kh: " + kh); if(isOpen) { RelativeLayout.LayoutParams p = (RelativeLayout.LayoutParams) rlTop.getLayoutParams(); p.height = rlBottom.getHeight() - kh; rlTop.setLayoutParams(p); if(kh > KeyboardVisibilityEvent.getVisibleThreshold(MainActivity.this)) { mKh = kh; } } else { RelativeLayout.LayoutParams p = (RelativeLayout.LayoutParams) rlTop.getLayoutParams(); p.height = rlBottom.getHeight(); rlTop.setLayoutParams(p); } } }); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { RelativeLayout.LayoutParams p = (RelativeLayout.LayoutParams) rlTop.getLayoutParams(); p.height = rlBottom.getHeight() - (mKh > 200 ? mKh : 600); rlTop.setLayoutParams(p); UIUtil.showKeyboard(MainActivity.this, mTextField); } }); updateKeyboardStatusText(KeyboardVisibilityEvent.isKeyboardVisible(this)); } private void updateKeyboardStatusText(boolean isOpen) { mKeyboardStatus.setText(String.format("keyboard is %s", (isOpen ? "visible" : "hidden"))); } }
五、若是有可滾動view的話,DecorView會resize,全部要監聽DecorView變化。this
final ViewGroup activityRoot = ((ViewGroup) findViewById(android.R.id.content)); activityRoot.getViewTreeObserver().addOnGlobalLayoutListener( new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { Log.i("aaaaaaaaaaaaab", "activityRoot: " + activityRoot.getHeight() + "-" + mDecorViewHeight); if(activityRoot.getHeight() < mDecorViewHeight) { Log.i("aaaaaaaaaaaaab", "set activityRoot: "); ViewGroup.LayoutParams p = (ViewGroup.LayoutParams) activityRoot.getLayoutParams(); p.height = mDecorViewHeight; activityRoot.setLayoutParams(p); } } });