【问题标题】:windowSoftInputMode="adjustResize" not working with translucent action/navbarwindowSoftInputMode="adjustResize" 不适用于半透明动作/导航栏
【发布时间】:2014-02-01 07:02:17
【问题描述】:

我在新的Android KitKat (4.4) 和windowSoftInputMode="adjustResize" 中遇到了半透明操作栏/导航栏的问题。

通常,将 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>

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

片段.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>

有解决这个问题的想法吗?

【问题讨论】:

标签: android resize statusbar android-4.4-kitkat window-soft-input-mode


【解决方案1】:

您缺少以下属性:

android:fitsSystemWindows="true"

fragment .xml 布局的根 RelativeLayout 中。

更新:

去年 Chris Bane 进行了一次有趣的演讲,详细解释了它的工作原理:

https://www.youtube.com/watch?v=_mGDMVRO3iE

【讨论】:

    【解决方案2】:

    有一个相关的错误报告here。我从有限的测试中找到了一种解决方法,似乎可以解决问题而没有任何影响。使用以下逻辑添加您的根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);
        }
    }
    

    由于fitSystemWindows 已被弃用,请参阅下面的答案以完成解决方法。

    【讨论】:

    • 根据我的经验,实际上 SOFT_INPUT_ADJUST_PAN 似乎不会被忽略 - 它会向上移动整个屏幕,包括系统栏和焦点视图下的移动键盘。
    • 谢谢 - 您对 SOFT_INPUT_ADJUST_PAN 的看法是正确的。我在我的片段中使用了这个:getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
    • 这是我可以实现为活动调整调整大小(在显示键盘时滚动视图所需)的唯一方法,将 fitSystemWindows 设置为 true 以便滚动实际发生在 >= Lollipop 并具有半透明状态栏。非常感谢。
    【解决方案3】:

    @kcoppock 的回答确实很有帮助,但 fitSystemWindows 在 API 级别 20 中已被弃用

    因此,从 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;
        }
    }
    

    【讨论】:

    • 我看不出你的解决方案和@kcoppock 的答案有什么不同。测试了两者。当我使用您的方法时,必须使用相同的待办事项 1 - 5,包括 kcoppock 答案的 fitSystemWindows。当我省略 fitSystemWindows 时,状态栏是半透明的,但 windowSoftInputMode=“adjustResize” 不起作用(我看不到我正在写的输入)
    【解决方案4】:

    这对我来说有半透明的状态栏和片段中的调整大小:

    1. 按照@Victor91 和@kcoppock 所说,制作一个自定义RelativeLayout。

    2. 使用 CustomRelativeLayout 作为片段的父布局。

    3. 用 android:windowTranslucentStatus = true 声明主题

    4. 容器 Activity 必须在 Manifest 中声明为 android:windowSoftInputMode="adjustResize" 并使用声明的 主题

    5. 请在片段根布局上使用 fitSystemWindows!

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

    然后在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>
    

    【讨论】:

    • 这是迄今为止最好的答案,我现在正在寻找解决方案。它工作得很好,但是你必须在你的工具栏上添加一些额外的填充,没有它你的工具栏将重叠状态栏
    【解决方案5】:

    如果您想自定义插图并且目标 API 级别 >=21,则无需创建自定义视图组即可完成此操作。默认情况下,只需设置fitsSystemWindows 填充将应用于您的容器视图,您可能不希望这样做。

    版本检查内置在此方法中,只有 >= 21 的设备会执行 lambda 中的代码。 Kotlin 示例:

    ViewCompat.setOnApplyWindowInsetsListener(container) { view, insets ->
      insets.replaceSystemWindowInsets(0, 0, 0, insets.systemWindowInsetBottom).apply {
        ViewCompat.onApplyWindowInsets(view, this)
      }
    }
    

    确保您的布局仍然设置fitsSystemWindows 标志,否则不会调用窗口插入侦听器。

    <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        />
    

    这些资源很有帮助:

    https://medium.com/google-developers/why-would-i-want-to-fitssystemwindows-4e26d9ce1eec https://medium.com/@azizbekian/windowinsets-24e241d4afb9

    【讨论】:

    • 这仍然是最好的方法,因为您可以应用这是您的 BaseFragment 以及 view.fitsSystemWindows = true,并且它无需对实际 XML 布局或视图子类进行任何更改即可工作。
    • 想指出,该解决方案可能不适用于充当container 的某些视图(在我的情况下是ConstraintLayout)。解决方法是用FrameLayout 包裹我的布局,这成为一个新的container。欣赏解决方案!
    【解决方案6】:

    我遇到了同样的问题, 我的 Activity 有一个 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" />
    

    【讨论】:

      【解决方案7】:

      @Victor RendinaanswerreplaceSystemWindowInsetssystemWindowInsetBottom 方法弃用引起的小幅更新。

      先决条件:

      • API >= 21
      • implementation 'androidx.core:core-ktx:1.5.0-alpha02' 至少

      Kotlin 扩展:

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

      用法:

      rootView.fitSystemWindowsAndAdjustResize()
      

      rootView 实际上是布局的根视图 :)

      注意: 如果扩展不适用于您的根视图(我在将ConstraintLayout 用作rootView 时遇到了这个问题)用FrameLayout 包裹整个布局以便FrameLayout 成为新的根视图

      【讨论】:

        【解决方案8】:

        基于 Joseph Johnson 在Android How to adjust layout in Full Screen Mode when softkeyboard is visible 中的解决方法

        在您的活动中在setContentView() 之后在onCreate() 中调用它。

        AndroidBug5497Workaround.assistActivity(this);

        与原来的略有不同,在computeUsableHeight() 中将return (r.bottom - r.top); 替换为return r.bottom;

        出于某种原因,我必须将我的活动fitsSystemWindows 属性设置为false

        这个解决方法救了我。它对我很有效。希望能帮到你。

        实现类是:

        public class AndroidBug5497Workaround {
        
        // For more information, see https://code.google.com/p/android/issues/detail?id=5497
        // To use this class, simply invoke assistActivity() on an Activity that already has its content view set.
        
        public static void assistActivity (Activity activity) {
            new AndroidBug5497Workaround(activity);
        }
        
        private View mChildOfContent;
        private int usableHeightPrevious;
        private FrameLayout.LayoutParams frameLayoutParams;
        
        private AndroidBug5497Workaround(Activity activity) {
            FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content);
            mChildOfContent = content.getChildAt(0);
            mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                public void onGlobalLayout() {
                    possiblyResizeChildOfContent();
                }
            });
            frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams();
        }
        
        private void possiblyResizeChildOfContent() {
            int usableHeightNow = computeUsableHeight();
            if (usableHeightNow != usableHeightPrevious) {
                int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();
                int heightDifference = usableHeightSansKeyboard - usableHeightNow;
                if (heightDifference > (usableHeightSansKeyboard/4)) {
                    // keyboard probably just became visible
                    frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
                } else {
                    // keyboard probably just became hidden
                    frameLayoutParams.height = usableHeightSansKeyboard;
                }
                mChildOfContent.requestLayout();
                usableHeightPrevious = usableHeightNow;
            }
        }
        
        private int computeUsableHeight() {
            Rect r = new Rect();
            mChildOfContent.getWindowVisibleDisplayFrame(r);
            return r.bottom;
        }
        
        }
        

        【讨论】:

          【解决方案9】:

          首先在你的根布局中添加这个。

          android:fitsSystemWindows="true"
          

          当您使用这种方法时,您有责任确保应用 UI 的关键部分(例如,地图应用中的内置控件)最终不会被系统栏覆盖。这可能会使您的应用程序无法使用。在大多数情况下,您可以通过将 android:fitsSystemWindows 属性添加到 XML 布局文件中来处理这个问题,并将其设置为 true。这会调整父 ViewGroup 的填充以为系统窗口留出空间。这对于大多数应用程序来说已经足够了。

          但是,在某些情况下,您可能需要修改默认填充以获得应用所需的布局。要直接操纵您的内容相对于系统栏的布局(占据称为窗口的“内容插入”的空间),请覆盖 fitSystemWindows(Rect insets)。当窗口的内容插入发生变化时,视图层次结构会调用 fitSystemWindows() 方法,以允许窗口相应地调整其内容。通过覆盖此方法,您可以随心所欲地处理插图(以及应用程序的布局)。

          https://developer.android.com/training/system-ui/status#behind

          如果你想成为一个窗口装配大师,请观看安卓开发者的视频。 https://www.youtube.com/watch?v=_mGDMVRO3iE

          【讨论】:

            【解决方案10】:

            它不应该与半透明状态栏一起使用;该设置强制窗口进入全屏模式,这不适用于adjustResize。

            您可以使用adjustPan 或使用fitsSystemWindows 属性。我建议您阅读有关该功能的信息,但它具有显着的副作用:

            https://medium.com/google-developers/why-would-i-want-to-fitssystemwindows-4e26d9ce1eec

            【讨论】:

              【解决方案11】:

              我遇到了一个问题。

              我将 windowDrawsSystemBarBackgrounds 设置为“true”,我的应用应该显示在状态栏下。

              这是我的活动主题。

              <item name="android:windowTranslucentStatus" tools:targetApi="KITKAT">false</item>
              <item name="android:windowDrawsSystemBarBackgrounds">true</item>
              <item name="android:windowTranslucentNavigation">true</item>
              <item name="android:statusBarColor">@android:color/transparent</item>
              

              我得到了jianshu's blog 的帮助。 您可以阅读代码,但可以像我一样阅读文本。 我添加了一些代码。

              public final class ZeroInsetsFrameLayout extends FrameLayout {
                  private int[] mInsets = new int[4];
              
                  public ZeroInsetsFrameLayout(Context context) {
                      super(context);
                  }
              
                  public ZeroInsetsFrameLayout(Context context, AttributeSet attrs) {
                      super(context, attrs);
                  }
              
                  public ZeroInsetsFrameLayout(Context context, AttributeSet attrs, int defStyle) {
                      super(context, attrs, defStyle);
                  }
              
                  public final int[] getInsets() {
                      return mInsets;
                  }
              
                  @Override
                  public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
                      outLocalInsets.left = 0;
                      outLocalInsets.top = 0;
                      outLocalInsets.right = 0;
              
                      return super.computeSystemWindowInsets(in, outLocalInsets);
                  }
              
                  @Override
                  protected final boolean fitSystemWindows(@NonNull 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);
                  }
              }
              

              这是我的片段布局。

              <com.dhna.widget.ZeroInsetsFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
                  xmlns:app="http://schemas.android.com/apk/res-auto"
                  xmlns:tools="http://schemas.android.com/tools"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent"
                  android:fitsSystemWindows="true"
                  android:background="@color/white">
              
                  <!-- your xml code -->
              
              </ZeroInsetsFrameLayout>
              

              我希望它对您有所帮助。 祝你好运!

              【讨论】:

              • 我几乎得了抑郁症。我以为只有透明状态栏有问题。经过2小时的搜索。终于得到了你的答案。你拯救了我的一天。谢谢!
              【解决方案12】:

              AndroidBug5497Workaround.java 注意内存泄漏。需要下面的代码

              getViewTreeObserver().removeOnGlobalLayoutListener(listener);
              

              我使用 RxJava 的示例在 Activity 生命周期中的 onPause() 时会自动调用 removeOnGlobalLayoutListener()

              public class MyActivity extends RxAppCompatActivity {
                  // ...
              
              protected void onStart(){
                  super.onStart();
              
                      TRSoftKeyboardVisibility
                          .changes(this) // activity
                          .compose(this.<TRSoftKeyboardVisibility.ChangeEvent>bindUntilEvent(ActivityEvent.PAUSE))
                          .subscribe(keyboardEvent -> {
                              FrameLayout content = (FrameLayout) findViewById(android.R.id.content);
                              View firstChildView = content.getChildAt(0);
                              firstChildView.getLayoutParams().height = keyboardEvent.viewHeight();
                              firstChildView.requestLayout();
              
                              // keyboardEvent.isVisible      = keyboard visible or not
                              // keyboardEvent.keyboardHeight = keyboard height
                              // keyboardEvent.viewHeight     = fullWindowHeight - keyboardHeight
                          });
                 //...
              }
              
              
              
              
              
              package commonlib.rxjava.keyboard;
              
              import android.app.Activity;
              import android.view.View;
              import android.widget.FrameLayout;
              import kr.ohlab.android.util.Assert;
              import rx.Observable;
              
              public class TRSoftKeyboardVisibility {
              
                  public static Observable<ChangeEvent> changes(Activity activity) {
                      Assert.notNull(activity, "activity == null");
                      FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content);
                      View childOfContent = content.getChildAt(0);
                      return Observable.create(
                          new TRSoftKeyboardVisibilityEventOnSubscribe(childOfContent));
                  }
              
                  public static final class ChangeEvent {
                      private final int keyboardHeight;
                      private final boolean visible;
                      private final int viewHeight;
              
                      public static ChangeEvent create(boolean visible, int keyboardHeight,
                          int windowDisplayHeight) {
                          return new ChangeEvent(visible, keyboardHeight, windowDisplayHeight);
                      }
              
                      private ChangeEvent(boolean visible, int keyboardHeight, int viewHeight) {
                          this.keyboardHeight = keyboardHeight;
                          this.visible = visible;
                          this.viewHeight = viewHeight;
                      }
              
                      public int keyboardHeight() {
                          return keyboardHeight;
                      }
              
                      public boolean isVisible() {
                          return this.visible;
                      }
              
                      public int viewHeight() {
                          return viewHeight;
                      }
              
                      @Override
                      public boolean equals(Object o) {
                          if (this == o) return true;
                          if (!(o instanceof ChangeEvent)) return false;
              
                          ChangeEvent that = (ChangeEvent) o;
              
                          if (keyboardHeight != that.keyboardHeight) return false;
                          if (visible != that.visible) return false;
                          return viewHeight == that.viewHeight;
                      }
              
                      @Override
                      public int hashCode() {
                          int result = keyboardHeight;
                          result = 31 * result + (visible ? 1 : 0);
                          result = 31 * result + viewHeight;
                          return result;
                      }
              
                      @Override
                      public String toString() {
                          return "ChangeEvent{" +
                              "keyboardHeight=" + keyboardHeight +
                              ", visible=" + visible +
                              ", viewHeight=" + viewHeight +
                              '}';
                      }
                  }
              }
              
              
              package commonlib.rxjava.keyboard;
              
              import android.graphics.Rect;
              import android.view.View;
              import android.view.ViewTreeObserver;
              import kr.ohlab.android.util.Assert;
              import rx.Observable;
              import rx.Subscriber;
              import rx.android.MainThreadSubscription;
              import timber.log.Timber;
              
              public class TRSoftKeyboardVisibilityEventOnSubscribe
                  implements Observable.OnSubscribe<TRSoftKeyboardVisibility.ChangeEvent> {
                  private final View mTopView;
                  private int mLastVisibleDecorViewHeight;
                  private final Rect mWindowVisibleDisplayFrame = new Rect();
              
                  public TRSoftKeyboardVisibilityEventOnSubscribe(View topView) {
                      mTopView = topView;
                  }
              
                  private int computeWindowFrameHeight() {
                      mTopView.getWindowVisibleDisplayFrame(mWindowVisibleDisplayFrame);
                      return (mWindowVisibleDisplayFrame.bottom - mWindowVisibleDisplayFrame.top);
                  }
              
                  private TRSoftKeyboardVisibility.ChangeEvent checkKeyboardVisibility() {
                      int windowFrameHeightNow = computeWindowFrameHeight();
                      TRSoftKeyboardVisibility.ChangeEvent event = null;
                      if (windowFrameHeightNow != mLastVisibleDecorViewHeight) {
                          int mTopViewHeight = mTopView.getHeight();
                          int heightDiff = mTopViewHeight - windowFrameHeightNow;
                          Timber.e("XXX heightDiff=" + heightDiff);
                          if (heightDiff > (mTopViewHeight / 4)) {
                              event = TRSoftKeyboardVisibility.ChangeEvent.create(true, heightDiff, windowFrameHeightNow);
                          } else {
                              event = TRSoftKeyboardVisibility.ChangeEvent.create(false, 0, windowFrameHeightNow);
                          }
                          mLastVisibleDecorViewHeight = windowFrameHeightNow;
                          return event;
                      }
              
                      return null;
                  }
              
                  public void call(final Subscriber<? super TRSoftKeyboardVisibility.ChangeEvent> subscriber) {
                      Assert.checkUiThread();
              
                      final ViewTreeObserver.OnGlobalLayoutListener listener =
                          new ViewTreeObserver.OnGlobalLayoutListener() {
                              @Override
                              public void onGlobalLayout() {
                                  TRSoftKeyboardVisibility.ChangeEvent event = checkKeyboardVisibility();
                                  if( event == null)
                                      return;
                                  if (!subscriber.isUnsubscribed()) {
                                      subscriber.onNext(event);
                                  }
                              }
                          };
              
                      mTopView.getViewTreeObserver().addOnGlobalLayoutListener(listener);
              
                      subscriber.add(new MainThreadSubscription() {
                          @Override
                          protected void onUnsubscribe() {
                              mTopView.getViewTreeObserver().removeOnGlobalLayoutListener(listener);
                          }
                      });
                  }
              }
              

              【讨论】:

                【解决方案13】:

                我遇到了同样的问题。我已经使用 coordinatorlayout 解决了

                activity.main.xml

                <?xml version="1.0" encoding="utf-8"?>
                <android.support.design.widget.CoordinatorLayout
                    android:layout_height="match_parent" android:layout_width="match_parent"
                    xmlns:tools="http://schemas.android.com/tools"
                    xmlns:app="http://schemas.android.com/apk/res-auto"
                    xmlns:android="http://schemas.android.com/apk/res/android">
                
                
                    <android.support.design.widget.AppBarLayout
                    android:layout_height="wrap_content"
                    android:layout_width="match_parent"
                    android:theme="@style/AppTheme.AppBarOverlay">
                
                    <android.support.v7.widget.Toolbar
                        android:layout_height="?attr/actionBarSize"
                        android:layout_width="match_parent"
                        app:popupTheme="@style/AppTheme.PopupOverlay"
                        android:background="?attr/colorPrimary"
                        android:id="@+id/toolbar"/>
                
                </android.support.design.widget.AppBarLayout>
                
                    <include layout="@layout/content_main2"/>
                
                </android.support.design.widget.CoordinatorLayout>
                

                content_main2.xml

                <?xml version="1.0" encoding="utf-8"?>
                <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    xmlns:app="http://schemas.android.com/apk/res-auto">
                
                
                    <android.support.v7.widget.RecyclerView
                        android:layout_height="match_parent"
                        android:layout_width="match_parent"
                        android:layout_marginTop="30dp"
                        android:layout_marginBottom="30dp"
                        app:layout_scrollFlags="scroll|exitUntilCollapsed"
                        android:id="@+id/post_msg_recyclerview">
                    </android.support.v7.widget.RecyclerView>
                
                    <EditText
                        android:layout_width="match_parent"
                        android:layout_height="50dp"
                        app:layout_constraintBottom_toBottomOf="parent"
                        android:background="@color/colorPrimary"
                
                
                        />
                
                </android.support.constraint.ConstraintLayout>
                

                MainActivity.java

                现在添加这一行 linearLayoutManager.setStackFromEnd(true);

                 LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
                        linearLayoutManager.setStackFromEnd(true);
                        recyclerView.setLayoutManager(linearLayoutManager);
                        Adapter adapter1=new Adapter(arrayList);
                        recyclerView.setAdapter(adapter1);
                

                【讨论】:

                  【解决方案14】:
                  <androidx.constraintlayout.widget.ConstraintLayout
                    android:fitsSystemWindows="true">
                  
                    <androidx.coordinatorlayout.widget.CoordinatorLayout>
                      <com.google.android.material.appbar.AppBarLayout>
                  
                        <com.google.android.material.appbar.CollapsingToolbarLayout/>
                  
                      </com.google.android.material.appbar.AppBarLayout>
                  
                      <androidx.core.widget.NestedScrollView>
                      <Editext/>
                      <androidx.core.widget.NestedScrollView/>
                  
                    </androidx.coordinatorlayout.widget.CoordinatorLayout>
                  
                  </androidx.constraintlayout.widget.ConstraintLayout>
                  

                  【讨论】:

                    【解决方案15】:

                    这是我使用的 在 xml 文件的主视图中,您将添加这个

                    android:animateLayoutChanges="true"
                    

                    然后在“onCreate”函数中,您将在每件事之前获得像这样的状态栏大小

                    int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
                    if (resourceId > 0)
                    {
                        status_bar=getResources().getDimensionPixelSize(resourceId);
                    }
                    

                    然后最后在“onCreate”中添加这个来更新大小

                            main_view= findViewById(R.id.the_main);
                            main_view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener()
                            {
                                @Override
                                public void onGlobalLayout()
                                {
                                    Rect r = new Rect();
                                    View view = getWindow().getDecorView();
                                    view.getWindowVisibleDisplayFrame(r);
                                    if (Math.abs(old_size - r.height()) > 100)
                                    {
                                        ViewGroup.LayoutParams params = main_view.getLayoutParams();
                                        params.height = r.height()+ status_bar ;
                                        main_view.setLayoutParams(params);
                                    }
                                    old_size = r.height();
                                }
                            });
                    

                    【讨论】:

                      【解决方案16】:

                      最佳做法是允许用户在显示键盘时滚动内容。 因此,要添加此功能,您需要将根布局放入 ScrollView 并使用 windowSoftInputMode="adjustResize" 活动方法。

                      但是,如果您想在 Android 5 上使用带有 <item name="android:windowTranslucentStatus">true</item> 标志的此功能,内容将无法滚动并且会与键盘重叠。

                      要解决这个问题,请查看answer

                      【讨论】:

                        【解决方案17】:
                        • 在我研究了所有论坛之后。那些方法不由得找出来点。当我尝试这样做时很幸运。它帮助我解决了问题

                        XML

                        <RelativeLayout 
                              xmlns:android="http://schemas.android.com/apk/res/android"
                              android:layout_width="match_parent"
                              android:layout_height="match_parent"
                              android:fitsSystemWindows="true">
                               <!-- Your xml -->
                            </RelativeLayout>
                        

                        活动

                        @Override
                        protected void onCreate(Bundle savedInstanceState) {
                           super.onCreate(savedInstanceState);
                           setContentView("Your Activity");
                           setAdjustScreen();
                        
                        }
                        

                        创建函数

                        protected void setAdjustScreen(){
                                getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
                                getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
                                /*android:windowSoftInputMode="adjustPan|adjustResize"*/
                        }
                        

                        最后在你的 mainifest 中添加几行

                         <activity
                             android:name="Your Activity"
                             android:windowSoftInputMode="adjustPan|adjustResize"
                             android:screenOrientation="portrait"></activity>
                        

                        【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          相关资源
                          最近更新 更多