【问题标题】:Can I have "adjustResize" soft keyboard behavior and a toolbar behind the status bar at the same time?我可以同时拥有“adjustResize”软键盘行为和状态栏后面的工具栏吗?
【发布时间】:2017-07-15 12:45:49
【问题描述】:

在我的 Android 应用程序中,对软键盘使用 adjustResize 行为至关重要。因此用户可以向下滚动到其他 UI 元素,例如“继续”按钮。

我注意到 adjustResize 仅在我在布局根元素中同时具有 Manifest 设置和 android:fitsSystemWindows="true" 时才有效。 (如有错误请指正!)

但使用android:fitsSystemWindows="true",工具栏不再位于状态栏后面。这很合理,但不是我想要的。

当工具栏位于其后面时,状态栏的颜色与我的工具栏颜色相匹配。我对android:fitsSystemWindows="true" 拥有的是一个无色状态栏和一个比我想要的低24dp 的工具栏。

为了adjustResize 键盘行为,我将放弃匹配颜色的状态栏。但我的问题是,有可能两者兼得吗? 我敢为美丽和无障碍而梦想吗?

有经验丰富的人知道设置的神奇组合吗? 或者,作为一种变通方法,一种为状态栏显式着色的方法?

仅供参考:

这些是带有RelativeLayout根元素的Activity,其中一些有ListViews和EditTexts。

工具栏是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 - 我已经阅读了几十个关于软键盘行为的类似问题,但找不到对工具栏的意外影响有帮助的任何内容。反之亦然,有很多关于工具栏/状态栏行为的样式问题,但似乎没有任何相关性。无论如何,如果我错过了什么,对不起!

非常感谢!

编辑

我一直在尝试删除 android:fitsSystemWindows="true" 并添加更多 ScrollView 或尝试将所有内容放入同一个 ScrollView。这没有任何作用。

如果我删除android:fitsSystemWindows="true",那么 UI 的底部会“粘”到屏幕底部——它不会像我期望的那样“调整大小”而是粘到软键盘的顶部在清单中设置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>

【问题讨论】:

  • 我无法正确理解您的问题。滚动当前视图时是否要隐藏工具栏?您使用 adjustResize 行为的目的是使您的“继续”按钮可访问,您是否尝试将 RealtiveLayout 嵌套在 NestedScrollView 中?您可以通过在主题中设置 ColorPrimaryDark 来控制状态栏颜色,如果您是 >= Lollipop
  • 尽量让你的布局保持在滚动视图中并移除 android:fitsSystemWindows="true" 并且只使用调整大小
  • fitsSystemWindow 只是在状态栏后面绘制您的视图。可能重复? stackoverflow.com/questions/37454733/…你能发布一个示例布局吗 - 有很多组合可能会导致问题。
  • @VarunJain 如果你能快速发表你的评论和回答,我会给你赏金! (不到一个小时就会过期)
  • 我也遇到了同样的问题,你有没有找到不涉及着色状态栏的解决方案(我试图在状态栏后面绘制的不是纯色)

标签: android android-layout keyboard android-softkeyboard android-styles


【解决方案1】:

我找到了一个似乎适用于操作系统的解决方案。首先将fitSystemWindows = true 设置为要对窗口做出反应的视图,然后告诉它忽略顶部填充:

  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

【讨论】:

  • 优秀的答案。
  • 我最初传递了这个答案,因为我还没准备好弄乱插图,但它实际上正是我所需要的。如果在将 fitSystemWindows 设置为 true 之后,Android Studio 的布局检查器在“mPadding”字段之一(与“mUserPadding”字段相反)中报告了一个无法解释的非零值,这可能是解决方案,就像我的情况一样。
【解决方案2】:

尝试将布局保持在滚动视图中并删除 android:fitsSystemWindows="true" 并仅使用调整大小

