利用Activity实现一个简单的可输入对话框

whale 2019-06-25

1、需求分析

在应用中这样那样的评论总是少不了的,有的应用是在底部直接加一个EditText和一个Button,让用户输入文字或者表情之后点击按钮提交;而有的虽然也放置了EditText,但仅仅是一个“摆设”,并不具备输入功能,用户点击它后会弹出一个跳转到一个可以真正编辑的页面或者弹出一个可以输入内容的对话框。比如下面这种效果:

利用Activity实现一个简单的可输入对话框

这里的效果可以细分为四点:

  1. 点击底部的按钮之后会弹出对话框,对话框在布局的底部;
  2. 对话框中有输入框EditText,可以输入内容;
  3. 对话框弹出后EditText会自动获取焦点,弹出软键盘;
  4. 软键盘会把对话框顶上去,便于用户编辑。

一开始我想到的是PopupWindow,但是由于里面有EditText,与软键盘交互起来很是头疼,于是改用了Activity。这样一来我们就可以像用Activity一样使用这个对话框,方便多了。不过毕竟跟我们平时使用的Activity还是有所不同的,特别是要设置好它的样式,否则也是一堆的坑啊。

2、对话框Activity的布局与样式

下面就来着手实现我们想要的对话框了。新建一个工程,MainActivity只是一个配角,底部放一个按钮就搞定。我们的主角是DialogActivity,它的布局很简单,就跟平时的Activity一样:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_gravity="bottom"
        android:background="@android:color/white"
        android:orientation="vertical"
        android:paddingLeft="10dp"
        android:paddingRight="10dp">

        <EditText
            android:id="@+id/et_comment"
            android:layout_width="match_parent"
            android:layout_height="150dp"
            android:layout_marginTop="15dp"
            android:background="#f0f0f0"
            android:focusable="true"
            android:focusableInTouchMode="true"
            android:gravity="left|top"
            android:hint="我來說一說~"
            android:paddingBottom="5dp"
            android:paddingLeft="8dp"
            android:paddingRight="8dp"
            android:paddingTop="5dp"
            android:textSize="14dp" />

        <Button
            android:textColor="@android:color/white"
            android:background="@android:color/holo_blue_light"
            android:id="@+id/btn_submit"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="right"
            android:layout_marginBottom="10dp"
            android:layout_marginTop="10dp"
            android:padding="5dp"
            android:text="發表評論"
            android:textSize="16sp" />
    </LinearLayout>

</LinearLayout>

重点是它的样式,看下面的代码:

<!--可输入对话框的样式 -->
    <style name="EditDialogStyle" parent="Theme.AppCompat.Light.NoActionBar">
        //设置背景
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:windowSoftInputMode">adjustResize|stateHidden</item>
        //Dialog的windowFrame框为无
        <item name="android:windowFrame">@null</item>
        //是否显示标题,true则去掉默认的标题栏
        <item name="android:windowNoTitle">true</item>
        //是否浮现在activity之上,false的话会被软键盘覆盖
        <item name="android:windowIsFloating">true</item>
        //是否半透明,为false时背景为黑色不透明
        <item name="android:windowIsTranslucent">true</item>
        //是否有覆盖
        <item name="android:windowContentOverlay">@null</item>
        //Activity的动画效果
        <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
        //背景是否模糊显示,为false时效果为全透明
        <item name="android:backgroundDimEnabled">true</item>
        //点击空白处时是否销毁Activity
        <item name="android:windowCloseOnTouchOutside">true</item>
    </style>

要设置的属性很多,我都做了注释了,大家明白每个属性的作用就行,这里就细说了。别忘了,到清单文件中给DialogActivity用上这个主题:

<activity android:name=".DialogActivity"
            android:configChanges="orientation|screenSize"
            android:screenOrientation="portrait"
            android:theme="@style/EditDialogStyle"/>

运行一下,相信大家可以看到效果了。

3、自动弹出软键盘效果

对话框的界面我们已经做好了,但是为了用户体验更好,我们要在对话框出现的时候自动弹出软键盘。下面介绍两种方法:

3.1、使用InputMethodManager类显示软键盘

我们平时要让某个EditText获得焦点自动弹出软键盘可以这样写:

InputMethodManager inputManager =(InputMethodManager)etComment.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
   inputManager.showSoftInput(etComment, 0);

但是这里面有一点要注意:我们想要让EditText获得焦点,那必须等界面绘制完毕才行。所以这样设置了延迟300ms执行弹出软键盘的代码,给界面留出绘制的时间:

new Handler(new Handler.Callback() {
            @Override
            public boolean handleMessage(Message msg) {
                InputMethodManager inputManager =
                        (InputMethodManager) etComment.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
                inputManager.showSoftInput(etComment, 0);
                return false;
            }
        }).sendEmptyMessageDelayed(0, 300);

加上上面的代码,你就可以软键盘自己弹出来了。

3.1、设置windowSoftInputMode属性

你如果细心的话一定发现前面给DialogActivity设置样式的代码中有一个windowSoftInputMode属性没有添加注释,请原谅我卖了个关子。这个属性是设置窗口和软键盘的交互模式的。它的属性有很多,可以参考我后面给出的参考文章。这里我们用到了adjustResize,它的作用就是调整界面布局给软键盘留出足够的空间。那么stateHidden呢?其实软键盘没有自动弹出就是它搞的鬼,它表示一般情况下软键盘都是隐藏的。我们改成另外一个属性:stateVisible,它表示软键盘通常是可见的。

再来运行一下,软键盘就如期而至了。

4、后记

我们在需求分析中提到的效果已经实现完毕。后来我还想过给对话框增加自定义的动画效果,但是退出时的动画始终没有设置成功,所以如果有读者实现了,欢迎交流学习。源码我保存到了码云,需要的话可以参考:
可输入对话框源码

5、参考文章

android:windowSoftInputMode属性详解
彻底搞定Android开发中软键盘的常见问题

相关推荐