實例分析下windowSoftInputMode 里面adjustPan和adjustResize的作用,以及在沉浸式樣式下的解決方案
windowSoftInputMode
頁面布局
在沒有設(shè)置scrollview的布局下
"adjustResize"
該 Activity主窗口總是被調(diào)整屏幕的大小以便留出軟鍵盤的空間憎蛤。
adjustResize 界面布局不會動疾牲,鍵盤會擋住輸入框
"adjustPan"
該 Activity主窗口并不調(diào)整屏幕的大小以便留出軟鍵盤的空間园爷。相反吨枉,當(dāng)前窗口的內(nèi)容將自動移動以便當(dāng)前焦點從不被鍵盤覆蓋和用戶能總是看到輸入內(nèi)容的部分。這個通常是不期望比調(diào)整大小怕敬,因為用戶可能關(guān)閉軟鍵盤以便獲得與被覆蓋內(nèi)容的交互操作咖为。
adjustPan輸入框獲得焦點的時候會被鍵盤上移秕狰,不遮擋
在設(shè)置scrollview的布局下
adjustPan 鍵盤不會遮擋輸入框,在原來布局不超過一屏的情況下不能滑動躁染,超過之后只能滑動少許鸣哀,這個原因有待分析。
adjustResize可以通過滑動scrollview布局移出輸入框
總結(jié):
adjustPan類似于鍵盤底部增加一塊鍵盤布局
adjustResize類似于鍵盤覆蓋在界面上面
使用沉浸式樣式時
adjustPan 界面上移軟鍵盤不遮擋輸入框吞彤,但是上面的布局會遮擋狀態(tài)欄
663178288014871941.jpg
adjustResize鍵盤會遮擋輸入框我衬,且不管是否用scrollview布局都不能滑動
解決方案有兩種
第一種是谷歌提的AndroidBug5497Workaround,適配小米,華為,三星時需要修改代碼饰恕,原本的方法在這些手機上會出現(xiàn)高度計算不準(zhǔn)確的情況挠羔,修改后代碼如下
public class AndroidBug5497Workaround {
public static void assistActivity(Activity activity) {
new AndroidBug5497Workaround(activity);
}
private View mChildOfContent;
private int usableHeightPrevious;
private FrameLayout.LayoutParams frameLayoutParams;
private int contentHeight;
private boolean isfirst = true;
private Activity activity;
private int statusBarHeight;
private AndroidBug5497Workaround(Activity activity) {
//獲取狀態(tài)欄的高度
int resourceId = activity.getResources().getIdentifier("status_bar_height", "dimen", "android");
statusBarHeight = activity.getResources().getDimensionPixelSize(resourceId);
this.activity = activity;
FrameLayout content = (FrameLayout)activity.findViewById(android.R.id.content);
mChildOfContent = content.getChildAt(0);
//界面出現(xiàn)變動都會調(diào)用這個監(jiān)聽事件
mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
public void onGlobalLayout() {
if (isfirst) {
contentHeight = mChildOfContent.getHeight();//兼容華為等機型
isfirst = false;
}
possiblyResizeChildOfContent();
}
});
frameLayoutParams = (FrameLayout.LayoutParams)
mChildOfContent.getLayoutParams();
}
//重新調(diào)整跟布局的高度
private void possiblyResizeChildOfContent() {
int usableHeightNow = computeUsableHeight();
//當(dāng)前可見高度和上一次可見高度不一致 布局變動
if (usableHeightNow != usableHeightPrevious) {
//int usableHeightSansKeyboard2 = mChildOfContent.getHeight();//兼容華為等機型
int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();
int heightDifference = usableHeightSansKeyboard - usableHeightNow;
if (heightDifference > (usableHeightSansKeyboard / 4)) {
// keyboard probably just became visible
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
//frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
frameLayoutParams.height = usableHeightSansKeyboard - heightDifference + statusBarHeight;
} else {
frameLayoutParams.height = usableHeightSansKeyboard -heightDifference;
}
} else {
frameLayoutParams.height = contentHeight;
}
mChildOfContent.requestLayout();
usableHeightPrevious = usableHeightNow;
}
}
/** * 計算mChildOfContent可見高度 ** @return */
private int computeUsableHeight() {
Rect r = new Rect();
mChildOfContent.getWindowVisibleDisplayFrame(r);
return (r.bottom - r.top);
}
}
第二種 解決方案 自定義LinearLayout,relativityLayout
ResizeRelativityLayout
public class ResizeLinearLayout extends LinearLayout {
private int[] mInsets = new int[4];
public ResizeLinearLayout(Context context) {
super(context);
}
public ResizeLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ResizeLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ResizeLinearLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
protected final boolean fitSystemWindows(Rect insets) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// Intentionally do not modify the bottom inset. For some reason,
// if the bottom inset is modified, window resizing stops working.
mInsets[0] = insets.left;
mInsets[1] = insets.top;
mInsets[2] = insets.right;
insets.left = 0;
insets.top = 0;
insets.right = 0;
}
return super.fitSystemWindows(insets);
}
@Override
public final WindowInsets onApplyWindowInsets(WindowInsets insets) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
mInsets[0] = insets.getSystemWindowInsetLeft();
mInsets[1] = insets.getSystemWindowInsetTop();
mInsets[2] = insets.getSystemWindowInsetRight();
return super.onApplyWindowInsets(insets.replaceSystemWindowInsets(0, 0, 0,
insets.getSystemWindowInsetBottom()));
} else {
return insets;
}
}
}
ResizeLinearLayout
public class ResizeLinearLayout extends LinearLayout {
private int[] mInsets = new int[4];
public ResizeLinearLayout(Context context) {
super(context);
}
public ResizeLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ResizeLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ResizeLinearLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
protected final boolean fitSystemWindows(Rect insets) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// Intentionally do not modify the bottom inset. For some reason,
// if the bottom inset is modified, window resizing stops working.
mInsets[0] = insets.left;
mInsets[1] = insets.top;
mInsets[2] = insets.right;
insets.left = 0;
insets.top = 0;
insets.right = 0;
}
return super.fitSystemWindows(insets);
}
@Override
public final WindowInsets onApplyWindowInsets(WindowInsets insets) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
mInsets[0] = insets.getSystemWindowInsetLeft();
mInsets[1] = insets.getSystemWindowInsetTop();
mInsets[2] = insets.getSystemWindowInsetRight();
return super.onApplyWindowInsets(insets.replaceSystemWindowInsets(0, 0, 0,
insets.getSystemWindowInsetBottom()));
} else {
return insets;
}
}
}
使用方法:在設(shè)置了布局根部使用此控件并且加上android:fitsSystemWindows="true"