Android Lollipop 软键盘隐藏 DialogFragment 中的用户输入

标签 android scrollview android-softkeyboard android-dialogfragment dialogfragment

我正在编写我的第一个真正的 Android 应用程序。我有一个安卓DialogFragment我显示的内容是为了允许用户添加或编辑所选项目的详细信息。 DialogFragment 弹出并在全屏模式下正常显示。但是,在 Lollipop 模拟器上,当我单击 EditText 时当小部件位于屏幕下方时,软键盘会覆盖小部件,而不是向上滚动屏幕以便用户可以看到他们正在输入的内容。我在 Lollipop 之前的模拟器中没有遇到这种行为。在 KitKat 模拟器上,屏幕会调整为 EditText仍然可见。 StackOverflow 还不让我发布图片。所以,你必须发挥你的想象力。 :-( 我尝试了不同的方法来解决这个问题。不幸的是,没有一个对 Lollipop 有效。

更新 - 我已在运行 Android 5.0.2 的 Sony Xperia Z3 Compact 和 DialogFragment 上对此进行了测试。选择下方 EditText 时不滚动或调整屏幕小部件。

以下是正在使用的样式:

<!-- Base application theme. -->
<style name="AppTheme" parent="AppTheme.Base">
    <!-- Customize your theme here. -->
</style>

<style name="AppTheme.Base" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    <item name="android:textColorPrimary">@color/colorPrimaryText</item>
    <item name="android:textColorSecondary">@color/colorSecondaryText</item>
    <item name="android:dialogTheme">@style/DialogTheme</item>
    <item name="android:actionBarStyle">@style/AppActionBarTheme</item>
    <item name="actionBarStyle">@style/AppActionBarTheme</item>"
    <item name="actionBarTheme">@style/AppActionBarTheme</item>
    <item name="actionBarPopupTheme">@style/AppActionBarOverflowMenuTheme</item>
    <item name="windowActionModeOverlay">true</item>
</style>

<style name="DialogTheme" parent="Theme.AppCompat.Light.Dialog">
    <item name="android:clickable">true</item>
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    <item name="android:windowSoftInputMode">stateHidden|adjustResize</item>
    <item name="windowActionModeOverlay">true</item>
</style>

正如您在 DialogTheme 中看到的那样,我已包含 android:windowSoftInputMode属性。我还尝试在最终包含 DialogFragment 的 Activity 下的 AndroidManifest.xml 文件中使用该属性。 。以下是 DialogFragment 的 XML 布局文件:

<?xml version="1.0" encoding="utf-8"?>
<com.ahappydevelopment.android.fishtales.views.LogEditView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginTop="@dimen/dialog_margin_top"
    android:background="@color/background_material_light"
    android:theme="@style/DialogTheme">

    <include
        android:id="@+id/app_bar"
        layout="@layout/app_bar_edit" />

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/app_bar">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingBottom="@dimen/activity_vertical_margin"
            android:paddingLeft="@dimen/activity_horizontal_margin"
            android:paddingRight="@dimen/activity_horizontal_margin"
            android:paddingTop="@dimen/activity_vertical_margin">

            <Button
                android:id="@+id/btnCatchDate"
                style="?android:attr/borderlessButtonStyle"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:layout_alignParentStart="true"
                android:layout_alignParentTop="true"
                android:textAllCaps="false" />

            <Button
                android:id="@+id/btnCatchTime"
                style="?android:attr/borderlessButtonStyle"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentEnd="true"
                android:layout_alignParentRight="true"
                android:layout_alignParentTop="true"
                android:textAllCaps="false" />

            <EditText
                android:id="@+id/editLatitudeLabel"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:layout_alignParentStart="true"
                android:layout_below="@id/btnCatchDate"
                android:ems="10"
                android:hint="@string/label_latitude"
                android:inputType="numberDecimal" />


            <EditText
                android:id="@+id/editLongitudeLabel"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:layout_alignParentStart="true"
                android:layout_below="@id/editLatitudeLabel"
                android:ems="10"
                android:hint="@string/label_longitude"
                android:inputType="numberDecimal" />

            <ImageView
                android:id="@+id/imgCatchPicture"
                android:layout_width="75dp"
                android:layout_height="75dp"
                android:layout_alignParentEnd="true"
                android:layout_alignParentRight="true"
                android:layout_alignTop="@id/editLatitudeLabel"
                android:background="@android:color/darker_gray"
                android:contentDescription="@string/imgcatchpicture_contentdescription"
                android:scaleType="centerInside"
                android:src="@android:drawable/ic_menu_camera" />

            <Spinner
                android:id="@+id/spinnerLocation"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:layout_alignParentStart="true"
                android:layout_below="@id/editLongitudeLabel" />

            <TextView
                android:id="@+id/txtFishHeader"
                style="?android:attr/listSeparatorTextViewStyle"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:layout_alignParentStart="true"
                android:layout_below="@id/spinnerLocation"
                android:text="@string/section_fish" />

            <Spinner
                android:id="@+id/spinnerSpeciesType"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:layout_alignParentStart="true"
                android:layout_below="@id/txtFishHeader" />

            <EditText
                android:id="@+id/editLengthLabel"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:layout_alignParentStart="true"
                android:layout_below="@id/spinnerSpeciesType"
                android:ems="5"
                android:hint="@string/hint_length"
                android:inputType="numberDecimal" />

            <EditText
                android:id="@+id/editWeightLabel"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentEnd="true"
                android:layout_alignParentRight="true"
                android:layout_below="@id/spinnerSpeciesType"
                android:ems="5"
                android:hint="@string/hint_weight"
                android:inputType="numberDecimal" />

            <EditText
                android:id="@+id/editLengthLabel2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:layout_alignParentStart="true"
                android:layout_below="@id/editLengthLabel"
                android:ems="5"
                android:hint="@string/hint_length"
                android:inputType="numberDecimal" />

            <EditText
                android:id="@+id/editWeightLabel2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentEnd="true"
                android:layout_alignParentRight="true"
                android:layout_below="@id/editWeightLabel"
                android:ems="5"
                android:hint="@string/hint_weight"
                android:inputType="numberDecimal" />

        </RelativeLayout>

    </ScrollView>

</com.ahappydevelopment.android.fishtales.views.LogEditView>

如您所见,我的布局确实包含 ScrollView 。我什至定义了 android:theme="@style/DialogTheme"在布局中。我尝试过设置 android:fillViewport="true"在 ScrollView 上,正如我在另一篇 StackOverflow 帖子中看到的那样。

在 Java 方面,我覆盖了 onCreateDialog方法定义如下:

@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Dialog dialog = new Dialog(getActivity(), R.style.DialogTheme);
    //set to adjust screen height automatically, when soft keyboard appears on screen
    dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
    return dialog;
}

