fix dialog 输入法总是移动布局

2020-11-30  本文已影响0人  王家匀匀

需求:

dialog固定高度、显示在屏幕底部,dialog中有一个EditText ,位置在布局上方且不会被键盘盖住。
所以要求,输入法不移动dialog布局,正常盖住即可。

问题:

dialog无论怎么设置,输入法总是会顶起布局,整个布局上移。

解决办法:

直接说答案----用activity代替dialog。
一定要注意 Android8.0 全屏透明页面不能设置页面方向,不然会奔溃。
参考 https://www.jianshu.com/p/aeccccd9117a

各种失败经验:

Dialog,AlertDialog,DialogFragment,AppCompatDialogFragment全部无效。

无论是 dialog.setView 还是dialog.setContentView.

无论是设置高度 march_parent,然后顶部透明;还是固定高度,gravity 为bottom。

无论是约束性布局、线性布局、FrameLayout作为根布局、即使是约束性布局(高度march_parent), 里面设置 app:layout_constraintBottom_toBottomOf="parent",键盘弹起来都会移动布局;

尝试了各种SoftInputMode,无论是adjustNothing、adjustResize、adjustPan
无论这个SoftInputMode设置的是activity还是dialog.window.setSoftInputMode都不行,在这里,adjustNothing效果等同于adjustPan。
android:windowSoftInputMode="adjustPan|stateHidden"

在activity中设置输入法监听,没有效果。在dialogFragment 中以及activity中设置
KeyboardUtils.fixAndroidBug5497(this.activity)都。。。

好吧,我认输。
那就用透明activity来代替dialog以及dialogFragment吧。

 <!-- 弹框效果,设置全屏。 -->
    <style name="activityBottomDialog" parent="@android:style/Theme.Black.NoTitleBar.Fullscreen">
        <!-- 背景透明 -->
        <item name="android:windowBackground">@android:color/transparent</item>
        <!-- 是否透明 -->
        <item name="android:windowIsTranslucent">false</item>
        <!-- 模糊 -->
        <item name="android:backgroundDimEnabled">false</item>
        <!--全屏-->
        <item name="android:windowFullscreen">true</item>
    </style>

在清单文件中设置style:

<activity android:name=".YourActivity"
       android:theme="@style/activityBottomDialog"     
       android:windowSoftInputMode="adjustNothing|stateHidden"
       android:screenOrientation="portrait" />

这里要格外注意继承的theme 是哪个。如果activity继承自AppCompatActivity,非Theme.AppCompat子类就会奔溃:

 Caused by: java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.
同时还需要设置动画,从底部进入

https://blog.csdn.net/xuewater/article/details/36398803
修改后如下:

 <style name="activityBottomDialog" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowFullscreen">true</item>
        <item name="windowNoTitle">true</item>
<!--设置页面进出动效,现在给的是从下进下出效果-->
        <item name="android:windowAnimationStyle">@style/animationTranslucentTranslate</item>

    </style>

    <style name="animationTranslucentTranslate" parent="@android:style/Animation.Translucent">
        <item name="android:windowEnterAnimation">@anim/slide_in_bottom</item>
        <item name="android:windowExitAnimation">@anim/slide_out_bottom</item>
<!--设置背景模糊效果,activity 中内容外部区域不设置背景色-->
        <item name="android:backgroundDimEnabled">true</item>
    </style>

//slide_in_bottom
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="200"
        android:fromYDelta="100.0%"
        android:toYDelta="0.0%" />
</set>

//slide_out_bottom
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="400"
        android:fromYDelta="0.0%"
        android:toYDelta="100.0%" />
</set>

anim 文件位于:src/main/res/anim。
这里如果不需要自定义动画效果,使用系统自带的@android:style/Animation.Translucent 样式也是可以的。效果基本是直接出来,可以看到代码是一个轻微移动和一个透明渐变效果。

还要注意:

activity 宽高都是match_parent;
activity中,顶部透明区域,要设置点击事件,关闭activity。
(模拟dialog.isCancelable=true,有内容区域设置clickable=true,就不会响应点击事件了)

那么,现在只差一个细节了:自动关闭输入法。

可以看到在小米8se\android 10 手机上,关闭弹框时输入法会自动消失,但是关闭弹框后 输入法又出来了(有的手机并不会在关闭页面时自动关闭输入法)。那么:
step1: 在此弹框页面 onDestroy 时关闭弹框:

private fun hideInputMethod() {
    val imm: InputMethodManager? = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
         imm?.hideSoftInputFromWindow(binding.edtSearch.windowToken, 0)
 }

step2:设置上级activity输入法模式为stateAlwaysHidden(无论如何不显示输入法)

android:windowSoftInputMode="stateAlwaysHidden"

第二步不能省略,不然在8se手机上,会恢复输入法。
也尝试了 stateHidden, 不行, 输入法关不掉。

至此,大功告成。

上一篇下一篇

猜你喜欢

热点阅读