30

我有一个使用这种布局的人造对话框:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout    xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_height="match_parent"
                android:layout_width="match_parent"
                android:id="@+id/containerPageConatiner">

    <FrameLayout    android:id="@+id/dialogHolder"
                    android:layout_height="wrap_content"
                    android:layout_width="wrap_content"
                    android:padding="15dp"
                    android:layout_gravity="center"
                    android:background="@drawable/panel_picture_frame_bg_focus_blue"/>    
</FrameLayout> 

<FrameLayout>我根据正在打开的对话框放置一个片段- 控制对话框的活动如下所示:

<activity
    android:label="@string/app_name"
    android:name=".activity.DialogActivity"
    android:theme="@style/CustomTheme.Screen.Transparent" 
    android:windowSoftInputMode="adjustResize">

不幸的是,当您单击对话框内的编辑文本时,不会调整大小。windowSoftInputMode字面上没有区别,因为功能与平移模式相同。

文档说“这当然只适用于具有可调整大小的区域的应用程序,可以缩小以腾出足够的空间”,但没有告诉你“可调整大小的区域”是什么意思,让我觉得在某种程度上我不知道t有一个可调整大小的区域?

如果有人知道发生了什么,他们可以帮助我吗?

编辑

像这样围绕对话框不会改变任何东西:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/containerPageConatiner"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <View
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_weight="1" />

    <FrameLayout    
        android:id="@+id/dialogHolder"
        android:layout_height="wrap_content"
    android:layout_width="wrap_content"
        android:padding="15dp"
        android:layout_gravity="center"
        android:background="@drawable/panel_picture_frame_bg_focus_blue"/>

    <View
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_weight="1" />
</LinearLayout>

编辑2

Scrollview 作为父级也无济于事:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/containerPageConatiner"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <FrameLayout
            android:id="@+id/dialogHolder"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:padding="15dp" />

</ScrollView>
4

9 回答 9

52

我创建了一个新项目,以尝试获得用于调整窗口大小的基本功能,并慢慢将其移向我项目的目标部分。这样做我将问题归结为:

在我的主题层次结构中,我有这个属性:

<item name="android:windowFullscreen">true</item> 

它被埋葬在Theme.Black.NoTitleBar.FullScreen- 我的自定义主题的祖先。

文档表明这是一个“指示此窗口是否应填满整个屏幕的标志” 。如果您有一个占据整个屏幕的应用程序,这听起来是一件好事……除了它仍然占据整个屏幕而没有标志。

事实上,一旦你把它拿出来,应用程序完全没有任何变化......除了adjustResize现在完美无缺。

于 2011-12-06T14:52:18.227 回答
49

