【问题标题】:Android Lollipop Soft Keyboard Hides User Inputs in DialogFragmentAndroid Lollipop 软键盘在 DialogFragment 中隐藏用户输入
【发布时间】:2015-05-08 19:00:43
【问题描述】:

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

更新 - 我在索尼xperia z3 compact android 5.0.2上测试了这个,并且在选择leow EditText小部件时,DialogFragment 987654324 @ DialogFragment /p>

以下是使用的样式:

<!-- 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"。正如我在另一个 StackOverflow 帖子中看到的那样,我尝试在 ScrollView 上设置 android:fillViewport="true"

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

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

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 调整大小。 :-) 有没有人看到我错过了什么或做错了什么?另外,如果我忽略了包含有助于找到解决方案的代码,请告诉我,我也会发布。感谢您提供的任何见解。

【问题讨论】:

    标签: android scrollview android-softkeyboard android-dialogfragment dialogfragment


    【解决方案1】:

    我花了一段时间才发现这个答案。我实际上已经将我的DialogFragment 重构为AppCompatActivity。然后我开始认为,也许为 Android Lollipop 设置的导航抽屉可能是我在使用 DialogFragment 时遇到的问题的罪魁祸首。我的 API 级别 21 及更高级别的 MainActivity 布局文件使用 DrawerLayout 小部件和 ScrimInsetsFrameLayout 用于导航抽屉视图。因此,DrawerLayoutScrimInsetsFrameLayout 在其定义中都使用了android:fitsSystemWindows="true",作为实现导航抽屉的 Material Design UI 规范的一部分。 DrawerLayout 定义中的 android:fitsSystemWindows="true" 会干扰 AndroidManifest.xml 文件中为 MainActivity 定义的 android:windowSoftInputMode="stateHidden|adjustResize",从而导致对话框在启动软键盘时进行调整和调整大小。这是 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 作为文档中规定的视图容器。通过试验使用哪个视图容器,我能够找到一个给出预期结果的容器。在我的例子中,它是 MainActivity 布局文件中定义的 DrawerLayout 视图。

    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 后,对话框和导航抽屉的行为都符合预期。

    【讨论】:

      猜你喜欢
      • 2014-04-07
      • 2013-12-09
      • 2012-10-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-14
      • 2019-06-17
      • 2016-10-19
      相关资源
      最近更新 更多