Android 安卓-显示键盘上方的对话片段

Android 安卓-显示键盘上方的对话片段,android,android-softkeyboard,bottom-sheet,Android,Android Softkeyboard,Bottom Sheet,我试图显示一个BottomSheetDialogFragment,其中包含一些EditText字段,供用户输入信息。我想直接在键盘上方显示它,但它一直在掩盖内容 这就是当我打开BottomSheetDialogFragment时发生的情况,您可以看到它正在选择卡号编辑文本,但覆盖了其他内容 理想情况下,这就是我要寻找的,您可以看到editText,以及视图的填充 我已经尝试了很多围绕windowSoftInputMode的解决方案,但似乎都不起作用。对于父级活动和实际的对话片段,我已将其设置

我试图显示一个
BottomSheetDialogFragment
,其中包含一些
EditText
字段,供用户输入信息。我想直接在键盘上方显示它,但它一直在掩盖内容

这就是当我打开
BottomSheetDialogFragment
时发生的情况,您可以看到它正在选择
卡号
编辑文本
,但覆盖了其他内容

理想情况下,这就是我要寻找的,您可以看到
editText
,以及视图的填充

我已经尝试了很多围绕
windowSoftInputMode
的解决方案,但似乎都不起作用。对于父级
活动
和实际的
对话片段
,我已将其设置为
adjustResize


dialog.window.setSoftInputMode(WindowManager.LayoutParams.SOFT\u INPUT\u ADJUST\u RESIZE)

我还尝试修改我的布局,将其从
FrameLayout
更改为
ScrollView
CoordinatorLayout
,以查看这是否对布局的位置有任何影响,但似乎没有任何效果


如果有人知道如何做到这一点,我们将不胜感激。以下步骤可能有助于解决您的问题

首先在xml文件中的EditText上添加以下行

android:imeOptions="actionSend|flagNoEnterAction"
例如:

<EditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:inputType="number"
    android:hint="Card number"
    android:imeOptions="actionSend|flagNoEnterAction"/>
<activity android:name=".stack.MainActivity"
    android:windowSoftInputMode="stateVisible|adjustResize">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
例如:

<EditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:inputType="number"
    android:hint="Card number"
    android:imeOptions="actionSend|flagNoEnterAction"/>
<activity android:name=".stack.MainActivity"
    android:windowSoftInputMode="stateVisible|adjustResize">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

Android操作系统本身不支持在虚拟键盘上添加填充,但有一些黑客方法可以实现

一种方法是收听edittext的焦点,并将ScrollView按如下方式滚动:

edittext.setOnFocusChangeListener(new OnFocusChangeListener() {

    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (hasFocus)
             scrollView.scrollBy(0, 100);

    });
正如我所说的,这种方式很老套,不推荐使用


另一种方法(这取决于您的布局,如果您让它工作起来,效果会更好)是在AndroidManifest.xml中将活动的
WindowsofInputMode
设置为
adjustPan
adjustResize
(取决于您的布局)。

尝试下面的对话片段:

import android.graphics.Rect; 
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.BottomSheetBehavior;
import android.support.design.widget.BottomSheetDialog;
import android.support.design.widget.BottomSheetDialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;

public class TestBottomSheetDialog extends BottomSheetDialogFragment {

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View fragmentView = LayoutInflater.from(getContext()).inflate(R.layout.fragment_bottom_sheet, container, false);
        if (getDialog().getWindow() != null) {
           getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
        }
        if (getActivity() != null) {
            View decorView = getActivity().getWindow().getDecorView();
            decorView.getViewTreeObserver().addOnGlobalLayoutListener(() -> {
                Rect displayFrame = new Rect();
                decorView.getWindowVisibleDisplayFrame(displayFrame);
                int height = decorView.getContext().getResources().getDisplayMetrics().heightPixels;
                int heightDifference = height - displayFrame.bottom;
                if (heightDifference != 0) {
                    if (fragmentView.getPaddingBottom() != heightDifference) {
                        fragmentView.setPadding(0, 0, 0, heightDifference);
                    }
                } else {
                    if (fragmentView.getPaddingBottom() != 0) {
                        fragmentView.setPadding(0, 0, 0, 0);
                    }
                }
            });
        }
        getDialog().setOnShowListener(dialog -> {
            BottomSheetDialog d = (BottomSheetDialog) dialog;
            View bottomSheetInternal = d.findViewById(android.support.design.R.id.design_bottom_sheet);
            if (bottomSheetInternal == null) return;
             BottomSheetBehavior.from(bottomSheetInternal).setState(BottomSheetBehavior.STATE_EXPANDED);
        });
        return fragmentView;
    }
}

我不得不放大版面高度。来自的编程方法没有帮助,所以我只是更改了布局