Fragment启动 DialogFragment有一个如下所示的方法:

public void addLogButtonOnClickEvent() {
    LogEditFragment addLog = LogEditFragment.get(0l);
    if(mIsLargeLayout) {
        // The device is using a large layout, so show the fragment as a dialog
        addLog.show(getFragmentManager(), "AddLog");
    } else {
        // The device is smaller, so show the fragment fullscreen
        FragmentTransaction transaction = getFragmentManager().beginTransaction();
        // For a little polish, specify a transition animation
        transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
        // To make it fullscreen, use the 'content' root view as the container
        // for the fragment, which is always the root view for the activity
        transaction.add(android.R.id.content, addLog).addToBackStack(null).commit();
    }
}

正如我所说,这对于 KitKat 模拟器来说运行良好。这不适用于 Lollipop 模拟器。你可以看到我正在非常努力地获取 DialogFragment进行调整调整大小。 :-) 有人看到我遗漏了什么或做错了什么吗?另外,如果我忽略了一些有助于找到解决方案的代码,请告诉我,我也会发布该代码。感谢您提供的任何见解。

最佳答案

我花了一段时间才发现这个答案。实际上,我已将 DialogFragment 重构为 AppCompatActivity。然后我开始认为,为 Android Lollipop 设置的抽屉导航可能是我在使用 DialogFragment 时遇到的问题的罪魁祸首。我的 API 级别 21 及更高版本的 MainActivity 布局文件使用 DrawerLayout 小部件以及用于抽屉导航 View 的 ScrimInsetsFrameLayout。因此,DrawerLayoutScrimInsetsFrameLayout 在其定义中都利用了 android:fitsSystemWindows="true" 作为实现 Material Design UI 规范的一部分抽屉式导航。 DrawerLayout 定义中的 android:fitsSystemWindows="true" 干扰了为 MainActivity 定义的 android:windowSoftInputMode="stateHidden|adjustResize"在 AndroidManifest.xml 文件中,使对话框在软键盘启动时调整和调整大小。这是 MainActivity 的 XML 布局:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout 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:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context=".MainActivity">

    <!-- The Main Content View -->
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <include
            android:id="@+id/app_bar"
            layout="@layout/app_bar_main" />

        <FrameLayout
            android:id="@+id/fragment_main_container"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@id/app_bar" />

    </RelativeLayout>

    <!-- The Navigation Drawer View -->
    <com.ahappydevelopment.android.fishtales.widgets.ScrimInsetsFrameLayout
        android:id="@+id/scrimInsetsFrameLayout"
        android:layout_width="@dimen/navigation_drawer_width"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:elevation="10dp"
        android:fitsSystemWindows="true"
        app:insetForeground="#4000">

        <FrameLayout
            android:id="@+id/fragment_drawer_container"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </com.ahappydevelopment.android.fishtales.widgets.ScrimInsetsFrameLayout>