【讨论】:

  • 很高兴有人能够获得赏金 :) 在赏金到期之前,我没有时间完全尝试您的解决方案。您的简单解决方案确实以我想要的方式获得了 StatusBar,并且我可以滚动......但我只能滚动到 ScrollView 内的 UI 部分。故意在 ScrollView 之外的“继续”按钮无法通过可见的键盘访问。我在问题中添加了一个代码示例 - 请您看一下并告诉我您是否有任何想法?谢谢!
  • 我尝试将外部的RelativeLayout包装在另一个ScrollView中,但是Continue Button不再位于屏幕底部,而是位于内容的底部。
  • 哈哈...是的,感谢您的赏金,我刚刚在您的布局中稍作修改添加了一个答案,这将解决您的问题...如果您需要即时支持,请联系我以获取未来支持我的whatsapp号码:- +91-8585949830
  • 你能详细说明你的答案吗......adjustResize 似乎对我没有任何作用,除非我也使用“fitSystemWindows”。谢谢:)
  • @FRR 您能否在此处发布与解决方案相关的内容
【解决方案3】:

我认为您可以尝试在 android:fitsSystemWindows="false" 时使用“adjustPan”而不是“adjustResize”。它对我有用。

【讨论】:

    【解决方案4】:

    我没有正确回答您的问题,但据我所知,我可以解决问题-

    对于填充问题,请尝试添加

    android:fitsSystemWindows="true"
    android:clipToPadding=”false”
    

    并为透明状态栏添加

    <item name="android:statusBarColor">@android:color/transparent</item>
    

    到您的 AppTheme。 希望对您有所帮助,请上传您的问题截图以查看详细问题。

    【讨论】:

    • clipToPadding 解决了我的问题,即活动使用 fitSystemWindows="false" 和片段使用 fitSystemWindows="true"... 以及 windowSoftInputMode="adjustResize" 活动。在设置 clipTopPadding="false" 之前,我在工具栏下看到了不必要的填充,它剪切了片段内容。
    【解决方案5】:

    (回答我自己的问题)

    这似乎是 android 中的一个错误: https://code.google.com/p/android/issues/detail?id=63777

    上述错误报告中的帖子链接到一些建议的解决方法,例如创建自定义布局类或自定义软键盘。

    我觉得我已经浪费了足够多的时间了。所以我的解决方案是手动为状态栏着色。

    解决方案:

    1. 在布局的根视图中或在 style.xml 中全局设置 android:fitsSystemWindows="true"。这(连同清单中的 adjustResize)使 UI 缩小到软键盘上方,因此没有 UI 被阻塞——这是最重要的。

    2. 为状态栏着色。这仅在 Lollypop 和更新版本中才有可能。无论如何,它与透明的状态栏相同。

      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);
      }
      

    【讨论】:

    • 但是,这仅适用于状态栏为纯色的情况,而不是您希望在状态栏后面实际显示内容:(
    【解决方案6】:

    它对我有用。

    在 manifest.xml 中,将其放入 &lt;activity&gt; 标记中。

    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 完成了这项工作

    【讨论】:

      【解决方案7】:

      为了同时拥有透明的状态栏和工作的 adjustResize 键盘行为,这对我有用。

      首先,我建议你观看 Chris Banes 的 27 分钟 droidcon 演讲,它可以很有启发性:https://www.youtube.com/watch?v=_mGDMVRO3iE

      在布局中在正确的层级上添加 fitSystemWindows,以便背景图像在状态栏下方展开。现在 fitSystemWindows 将修复与 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 -->
      

      在活动中:

          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
      }
      }
      

      在清单的活动标签中:

      android:windowSoftInputMode="adjustResize|stateHidden"
      

      我决定做“.systemUiVisibility += ...”所以我可以通过xml在主题上设置一些东西,比如windowLightStatusBar(我用不同的风格覆盖它)。但是您可以直接指定 LIGHT_STATUS_BAR 标志(或不指定,取决于您的背景)。

      请记住,fitsSystemWindows 会覆盖填充,因此如果您使用填充,则需要使用其他布局。

      【讨论】:

        【解决方案8】:

        我已经解决了您的问题,并在我的最后进行了测试。请将您的相对布局更改为 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 为您提供了 (1) 在软键盘上方可见的底部按钮栏和 (2) 透明状态栏?
        • 但我在三星 edge s6 的棉花糖中进行了测试。使用上面的代码并在打开软键盘底部布局时拿出键盘并在隐藏键盘底部布局时下降...
        猜你喜欢
        • 1970-01-01
        • 2016-07-03
        • 1970-01-01
        • 2019-05-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多