不久前,我在创建的库中也遇到了同样的问题。(材料抽屉

据我所见,所有提供的答案都没有解决主要问题,他们只是指出删除全屏标志(android:windowFullscreen),这对许多人来说都没有解决方案。

上述“问题”仅出现在从 API Level 19 (KITKAT) 开始的 Android 版本中,因为它们改变了行为。正确地说,这不是问题,它按预期工作。请参阅 Android 员工 ( Android-Issue ) 的评论。


ViewTreeObserver.OnGlobalLayoutListener因此,我开始挖掘 Android 源代码,并通过使用并在键盘显示/或隐藏时做出反应来得出以下解决方案。如果显示键盘,我将填充添加到容器视图的底部,然后将模拟相同的adjustResize操作。


解决方案

为了简化使用,我将整个东西包装在一个简单的 KeyboardUtil 帮助器类中。

/**
 * Created by mikepenz on 14.03.15.
 * This class implements a hack to change the layout padding on bottom if the keyboard is shown
 * to allow long lists with editTextViews
 * Basic idea for this solution found here: http://stackoverflow.com/a/9108219/325479
 */
public class KeyboardUtil {
    private View decorView;
    private View contentView;

    public KeyboardUtil(Activity act, View contentView) {
        this.decorView = act.getWindow().getDecorView();
        this.contentView = contentView;

        //only required on newer android versions. it was working on API level 19 (Build.VERSION_CODES.KITKAT)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            decorView.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener);
        }
    }

    public void enable() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            decorView.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener);
        }
    }

    public void disable() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            decorView.getViewTreeObserver().removeOnGlobalLayoutListener(onGlobalLayoutListener);
        }
    }


    //a small helper to allow showing the editText focus
    ViewTreeObserver.OnGlobalLayoutListener onGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            Rect r = new Rect();
            //r will be populated with the coordinates of your view that area still visible.
            decorView.getWindowVisibleDisplayFrame(r);

            //get screen height and calculate the difference with the useable area from the r
            int height = decorView.getContext().getResources().getDisplayMetrics().heightPixels;
            int diff = height - r.bottom;

            //if it could be a keyboard add the padding to the view
            if (diff != 0) {
                // if the use-able screen height differs from the total screen height we assume that it shows a keyboard now
                //check if the padding is 0 (if yes set the padding for the keyboard)
                if (contentView.getPaddingBottom() != diff) {
                    //set the padding of the contentView for the keyboard
                    contentView.setPadding(0, 0, 0, diff);
                }
            } else {
                //check if the padding is != 0 (if yes reset the padding)
                if (contentView.getPaddingBottom() != 0) {
                    //reset the padding of the contentView
                    contentView.setPadding(0, 0, 0, 0);
                }
            }
        }
    };


    /**
     * Helper to hide the keyboard
     *
     * @param act
     */
    public static void hideKeyboard(Activity act) {
        if (act != null && act.getCurrentFocus() != null) {
            InputMethodManager inputMethodManager = (InputMethodManager) act.getSystemService(Activity.INPUT_METHOD_SERVICE);
            inputMethodManager.hideSoftInputFromWindow(act.getCurrentFocus().getWindowToken(), 0);
        }
    }
}

然后,您可以通过执行以下操作在您的活动或片段中使用它:

//initialize the KeyboardUtil (you can do this global)
KeyboardUtil keyboardUtil = new KeyboardUtil(activity, getContent().getChildAt(0));

//enable it
keyboardUtil.enable();

//disable it
keyboardUtil.disable();

整个 util 类在上述库MaterialDrawer中使用,可以在这里找到KeyboardUtil。这将始终包含最新版本。(如果有改进)

于 2015-05-03T20:40:22.787 回答
2

似乎问题出在 FrameLayout 上,因为它的行为方式是,每个孩子都占据该框架的可见空间,因此无需调整大小以适合孩子。尝试使用相对布局。它应该工作。

于 2011-12-06T10:29:22.983 回答
1

在没有使用 aScrollView作为我的父母的情况下,我只是将其添加android:fitsSystemWindows="true"到了我的父视图(这是 a RelativeLayout)和adjustResize活动的清单中,并且它起作用了。

于 2016-10-22T20:56:45.710 回答
0

尝试把你LinearLayoutScrollView,这对我有用一次..

于 2011-12-06T10:36:34.580 回答
0

我不得不设置

<item name="android:windowFullscreen">false</item> 

尽管如此,我从未将其设置为 true 并且应用程序实际上不是全屏的。

于 2017-09-13T14:09:02.197 回答
0

我不知道为什么,但是如果您<item name="android:windowTranslucentNavigation">true</item>的主题中有,请将其更改为false. 它将开始工作。真的很奇怪。

于 2018-06-15T18:18:54.613 回答
-1

正如原始海报在将全屏标志分配给活动时发现的那样, android:windowFullscreen 属性将不起作用,因此当软键盘可见且无法滚动时,您的窗口将不会调整大小。

当软键盘可见时,只需删除全屏标志而不使用全屏主题将允许滚动。

于 2013-01-16T20:43:38.037 回答
-3

确保您设置windowTranslucentStatusfalse您的样式。

于 2016-02-25T12:43:17.200 回答