我可以同时拥有 "adjustResize" 软键盘行为和状态栏后面的工具栏吗?
Can I have "adjustResize" soft keyboard behavior and a toolbar behind the status bar at the same time?
在我的 Android 应用程序中,使用软键盘的 adjustResize
行为对我来说至关重要。因此用户可以向下滚动到其他 UI 元素,例如 "continue" 按钮。
我注意到 adjustResize
仅当我在布局根元素中同时具有 Manifest 设置和 android:fitsSystemWindows="true"
时才有效。 (如有错误请指正!)
但是 android:fitsSystemWindows="true"
工具栏不再位于状态栏后面。这很有道理,但不是我想要的。
当工具栏位于其后面时,状态栏具有与我的工具栏颜色匹配的深色阴影。 android:fitsSystemWindows="true"
我拥有的是一个无色状态栏和一个比我想要的低 24dp 的工具栏。
为了 adjustResize
键盘行为,我将放弃匹配的彩色状态栏。但我的问题是,是否可以同时拥有两者? 我敢梦想既美丽又无障碍吗?
更有经验的人知道设置的神奇组合吗?
或者,作为变通方法,一种显式为状态栏着色的方法?
仅供参考:
这些是具有 RelativeLayout 根元素的 Activity,其中一些有 ListView
和 EditText
。
工具栏是 android.support.v7.widget.Toolbar
可能相关的样式项目:
<style name="AppBaseTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="android:windowContentOverlay">@null</item>
PS - 我已经阅读了数十个关于软键盘行为的类似问题,但无法找到任何有助于解决工具栏意外影响的问题。反之亦然,很多关于 toolbar/statusbar 行为的风格问题,但似乎没有什么相关的。尽管如此,如果我遗漏了什么,抱歉!
非常感谢!
编辑
我一直在尝试删除 android:fitsSystemWindows="true"
并添加更多 ScrollView 或尝试将所有内容放入同一个 ScrollView。这没有任何作用。
如果我删除 android:fitsSystemWindows="true"
,那么 UI 的底部是 "glued" 到屏幕的底部——它不会 "resize" 粘附到软键盘的顶部,就像我希望它与清单中设置的 adjustResize
一样。
在根视图中设置 android:fitsSystemWindows="true"
使 UI 像我期望的那样调整大小——但它也使工具栏不再绘制在状态栏后面。
所以我仍然是我开始的地方:(
添加布局 XML 代码示例:
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- CoordinatorLayout because this view uses SnackBars -->
<!-- Relative Layout to lock "continue" button bar to bottom -->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Main content, that scrolls with or without keyboard -->
<!-- Correctly sits behind transparent Status Bar -->
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/footer_persistent_height">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- ACTUAL VIEWS DELETED FOR BREVITY / CLARITY -->
</RelativeLayout>
</android.support.v4.widget.NestedScrollView>
<!-- Bottom nav bar -->
<!-- Correctly sits at bottom of UI when keyboard is not visible -->
<!-- PROBLEM: Not accessible when soft keyboard is visible -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
style="?android:attr/buttonBarStyle">
<Button
android:id="@+id/skip_button"
android:theme="@style/ButtonContinueGrey"
android:onClick="skipClickHandler"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight=".5"
style="?android:attr/buttonBarButtonStyle"/>
<Button
android:id="@+id/button_progress"
android:theme="@style/ButtonContinueColored"
android:onClick="continueClickHandler"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight=".5"
style="?android:attr/buttonBarButtonStyle"/>
</LinearLayout>
</RelativeLayout>
</android.support.design.widget.CoordinatorLayout>
我没有正确回答你的问题,但据我所知可以解决问题-
对于填充问题尝试添加
android:fitsSystemWindows="true"
android:clipToPadding=”false”
并为透明状态栏添加
<item name="android:statusBarColor">@android:color/transparent</item>
到您的 AppTheme。
希望对大家有帮助,请上传问题截图,查看详细问题
尝试将布局保持在滚动视图中并删除 android:fitsSystemWindows="true" 并仅使用调整大小
我已经解决了你的问题,并在我这边进行了测试。请将您的相对布局更改为 framelayout,如下所示:
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- CoordinatorLayout because this view uses SnackBars -->
<!-- Relative Layout to lock "continue" button bar to bottom -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<!-- Main content, that scrolls with or without keyboard -->
<!-- Correctly sits behind transparent Status Bar -->
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="24dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- ACTUAL VIEWS DELETED FOR BREVITY / CLARITY -->
</RelativeLayout>
</android.support.v4.widget.NestedScrollView>
<!-- Bottom nav bar -->
<!-- Correctly sits at bottom of UI when keyboard is not visible -->
<!-- PROBLEM: Not accessible when soft keyboard is visible -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
style="?android:attr/buttonBarStyle"
android:layout_gravity="bottom">
<Button
android:id="@+id/skip_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight=".5"
style="?android:attr/buttonBarButtonStyle"/>
<Button
android:id="@+id/button_progress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight=".5"
style="?android:attr/buttonBarButtonStyle"/>
</LinearLayout>
</FrameLayout>
</android.support.design.widget.CoordinatorLayout>
(回答我自己的问题)
这似乎是 android 中的错误:
https://code.google.com/p/android/issues/detail?id=63777
关于上述错误报告的帖子 link 以及一些建议的解决方法,例如创建自定义布局 class 或自定义软键盘。
我觉得我已经在这上面浪费了足够多的时间。所以我的解决方案是手动为状态栏着色。
解决方案:
在布局的根视图中或在 style.xml 中全局设置 android:fitsSystemWindows="true"
。这(与清单中的 adjustResize 一起)使 UI 缩小到软键盘上方,因此没有 UI 被阻止——最重要的是。
给状态栏上色。这只有在 Lollypop 和更新版本中才有可能。反正跟透明的StatusBar是一样的
private void updateStatusBarColor(){
// Check Version
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// OPTIONAL: Calculate a darker version of the toolbar color
int color = calculateDarkerColor(toolBarColor);
// Get the statusBar
Window window = getWindow();
// You can't color a transparent statusbar
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
// Set the color
window.setStatusBarColor(color);
}
}
// Calculate a darker version of a given color
// Note I do this because the color always changes, if it's always the same I would save the darker version as a Resource in colors.xml
private int calculateDarkerColor(int color){
float[] hsv = new float[3];
Color.colorToHSV(color, hsv);
hsv[2] *= 0.8f; // smaller = darker
return Color.HSVToColor(hsv);
}
我找到了一个似乎适用于 OS 的解决方案。首先将 fitSystemWindows = true
设置为您想要对 window 做出反应的视图,然后告诉它忽略顶部填充:
ViewCompat.setOnApplyWindowInsetsListener(yourView, (view, insets) ->
ViewCompat.onApplyWindowInsets(yourView,
insets.replaceSystemWindowInsets(insets.getSystemWindowInsetLeft(), 0,
insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom()))
);
在此处阅读更多内容:https://medium.com/google-developers/why-would-i-want-to-fitssystemwindows-4e26d9ce1eec
它对我有用。
在 manifest.xml 中,将其放入 <activity>
标签中。
android:windowSoftInputMode="adjustResize"
在您布局的父标签中,放置此内容。
android:fitsSystemWindows="true"
android:clipToPadding="false"
在styles.xml里放这个。
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
我已经用 minSdkVersion 16 和 targetSdkVersion 26 做到了
我认为当 android:fitsSystemWindows="false" 时,您可以尝试使用 "adjustPan" 而不是 "adjustResize"。它对我有用。
为了同时拥有透明状态栏和有效的 adjustResize 键盘行为,以下是对我有用的方法。
首先,我建议您观看 Chris Banes 的这个 27 分钟的 droidcon 演讲,它可以启发:https://www.youtube.com/watch?v=_mGDMVRO3iE
在布局中将 fitsSystemWindows 添加到正确的层级,以便背景图像在状态栏下方展开。现在 fitsSystemWindows 将修复与 adjustResize 相关的键盘布局行为。
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<!-- EditText etc here -->
在Activity中:
makeStatusBarTransparent(this);
setContentView(R.layout.activity_login);
扩展方法:
fun Activity.makeStatusBarTransparent() {
window.apply {
clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
decorView.systemUiVisibility += View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
// or:
// decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
statusBarColor = Color.TRANSPARENT
}
}
在清单的 activity 标签中:
android:windowSoftInputMode="adjustResize|stateHidden"
我决定做“.systemUiVisibility += ...”,这样我就可以通过 xml 在主题上设置 windowLightStatusBar 之类的东西(我以不同的方式覆盖它)。但是你可以直接指定LIGHT_STATUS_BAR标志(也可以不指定,取决于你的背景)。
请记住,fitsSystemWindows 会覆盖填充,因此如果您使用填充,则需要使用其他布局。
在我的 Android 应用程序中,使用软键盘的 adjustResize
行为对我来说至关重要。因此用户可以向下滚动到其他 UI 元素,例如 "continue" 按钮。
我注意到 adjustResize
仅当我在布局根元素中同时具有 Manifest 设置和 android:fitsSystemWindows="true"
时才有效。 (如有错误请指正!)
但是 android:fitsSystemWindows="true"
工具栏不再位于状态栏后面。这很有道理,但不是我想要的。
当工具栏位于其后面时,状态栏具有与我的工具栏颜色匹配的深色阴影。 android:fitsSystemWindows="true"
我拥有的是一个无色状态栏和一个比我想要的低 24dp 的工具栏。
为了 adjustResize
键盘行为,我将放弃匹配的彩色状态栏。但我的问题是,是否可以同时拥有两者? 我敢梦想既美丽又无障碍吗?
更有经验的人知道设置的神奇组合吗? 或者,作为变通方法,一种显式为状态栏着色的方法?
仅供参考:
这些是具有 RelativeLayout 根元素的 Activity,其中一些有 ListView
和 EditText
。
工具栏是 android.support.v7.widget.Toolbar
可能相关的样式项目:
<style name="AppBaseTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="android:windowContentOverlay">@null</item>
PS - 我已经阅读了数十个关于软键盘行为的类似问题,但无法找到任何有助于解决工具栏意外影响的问题。反之亦然,很多关于 toolbar/statusbar 行为的风格问题,但似乎没有什么相关的。尽管如此,如果我遗漏了什么,抱歉!
非常感谢!
编辑
我一直在尝试删除 android:fitsSystemWindows="true"
并添加更多 ScrollView 或尝试将所有内容放入同一个 ScrollView。这没有任何作用。
如果我删除 android:fitsSystemWindows="true"
,那么 UI 的底部是 "glued" 到屏幕的底部——它不会 "resize" 粘附到软键盘的顶部,就像我希望它与清单中设置的 adjustResize
一样。
在根视图中设置 android:fitsSystemWindows="true"
使 UI 像我期望的那样调整大小——但它也使工具栏不再绘制在状态栏后面。
所以我仍然是我开始的地方:(
添加布局 XML 代码示例:
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- CoordinatorLayout because this view uses SnackBars -->
<!-- Relative Layout to lock "continue" button bar to bottom -->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Main content, that scrolls with or without keyboard -->
<!-- Correctly sits behind transparent Status Bar -->
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/footer_persistent_height">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- ACTUAL VIEWS DELETED FOR BREVITY / CLARITY -->
</RelativeLayout>
</android.support.v4.widget.NestedScrollView>
<!-- Bottom nav bar -->
<!-- Correctly sits at bottom of UI when keyboard is not visible -->
<!-- PROBLEM: Not accessible when soft keyboard is visible -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
style="?android:attr/buttonBarStyle">
<Button
android:id="@+id/skip_button"
android:theme="@style/ButtonContinueGrey"
android:onClick="skipClickHandler"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight=".5"
style="?android:attr/buttonBarButtonStyle"/>
<Button
android:id="@+id/button_progress"
android:theme="@style/ButtonContinueColored"
android:onClick="continueClickHandler"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight=".5"
style="?android:attr/buttonBarButtonStyle"/>
</LinearLayout>
</RelativeLayout>
</android.support.design.widget.CoordinatorLayout>
我没有正确回答你的问题,但据我所知可以解决问题-
对于填充问题尝试添加
android:fitsSystemWindows="true"
android:clipToPadding=”false”
并为透明状态栏添加
<item name="android:statusBarColor">@android:color/transparent</item>
到您的 AppTheme。 希望对大家有帮助,请上传问题截图,查看详细问题
尝试将布局保持在滚动视图中并删除 android:fitsSystemWindows="true" 并仅使用调整大小
我已经解决了你的问题,并在我这边进行了测试。请将您的相对布局更改为 framelayout,如下所示:
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- CoordinatorLayout because this view uses SnackBars -->
<!-- Relative Layout to lock "continue" button bar to bottom -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<!-- Main content, that scrolls with or without keyboard -->
<!-- Correctly sits behind transparent Status Bar -->
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="24dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- ACTUAL VIEWS DELETED FOR BREVITY / CLARITY -->
</RelativeLayout>
</android.support.v4.widget.NestedScrollView>
<!-- Bottom nav bar -->
<!-- Correctly sits at bottom of UI when keyboard is not visible -->
<!-- PROBLEM: Not accessible when soft keyboard is visible -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
style="?android:attr/buttonBarStyle"
android:layout_gravity="bottom">
<Button
android:id="@+id/skip_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight=".5"
style="?android:attr/buttonBarButtonStyle"/>
<Button
android:id="@+id/button_progress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight=".5"
style="?android:attr/buttonBarButtonStyle"/>
</LinearLayout>
</FrameLayout>
</android.support.design.widget.CoordinatorLayout>
(回答我自己的问题)
这似乎是 android 中的错误: https://code.google.com/p/android/issues/detail?id=63777
关于上述错误报告的帖子 link 以及一些建议的解决方法,例如创建自定义布局 class 或自定义软键盘。
我觉得我已经在这上面浪费了足够多的时间。所以我的解决方案是手动为状态栏着色。
解决方案:
在布局的根视图中或在 style.xml 中全局设置
android:fitsSystemWindows="true"
。这(与清单中的 adjustResize 一起)使 UI 缩小到软键盘上方,因此没有 UI 被阻止——最重要的是。给状态栏上色。这只有在 Lollypop 和更新版本中才有可能。反正跟透明的StatusBar是一样的
private void updateStatusBarColor(){ // Check Version if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { // OPTIONAL: Calculate a darker version of the toolbar color int color = calculateDarkerColor(toolBarColor); // Get the statusBar Window window = getWindow(); // You can't color a transparent statusbar window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); // Set the color window.setStatusBarColor(color); } } // Calculate a darker version of a given color // Note I do this because the color always changes, if it's always the same I would save the darker version as a Resource in colors.xml private int calculateDarkerColor(int color){ float[] hsv = new float[3]; Color.colorToHSV(color, hsv); hsv[2] *= 0.8f; // smaller = darker return Color.HSVToColor(hsv); }
我找到了一个似乎适用于 OS 的解决方案。首先将 fitSystemWindows = true
设置为您想要对 window 做出反应的视图,然后告诉它忽略顶部填充:
ViewCompat.setOnApplyWindowInsetsListener(yourView, (view, insets) ->
ViewCompat.onApplyWindowInsets(yourView,
insets.replaceSystemWindowInsets(insets.getSystemWindowInsetLeft(), 0,
insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom()))
);
在此处阅读更多内容:https://medium.com/google-developers/why-would-i-want-to-fitssystemwindows-4e26d9ce1eec
它对我有用。
在 manifest.xml 中,将其放入 <activity>
标签中。
android:windowSoftInputMode="adjustResize"
在您布局的父标签中,放置此内容。
android:fitsSystemWindows="true"
android:clipToPadding="false"
在styles.xml里放这个。
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
我已经用 minSdkVersion 16 和 targetSdkVersion 26 做到了
我认为当 android:fitsSystemWindows="false" 时,您可以尝试使用 "adjustPan" 而不是 "adjustResize"。它对我有用。
为了同时拥有透明状态栏和有效的 adjustResize 键盘行为,以下是对我有用的方法。
首先,我建议您观看 Chris Banes 的这个 27 分钟的 droidcon 演讲,它可以启发:https://www.youtube.com/watch?v=_mGDMVRO3iE
在布局中将 fitsSystemWindows 添加到正确的层级,以便背景图像在状态栏下方展开。现在 fitsSystemWindows 将修复与 adjustResize 相关的键盘布局行为。
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<!-- EditText etc here -->
在Activity中:
makeStatusBarTransparent(this);
setContentView(R.layout.activity_login);
扩展方法:
fun Activity.makeStatusBarTransparent() {
window.apply {
clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
decorView.systemUiVisibility += View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
// or:
// decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
statusBarColor = Color.TRANSPARENT
}
}
在清单的 activity 标签中:
android:windowSoftInputMode="adjustResize|stateHidden"
我决定做“.systemUiVisibility += ...”,这样我就可以通过 xml 在主题上设置 windowLightStatusBar 之类的东西(我以不同的方式覆盖它)。但是你可以直接指定LIGHT_STATUS_BAR标志(也可以不指定,取决于你的背景)。
请记住,fitsSystemWindows 会覆盖填充,因此如果您使用填充,则需要使用其他布局。