<android.support.constraint.ConstraintLayout
    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:layout_width="match_parent"
    android:layout_height="match_parent"
    >

    <View
        android:id="@+id/top_space"
        android:layout_width="match_parent"
        android:layout_height="10dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        />

    <!-- Other views -->

    <View
        android:id="@+id/bottom_space"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/button"
        app:layout_constraintVertical_weight="1"
        />

</android.support.constraint.ConstraintLayout>

我终于在键盘打开时更改了对话框的高度,并在键盘关闭时将其调整为正常大小

键盘可视性事件库:

支持2.0.0的最小SDK版本为14

并在键盘打开时将对话框高度设置为80%:

    /**
     * Changes size of dialog based on keyboard visibility state
     */
    private fun setDialogHeight(expanded: Boolean) {
        val dialog = dialog as BottomSheetDialog?
        val bottomSheet =
            dialog!!.findViewById<View>(com.google.android.material.R.id.design_bottom_sheet) as FrameLayout?
        val behavior = BottomSheetBehavior.from(bottomSheet!!)

        val displayMetrics = activity!!.resources.displayMetrics

        val width = displayMetrics.widthPixels
        val height = displayMetrics.heightPixels

        val maxHeight = (height * 0.88).toInt()

        behavior.peekHeight = if (expanded) maxHeight else -1
    }
/**
*根据键盘可见性状态更改对话框的大小
*/
private fun setDialogHeight(扩展:布尔值){
val dialog=对话框是否为BottomSheetDialog?
val底板=
对话框!!.findViewById(com.google.android.material.R.id.design\u bottom\u sheet)作为框架布局?
val behavior=BottomSheetBehavior.from(bottomSheet!!)
val displayMetrics=活动!!.resources.displayMetrics
val width=displayMetrics.widthPixels
val高度=displayMetrics.heightPixels
val maxHeight=(高度*0.88).toInt()
behavior.peekHeight=如果(扩展)maxHeight else-1
}

可能是迟来的答案,但可能会有所帮助

我没有别的办法。但这一解决方案正在发挥作用

内部样式:

<style>  // main theme
    <item name="bottomSheetDialogTheme">@style/BottomSheetDialogTheme</item>
    ........ // rest of the code
</style>

<style name="BottomSheetDialogTheme" parent="Theme.Design.Light.BottomSheetDialog">
    <item name="bottomSheetStyle">@style/AppModalStyle</item>
    <item name="android:windowIsFloating">false</item>
    <item name="android:windowSoftInputMode">adjustResize</item>
    <item name="android:statusBarColor">@android:color/transparent</item> 
</style>
嵌套滚动视图中的换行布局

<androidx.core.widget.NestedScrollView
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

     <--Rest of the layout-->
</androidx.core.widget.NestedScrollView>

在某些设备上,这种解决方案是不够的。将此添加到代码中完全解决了我的问题

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    dialog?.setOnShowListener {
        val dialog = it as BottomSheetDialog
        val bottomSheet = dialog.findViewById<View>(R.id.design_bottom_sheet)
        bottomSheet?.let { sheet ->
            dialog.behavior.state = BottomSheetBehavior.STATE_EXPANDED
            sheet.parent.parent.requestLayout()
        }
    }
}
覆盖已创建的视图(视图:视图,savedInstanceState:Bundle?){
super.onViewCreated(视图,savedInstanceState)
对话框?.setOnShowListener{
val dialog=它作为BottomSheetDialog
val bottomSheet=dialog.findviewbyd(R.id.design\u bottom\u sheet)
底页?让{页->
dialog.behavior.state=BottomSheetBehavior.state\u已展开
sheet.parent.parent.requestLayout()文件
}
}
}

Post your layout添加
actionSend
imeOptions
与此问题无关。如果显示布局,可能会更好。可能与类似,但我没有检查。为什么需要BottomSheetDialogTheme?您不在代码中使用。您需要在主样式或代码中添加它。请看更新的答案。我对此表示怀疑,但这确实很有效。我发现使用
NestedScrollView
,或者添加
onViewCreated
代码片段,不需要更改布局-仅样式对我来说是不够的,NestedScrollView很麻烦,因为里面有回收器视图。保持布局与以前一样,只是改变样式以及通过编程处理BottomSheetDialogFragment,效果非常好!!谢谢
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    dialog?.setOnShowListener {
        val dialog = it as BottomSheetDialog
        val bottomSheet = dialog.findViewById<View>(R.id.design_bottom_sheet)
        bottomSheet?.let { sheet ->
            dialog.behavior.state = BottomSheetBehavior.STATE_EXPANDED
            sheet.parent.parent.requestLayout()
        }
    }
}