</android.support.v4.widget.DrawerLayout>

当告诉 FragmentManager 添加 DialogFragment 时,我使用 android.R.id.content 作为 View 容器,这是文档中规定的。通过尝试使用哪个 View 容器,我找到了一个能够提供预期结果的容器。就我而言,它是 MainActivity 布局文件中定义的 DrawerLayout View 。

LogEditFragment addLog = LogEditFragment.get(0l);
if(mIsLargeLayout) {
    // The device is using a large layout, so show the fragment as a dialog
    addLog.show(getFragmentManager(), "AddLog");
} else {
    // The device is smaller, so show the fragment fullscreen
    FragmentTransaction transaction = getFragmentManager().beginTransaction();
    // For a little polish, specify a transition animation
    transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
    // To make it fullscreen, use the 'drawer_layout' view 
    // as the container for the fragment
    transaction.add(R.id.drawer_layout, addLog).addToBackStack(null).commit();
}

完成这些更改并重构我的 LogEditFragment 类以再次扩展 DialogFragment 后,对话框和抽屉导航的行为都符合预期。

关于Android Lollipop 软键盘隐藏 DialogFragment 中的用户输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30131024/

相关文章:

java - 通过点击 Android 中的 "Next"和 "Previous"按钮来更改阵列图像和音频

android - 对所有 API 级别应用相同的样式

Android 自定义数字键盘

android - 您最喜欢在 Android 手机上使用的代码编辑器是什么?

android - 如何通过非 Activity 类从另一个 Activity 获取数据

java - 安卓 Ant 错误 : invalid resource directory name: ./bin/res\crunch

javascript - TypeError : this. path.replace 不是新 FirestoreDelete 的函数

ScrollView 中的 iOS textview 自动调整大小(没有 textview 的滚动条)

android - 如何在 Android 上打开键盘时隐藏广告横幅

xaml - 适用于 Surface 的 Windows Store APP 的页面翻转应用程序, ScrollView 无法正常工作