"Push up" 显示软输入时的列表视图而不是栏
"Push up" a listview but not the bar when soft input is shown
我在 View Pager 的页面中有这样的布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black">
<LinearLayout
android:id="@+id/bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:layout_alignParentTop="true"
android:orientation="horizontal"
android:gravity="center"
android:background="@drawable/background_gray">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:paddingTop="15dp"
android:paddingBottom="15dp"
android:paddingLeft="3dp" />
</LinearLayout>
<RelativeLayout
android:id="@+id/container_chat_box"
android:background="@drawable/conversation_background_gray"
android:layout_alignParentBottom="true"
android:layout_marginBottom="50dp">
<EditText
android:id="@+id/chat_box"
style="@style/ConversationChatBox" />
</RelativeLayout>
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/bar"
android:background="@android:color/white"
android:stackFromBottom="true"
android:transcriptMode="normal"
android:layout_above="@id/chat_box"
android:paddingBottom="15dp"
android:clipToPadding="false"
android:divider="@null"
android:dividerHeight="0dp"
android:listSelector="@android:color/transparent" />
</RelativeLayout>
这是一个想法:
----------
[ bar ]
[list view]
[list view]
[list view]
[list view]
[edit text]
当我点击编辑文本时,我希望栏保持原样(在屏幕顶部),但列表视图被推上去,所以它看起来像:
------------
[ bar ]
[list view]
[list view]
[edit text]
[keyboard ]
我得到的结果(条被推高并消失):
------------
[list view]
[list view]
[list view]
[edit text]
[keyboard ]
我的 AndroidManifest 上有这个:
android:windowSoftInputMode="adjustPan"
我尝试了不同的值组合来设置 android:windowSoftInputMode
,但我要么让键盘覆盖编辑文本,要么将整个屏幕向上推。
有没有办法在向上推列表视图时将栏保持在原位?提前谢谢你。
我能够解决这个问题,尽管到目前为止只在几部手机上进行了测试。
这就是解决方案:
1) 将软输入模式更改为android:windowSoftInputMode="adjustResize"并在布局根视图中添加android:fitsSystemWindows="true"。
2) 创建了一个扩展 RelativeLayout(代码如下)的 CustomInsetsLayout class,因此我可以控制屏幕调整大小时布局发生的情况。
3) 此时我在布局底部有一个不需要的黑条。该栏是本应隐藏在导航栏下方的边距底部,但负责该栏的 FULLSCREEN 标志不适用于 adjustResize。因此,我必须向 CustomInsetsLayout 添加代码,以在屏幕调整大小时从根视图中删除底部边距。
这就是 CustomInsetsLayout class 的样子(class 描述中的参考和注释):
package com.playchat.ui.full;
import android.content.Context;
import android.graphics.Rect;
import android.os.Build;
import android.util.AttributeSet;
import android.view.WindowInsets;
import android.widget.RelativeLayout;
/**
*
*
* @author Kevin
* Date Created: 3/7/14
*
* https://code.google.com/p/android/issues/detail?id=63777
*
* When using a translucent status bar on API 19+, the window will not
* resize to make room for input methods (i.e.
* {@link android.view.WindowManager.LayoutParams#SOFT_INPUT_ADJUST_RESIZE} and
* {@link android.view.WindowManager.LayoutParams#SOFT_INPUT_ADJUST_PAN} are
* ignored).
*
* To work around this; override {@link #fitSystemWindows(android.graphics.Rect)},
* capture and override the system insets, and then call through to FrameLayout's
* implementation.
*
* For reasons yet unknown, modifying the bottom inset causes this workaround to
* fail. Modifying the top, left, and right insets works as expected.
*/
public class CustomInsetsLayout extends RelativeLayout {
private int[] mInsets = new int[4];
public CustomInsetsLayout(Context context) {
super(context);
}
public CustomInsetsLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomInsetsLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public final int[] getInsets() {
return mInsets;
}
@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.
// TODO: Figure out why.
mInsets[0] = insets.left;
mInsets[1] = insets.top;
mInsets[2] = insets.right;
insets.left = 0;
insets.top = 0;
insets.right = 0;
if (insets.bottom > 0) {
// Remove bottom margin from the root view
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) getLayoutParams();
params.bottomMargin = 0;
setLayoutParams(params);
}
}
return super.fitSystemWindows(insets);
}
@Override
public final WindowInsets onApplyWindowInsets(WindowInsets insets) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
if (insets.getSystemWindowInsetBottom() > 0) {
// Remove bottom margin from the root view
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) getLayoutParams();
params.bottomMargin = 0;
setLayoutParams(params);
}
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;
}
}
}
我在 View Pager 的页面中有这样的布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black">
<LinearLayout
android:id="@+id/bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:layout_alignParentTop="true"
android:orientation="horizontal"
android:gravity="center"
android:background="@drawable/background_gray">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:paddingTop="15dp"
android:paddingBottom="15dp"
android:paddingLeft="3dp" />
</LinearLayout>
<RelativeLayout
android:id="@+id/container_chat_box"
android:background="@drawable/conversation_background_gray"
android:layout_alignParentBottom="true"
android:layout_marginBottom="50dp">
<EditText
android:id="@+id/chat_box"
style="@style/ConversationChatBox" />
</RelativeLayout>
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/bar"
android:background="@android:color/white"
android:stackFromBottom="true"
android:transcriptMode="normal"
android:layout_above="@id/chat_box"
android:paddingBottom="15dp"
android:clipToPadding="false"
android:divider="@null"
android:dividerHeight="0dp"
android:listSelector="@android:color/transparent" />
</RelativeLayout>
这是一个想法:
----------
[ bar ]
[list view]
[list view]
[list view]
[list view]
[edit text]
当我点击编辑文本时,我希望栏保持原样(在屏幕顶部),但列表视图被推上去,所以它看起来像:
------------
[ bar ]
[list view]
[list view]
[edit text]
[keyboard ]
我得到的结果(条被推高并消失):
------------
[list view]
[list view]
[list view]
[edit text]
[keyboard ]
我的 AndroidManifest 上有这个:
android:windowSoftInputMode="adjustPan"
我尝试了不同的值组合来设置 android:windowSoftInputMode
,但我要么让键盘覆盖编辑文本,要么将整个屏幕向上推。
有没有办法在向上推列表视图时将栏保持在原位?提前谢谢你。
我能够解决这个问题,尽管到目前为止只在几部手机上进行了测试。
这就是解决方案:
1) 将软输入模式更改为android:windowSoftInputMode="adjustResize"并在布局根视图中添加android:fitsSystemWindows="true"。
2) 创建了一个扩展 RelativeLayout(代码如下)的 CustomInsetsLayout class,因此我可以控制屏幕调整大小时布局发生的情况。
3) 此时我在布局底部有一个不需要的黑条。该栏是本应隐藏在导航栏下方的边距底部,但负责该栏的 FULLSCREEN 标志不适用于 adjustResize。因此,我必须向 CustomInsetsLayout 添加代码,以在屏幕调整大小时从根视图中删除底部边距。
这就是 CustomInsetsLayout class 的样子(class 描述中的参考和注释):
package com.playchat.ui.full;
import android.content.Context;
import android.graphics.Rect;
import android.os.Build;
import android.util.AttributeSet;
import android.view.WindowInsets;
import android.widget.RelativeLayout;
/**
*
*
* @author Kevin
* Date Created: 3/7/14
*
* https://code.google.com/p/android/issues/detail?id=63777
*
* When using a translucent status bar on API 19+, the window will not
* resize to make room for input methods (i.e.
* {@link android.view.WindowManager.LayoutParams#SOFT_INPUT_ADJUST_RESIZE} and
* {@link android.view.WindowManager.LayoutParams#SOFT_INPUT_ADJUST_PAN} are
* ignored).
*
* To work around this; override {@link #fitSystemWindows(android.graphics.Rect)},
* capture and override the system insets, and then call through to FrameLayout's
* implementation.
*
* For reasons yet unknown, modifying the bottom inset causes this workaround to
* fail. Modifying the top, left, and right insets works as expected.
*/
public class CustomInsetsLayout extends RelativeLayout {
private int[] mInsets = new int[4];
public CustomInsetsLayout(Context context) {
super(context);
}
public CustomInsetsLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomInsetsLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public final int[] getInsets() {
return mInsets;
}
@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.
// TODO: Figure out why.
mInsets[0] = insets.left;
mInsets[1] = insets.top;
mInsets[2] = insets.right;
insets.left = 0;
insets.top = 0;
insets.right = 0;
if (insets.bottom > 0) {
// Remove bottom margin from the root view
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) getLayoutParams();
params.bottomMargin = 0;
setLayoutParams(params);
}
}
return super.fitSystemWindows(insets);
}
@Override
public final WindowInsets onApplyWindowInsets(WindowInsets insets) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
if (insets.getSystemWindowInsetBottom() > 0) {
// Remove bottom margin from the root view
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) getLayoutParams();
params.bottomMargin = 0;
setLayoutParams(params);
}
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;
}
}
}