fab*_*bru 117 android resize statusbar window-soft-input-mode android-4.4-kitkat
我在新的Android KitKat(4.4)中使用半透明操作栏/导航栏时出现问题windowSoftInputMode="adjustResize".
Normaly将InputMode更改为adjustResize,应用程序应该在键盘显示时自行调整大小......但是在这里它不会!如果我删除透明效果的行,则调整大小正常.
因此,如果键盘可见,我的ListView就在它下面,我无法访问最后几个项目.(只能手动隐藏键盘)
AndroidManifest.xml中
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="XYZ"
android:versionCode="23"
android:versionName="0.1" >
<uses-sdk
android:minSdkVersion="9"
android:targetSdkVersion="19" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/Theme.XYZStyle" >
<activity
android:name="XYZ"
android:label="@string/app_name"
android:windowSoftInputMode="adjustResize" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Run Code Online (Sandbox Code Playgroud)
值-V19/styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Theme.XYZStyle" parent="@style/Theme.AppCompat.Light">
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
</style>
</resources>
Run Code Online (Sandbox Code Playgroud)
fragment.xml之
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="@+id/listView_contacts"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:divider="@null"
android:dividerHeight="0dp"
android:drawSelectorOnTop="true"
android:fastScrollAlwaysVisible="true"
android:fastScrollEnabled="true"
android:paddingBottom="@dimen/navigationbar__height" >
</ListView>
</RelativeLayout>
Run Code Online (Sandbox Code Playgroud)
有没有想法解决这个问题?
pab*_*sco 168
您缺少以下属性:
android:fitsSystemWindows="true"
Run Code Online (Sandbox Code Playgroud)
在片段 .xml布局的根目录RelativeLayout中.
更新:
去年Chris Bane发表了一篇有趣的演讲,详细解释了这是如何工作的:
https://www.youtube.com/watch?v=_mGDMVRO3iE
kco*_*ock 32
有一个相关的bug报告在这里.我找到了一种解决方法,从有限的测试来看,似乎没有任何影响.ViewGroup使用FrameLayout下面的逻辑添加根的自定义实现(我几乎总是使用,所以这是我测试过的).然后,使用此自定义布局代替根布局,并确保进行设置android:fitsSystemWindows="true".然后,您可以getInsets()在布局后随时调用(例如添加一个OnPreDrawListener)来调整布局的其余部分,以便根据需要考虑系统插入.
import android.content.Context;
import android.graphics.Rect;
import android.os.Build;
import android.util.AttributeSet;
import android.widget.FrameLayout;
import org.jetbrains.annotations.NotNull;
/**
* @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 final class CustomInsetsFrameLayout extends FrameLayout {
private int[] mInsets = new int[4];
public CustomInsetsFrameLayout(Context context) {
super(context);
}
public CustomInsetsFrameLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomInsetsFrameLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public final int[] getInsets() {
return mInsets;
}
@Override
protected final boolean fitSystemWindows(@NotNull 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;
}
return super.fitSystemWindows(insets);
}
}
Run Code Online (Sandbox Code Playgroud)
由于fitSystemWindows已弃用,请参阅以下答案以完成解决方法.
小智 26
@kcoppock的回答非常有用,但是在API级别20中不推荐使用fitSystemWindows
因此,自API 20(KITKAT_WATCH)以来,您应该覆盖onApplyWindowInsets
@Override
public final WindowInsets onApplyWindowInsets(WindowInsets insets) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
return super.onApplyWindowInsets(insets.replaceSystemWindowInsets(0, 0, 0,
insets.getSystemWindowInsetBottom()));
} else {
return insets;
}
}
Run Code Online (Sandbox Code Playgroud)
Her*_*man 11
这对我来说在片段中有半透明状态栏和adjustResize:
将自定义RelativeLayout设为@ Victor91和@kcoppock说.
使用CustomRelativeLayout作为片段的父布局.
用android声明主题:windowTranslucentStatus = true
必须使用android:windowSoftInputMode ="adjustResize"在Manifest中声明容器Activity并使用声明的主题
请在片段根布局上使用fitsSystemWindows!
public class CustomRelativeLayout extends RelativeLayout {
private int[] mInsets = new int[4];
public CustomRelativeLayout(Context context) {
super(context);
}
public CustomRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public CustomRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@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;
}
}
}
Run Code Online (Sandbox Code Playgroud)然后在xml中,
<com.blah.blah.CustomRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
</com.blah.blah.CustomRelativeLayout>
Run Code Online (Sandbox Code Playgroud)
如果要自定义插图,并且目标API级别> = 21,则可以完成此操作而不必创建自定义视图组。通过仅设置fitsSystemWindows填充,默认情况下会将填充应用于您的容器视图,这可能是您不希望的。
版本检查内置于此方法中,只有> = 21的设备才会在lambda中执行代码。Kotlin示例:
ViewCompat.setOnApplyWindowInsetsListener(container) { view, insets ->
insets.replaceSystemWindowInsets(0, 0, 0, insets.systemWindowInsetBottom).apply {
ViewCompat.onApplyWindowInsets(view, this)
}
}
Run Code Online (Sandbox Code Playgroud)
确保您的布局仍然设置该fitsSystemWindows标志,否则将不会调用窗口插入侦听器。
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
/>
Run Code Online (Sandbox Code Playgroud)
这些来源很有帮助:
https://medium.com/google-developers/why-would-i-want-to-fitssystemwindows-4e26d9ce1eec https://medium.com/@azizbekian/windowinsets-24e241d4afb9
小智 6
首先将其添加到根布局中。
android:fitsSystemWindows="true"
Run Code Online (Sandbox Code Playgroud)
当您使用此方法时,您有责任确保应用程序 UI 的关键部分(例如,地图应用程序中的内置控件)最终不会被系统栏覆盖。这可能会使您的应用程序无法使用。在大多数情况下,您可以通过将 android:fitsSystemWindows 属性添加到 XML 布局文件中并设置为 true 来处理此问题。这会调整父 ViewGroup 的填充,以为系统窗口留出空间。这对于大多数应用程序来说已经足够了。
但是,在某些情况下,您可能需要修改默认填充以获得应用程序所需的布局。要直接操纵内容相对于系统栏(占据称为窗口“内容插图”的空间)的布局方式,请重写 fitSystemWindows(Rect insets)。当窗口的内容插入发生更改时,视图层次结构将调用 fitSystemWindows() 方法,以允许窗口相应地调整其内容。通过重写此方法,您可以根据需要处理插图(以及应用程序的布局)。
https://developer.android.com/training/system-ui/status#behind
如果你想成为一名窗户装配大师,请观看来自android开发者的视频。 https://www.youtube.com/watch?v=_mGDMVRO3iE
我有同样的问题,我的活动有一个ScrollView作为根视图和半透明状态栏激活它没有正确调整大小键盘显示...并且因此屏幕没有滚动隐藏输入视图.
解决方案:将所有内容(布局和活动逻辑)移动到新的片段中.然后将Activity更改为仅包含此Fragment.现在一切都按预期工作!
这是活动的布局:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/contentView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true" />
Run Code Online (Sandbox Code Playgroud)
由和方法弃用引起的有用@Victor Rendina的答案的小更新。replaceSystemWindowInsetssystemWindowInsetBottom
先决条件:
implementation 'androidx.core:core-ktx:1.5.0-alpha02' 至少科特林扩展:
fun View?.fitSystemWindowsAndAdjustResize() = this?.let { view ->
ViewCompat.setOnApplyWindowInsetsListener(view) { v, insets ->
view.fitsSystemWindows = true
val bottom = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom
WindowInsetsCompat
.Builder()
.setInsets(
WindowInsetsCompat.Type.systemBars(),
Insets.of(0, 0, 0, bottom)
)
.build()
.apply {
ViewCompat.onApplyWindowInsets(v, this)
}
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
rootView.fitSystemWindowsAndAdjustResize()
Run Code Online (Sandbox Code Playgroud)
哪里rootView是布局的根视图:)
注: 如果扩展不为你的根视图的工作(我有当遇到了这个ConstraintLayout作为rootView一个包住整个布局)FrameLayout,以便FrameLayout成为新的根视图。
| 归档时间: |
|
| 查看次数: |
78032 次 |
| 最近记录: |