在键盘上方使用 EditText 显示整个底部 sheet
Show entire bottom sheet with EditText above Keyboard
我正在实现一个 UI,其中底部 sheet 将出现在键盘上方,并带有一个 EditText 供用户输入值。问题是 View 被键盘部分重叠,覆盖了底部 sheet.
这是底部 Sheet,没有键盘。
这是显示键盘的底部 Sheet。
确保显示整个底部 Sheet 的最佳方法是什么?
谢谢。
A BottomSheetDialog
可以对此有所帮助。它将打开 Softkeyboard open with focus on edit text.But 用户仍然可以关闭 Softkeyboard 并且对话框将重置为底部。再次聚焦将使对话框出现在软键盘的顶部。
public void showDialog() {
final BottomSheetDialog dialog=new BottomSheetDialog(this);
dialog.setContentView(R.layout.item_dialog);
dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
dialog.show();
}
您可以使 BottomSheetDialog 在键盘上展开。但是为此你需要在 SoftKeyboard Open 之后调用它。展开代码是 .
BottomSheetDialog d = (BottomSheetDialog) dialog;
FrameLayout bottomSheet = (FrameLayout) d.findViewById(android.support.design.R.id.design_bottom_sheet);
BottomSheetBehavior.from(bottomSheet).setState(BottomSheetBehavior.STATE_EXPANDED);
我已经在 DialogInterface.OnShowListener()
上对其进行了测试,但它不起作用。用它测试 1 秒延迟它的工作。但延迟不是解决方案。您需要弄清楚应该在哪个操作上展开对话框。
final BottomSheetDialog dialog=new BottomSheetDialog(this);
dialog.setContentView(R.layout.item_dialog);
dialog.getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE|
WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
FrameLayout bottomSheet = (FrameLayout) dialog.findViewById(android.support.design.R.id.design_bottom_sheet);
BottomSheetBehavior.from(bottomSheet).setState(BottomSheetBehavior.STATE_EXPANDED);
}
},2000);
dialog.show();
为此,我发现 AlertDialog
效果最好。虽然它没有与屏幕的底部或侧面齐平,但看起来还是不错的。
首先,使用您的视图创建 AlertDialog
。
val view = LayoutInflater.from(context).inflate(R.layout.alert, null)
dialog = AlertDialog.Builder(context)
.setView(view)
.create()
接下来,设置重力。
dialog.window.attributes.gravity = Gravity.BOTTOM
最后,展示一下。
dialog.show()
您还可以使用 onDismissListener
.
将键盘绑定到对话框中
显示AlertDialog
后,我强行按下键盘。
调用此方法,传入您的EditText
。
fun showKeyboard(view: View?) {
if (view == null) return;
val imm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
}
并在 onDismissListener
内解雇。
private fun hideKeyboard() {
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0)
}
dialog = new BottomSheetDialog(getContext(), R.style.BottomSheetDialog);
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialog) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
BottomSheetDialog d = (BottomSheetDialog) dialog;
FrameLayout bottomSheet = d.findViewById(R.id.design_bottom_sheet);
BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
},0);
}
});
此代码在 Fragment 的 onCreateView 方法中运行良好(感谢 ADM)
只是重新发布@jblejder 这个问题 因为它对我有用,让其他人更容易找到:
我发现最方便的更改方式是创建样式:
<style name="DialogStyle" parent="Theme.Design.Light.BottomSheetDialog">
<item name="android:windowIsFloating">false</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:windowSoftInputMode">adjustResize</item>
</style>
并在 BottomSheetDialogFragment 的 onCreate 方法中进行设置:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setStyle(DialogFragment.STYLE_NORMAL, R.style.DialogStyle)
}
这是它在我的设备上的样子:
====更新====
正如评论中多次提到的那样,您可能还需要将 BottomSheetDialog 的状态设置为 STATE_EXPANDED,就像下面 Nordknight 的回答一样
dialog = new BottomSheetDialog(getContext(), R.style.BottomSheetDialog);
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialog) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
BottomSheetDialog d = (BottomSheetDialog) dialog;
FrameLayout bottomSheet = d.findViewById(R.id.design_bottom_sheet);
BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
},0);
}
});
我的回答可能对仍在寻找解决方案的人有用。如果键盘覆盖 BottomSheetDialogFragment 中的编辑文本,则在 setupDialog()
方法中创建 class KeyboardUtil 实例并传递您的根视图。
@Override
public void setupDialog(final Dialog dialog, int style) {
super.setupDialog(dialog, style);
View view = View.inflate(getActivity(), R.layout.reopen_dialog_layout, null);
new KeyboardUtil(getActivity(), view);
}
新建一个class
public class KeyboardUtil {
private View decorView;
private View contentView;
//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);
}
}
}
};
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
if (Build.VERSION.SDK_INT >= 19) {
decorView.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener);
}
}
/**
* 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);
}
}
public void enable() {
if (Build.VERSION.SDK_INT >= 19) {
decorView.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener);
}
}
public void disable() {
if (Build.VERSION.SDK_INT >= 19) {
decorView.getViewTreeObserver().removeOnGlobalLayoutListener(onGlobalLayoutListener);
}
}
}
这可能是一个多余的答案。虽然只是指出问题。
如果您使用 BottomSheetDialogFragment
,唯一的方法是将属性 android:windowIsFloating 设为 true。这将使整个 window 处于试图将 space 置于其后的任何事物之上。
<style name="BottomSheetDialogThemeNoFloating" parent="Theme.Design.Light.BottomSheetDialog">
<item name="android:windowIsFloating">false</item>
<item name="android:windowSoftInputMode">adjustResize|stateVisible</item>
</style>
然后在对话框的 onCreate()
中设置此样式。
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// set the window no floating style
setStyle(DialogFragment.STYLE_NORMAL, R.style.AppRoundedBottomSheetDialogThemeNoFloating)
}
这对于那些经常使用底部工作表并且可能想要处理 EditText
和软键盘相互重叠的人来说非常方便。
注意:mikepenz 的 class KeyboardUtil
有一个问题,在某些手机上,尽管对提供的整个内容视图进行了底部填充,但带有输入字段的内容视图会自动推到键盘上方.
这个有效
BottomSheetDialog dialog = new BottomSheetDialog(this, R.style.DialogStyle);
View sheetView = getLayoutInflater().inflate(R.layout.dialog_remark, null);
Objects.requireNonNull(dialog.getWindow())
.setSoftInputMode(SOFT_INPUT_STATE_VISIBLE);
dialog.setContentView(sheetView);
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialog) {
BottomSheetDialog d = (BottomSheetDialog) dialog;
View bottomSheetInternal = d.findViewById(com.google.android.material.R.id.design_bottom_sheet);
BottomSheetBehavior.from(bottomSheetInternal).setState(BottomSheetBehavior.STATE_EXPANDED);
}
});
dialog.show();
将此样式添加到您的 styles.xml
<style name="DialogStyle" parent="Theme.Design.Light.BottomSheetDialog">
<item name="android:windowIsFloating">false</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:windowSoftInputMode">adjustPan</item>
</style>
像这样添加布局
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:id="@+id/scrollview"
android:layout_height="match_parent">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="8dp"
android:fontFamily="@font/montserratmedium"
android:text="Add Remarks"
android:textColor="@android:color/black"
android:textSize="18sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="24dp"
android:fontFamily="@font/montserratmedium"
android:text="Branch"
android:textColor="#8B8B8B"
android:textSize="18sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:fontFamily="@font/montserratmedium"
android:text="BLR-CO-SINDHUBHAVAN-384"
android:textColor="@android:color/black"
android:textSize="18sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="24dp"
android:fontFamily="@font/montserratmedium"
android:text="Enter Remarks"
android:textColor="#8B8B8B"
android:textSize="18sp" />
<EditText
android:id="@+id/input_remark"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_marginTop="8dp"
android:background="@drawable/remark_inputbg"
android:gravity="start"
android:inputType="textMultiLine"
android:lines="5" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/action"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="2">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:layout_weight="1"
android:background="@drawable/reset_bg"
android:padding="8dp"
android:text="CANCEL" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:layout_weight="1"
android:background="#4F4DBB"
android:padding="8dp"
android:text="CANCEL"
android:textColor="@android:color/white" />
</LinearLayout>
</RelativeLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
</ScrollView>
一些答案似乎比其他答案更有效,但在使用新的 material 设计组件而不是旧的支持库同时还使用 kotlin
时需要修改
希望这会对某人有所帮助。
BottomSheetDialog(this, R.style.DialogStyle).apply {
setContentView(layoutInflater.inflate(R.layout.bottom_sheet, null))
window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
findViewById<EditText>(R.id.time_et)?.requestFocus()
show()
}
layout/bottom_sheet.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView 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="wrap_content"
android:background="#ffffff"
android:padding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<View
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="5"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Time"
android:textColor="#000000"
android:textSize="24sp"
android:textStyle="bold" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:orientation="horizontal">
<EditText
android:id="@+id/time_et"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="numberSigned"
android:minWidth="50dp"
android:text="15" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:text="min" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:background="#000"
android:text="Save"
android:textColor="#fff" />
</LinearLayout>
</ScrollView>
styes.xml(为 v-21 拆分以使用 statusBarColor)
<style name="DialogStyle" parent="Theme.MaterialComponents.Light.BottomSheetDialog">
<item name="android:windowIsFloating">false</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:windowSoftInputMode">adjustResize</item>
</style>
private fun enterMobileNumberPopUp() {
val dialog = BottomSheetDialog(this,R.style.DialogStyle)
val view = layoutInflater.inflate(R.layout.layout_otp, null)
dialog.setContentView(view)
dialog.behavior.state = BottomSheetBehavior.STATE_EXPANDED
dialog.show()}
- 这是处理底部 SHEET 对话框最简单也是最好的方法
您可以在方法
中调用它
<style name="DialogStyle" parent="Theme.Design.Light.BottomSheetDialog">
<item name="android:windowIsFloating">false</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:windowSoftInputMode">adjustResize</item>
风格参考
为那些使用 Material 组件主题的人更新的答案,以及一个改进的答案,无需在每个对话框的 onCreate()
.
中添加任何内容
在您的主 AppTheme 样式中,您可以添加属性 bottomSheetDialogTheme
以将样式应用于 BottomSheetDialogFragments 的 all:
<style name="AppTheme" parent="Theme.MaterialComponents.Light.DarkActionBar">
<item name="colorPrimary">@color/primary</item>
<item name="colorPrimaryDark">@color/primary_dark</item>
<item name="colorAccent">@color/accent</item>
<item name="bottomSheetDialogTheme">@style/BottomSheetDialogStyle</item>
</style>
因此,有了上面的内容,无需向 BottomSheetDialogFragment 代码添加任何内容。
然后,如前所述,您的对话框样式,注意也要将样式与相同的 Material 组件库相匹配(否则您会得到一些看起来很奇怪的按钮、编辑文本等):
<style name="BottomSheetDialogStyle" parent="Theme.MaterialComponents.Light.BottomSheetDialog">
<item name="android:windowIsFloating">false</item>
<item name="android:windowSoftInputMode">adjustResize</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="colorPrimary">@color/primary</item>
<item name="colorPrimaryDark">@color/primary_dark</item>
<item name="colorAccent">@color/accent</item>
</style>
请注意,我在此处添加了我的应用主题颜色;由于您不能在 Android 样式中进行多重继承,因此您可能希望在此处定义这些颜色,以便任何按钮和重音与应用程序的其余部分保持一致。
Kotlin,+viewBinding,+通过使用已接受答案的对话框样式
val bottomSheet = BottomSheetDialog(this, R.style.BottomSheetDialogStyle)
val binding = [YourSheetBinding].inflate(LayoutInflater.from(YourActivity.this))
bottomSheet.setContentView(binding.root)
bottomSheet.behavior.state = BottomSheetBehavior.STATE_EXPANDED
bottomSheet.show()
参见:
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val dialog = super.onCreateDialog(savedInstanceState) as BottomSheetDialog
dialog.behavior.state = BottomSheetBehavior.STATE_EXPANDED
return dialog
}
但如果布局不够高,您可以使用 代替。它将几乎全屏打开 BottomSheetDialog:
<style name="BottomSheetDialogTheme" parent="Theme.MaterialComponents.Light.BottomSheetDialog">
<item name="android:windowIsFloating">false</item>
<item name="android:windowSoftInputMode">adjustResize|stateVisible</item>
</style>
bottomSheetDialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
一定会成功的。
摆弄 BottomSheetDialogFragment 真的不值得。所以我只是将其更改为简单的 DialogFragment
并将其重力设置为底部:
window.setGravity(Gravity.BOTTOM);
工作得很好。
试试这个解决方案:
我使用 NestedScrollView 作为根布局。
我正在实现一个 UI,其中底部 sheet 将出现在键盘上方,并带有一个 EditText 供用户输入值。问题是 View 被键盘部分重叠,覆盖了底部 sheet.
这是底部 Sheet,没有键盘。
这是显示键盘的底部 Sheet。
确保显示整个底部 Sheet 的最佳方法是什么?
谢谢。
A BottomSheetDialog
可以对此有所帮助。它将打开 Softkeyboard open with focus on edit text.But 用户仍然可以关闭 Softkeyboard 并且对话框将重置为底部。再次聚焦将使对话框出现在软键盘的顶部。
public void showDialog() {
final BottomSheetDialog dialog=new BottomSheetDialog(this);
dialog.setContentView(R.layout.item_dialog);
dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
dialog.show();
}
您可以使 BottomSheetDialog 在键盘上展开。但是为此你需要在 SoftKeyboard Open 之后调用它。展开代码是 .
BottomSheetDialog d = (BottomSheetDialog) dialog;
FrameLayout bottomSheet = (FrameLayout) d.findViewById(android.support.design.R.id.design_bottom_sheet);
BottomSheetBehavior.from(bottomSheet).setState(BottomSheetBehavior.STATE_EXPANDED);
我已经在 DialogInterface.OnShowListener()
上对其进行了测试,但它不起作用。用它测试 1 秒延迟它的工作。但延迟不是解决方案。您需要弄清楚应该在哪个操作上展开对话框。
final BottomSheetDialog dialog=new BottomSheetDialog(this);
dialog.setContentView(R.layout.item_dialog);
dialog.getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE|
WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
FrameLayout bottomSheet = (FrameLayout) dialog.findViewById(android.support.design.R.id.design_bottom_sheet);
BottomSheetBehavior.from(bottomSheet).setState(BottomSheetBehavior.STATE_EXPANDED);
}
},2000);
dialog.show();
为此,我发现 AlertDialog
效果最好。虽然它没有与屏幕的底部或侧面齐平,但看起来还是不错的。
首先,使用您的视图创建 AlertDialog
。
val view = LayoutInflater.from(context).inflate(R.layout.alert, null)
dialog = AlertDialog.Builder(context)
.setView(view)
.create()
接下来,设置重力。
dialog.window.attributes.gravity = Gravity.BOTTOM
最后,展示一下。
dialog.show()
您还可以使用 onDismissListener
.
显示AlertDialog
后,我强行按下键盘。
调用此方法,传入您的EditText
。
fun showKeyboard(view: View?) {
if (view == null) return;
val imm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
}
并在 onDismissListener
内解雇。
private fun hideKeyboard() {
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0)
}
dialog = new BottomSheetDialog(getContext(), R.style.BottomSheetDialog);
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialog) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
BottomSheetDialog d = (BottomSheetDialog) dialog;
FrameLayout bottomSheet = d.findViewById(R.id.design_bottom_sheet);
BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
},0);
}
});
此代码在 Fragment 的 onCreateView 方法中运行良好(感谢 ADM)
只是重新发布@jblejder 这个问题
我发现最方便的更改方式是创建样式:
<style name="DialogStyle" parent="Theme.Design.Light.BottomSheetDialog">
<item name="android:windowIsFloating">false</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:windowSoftInputMode">adjustResize</item>
</style>
并在 BottomSheetDialogFragment 的 onCreate 方法中进行设置:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setStyle(DialogFragment.STYLE_NORMAL, R.style.DialogStyle)
}
这是它在我的设备上的样子:
====更新====
正如评论中多次提到的那样,您可能还需要将 BottomSheetDialog 的状态设置为 STATE_EXPANDED,就像下面 Nordknight 的回答一样
dialog = new BottomSheetDialog(getContext(), R.style.BottomSheetDialog);
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialog) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
BottomSheetDialog d = (BottomSheetDialog) dialog;
FrameLayout bottomSheet = d.findViewById(R.id.design_bottom_sheet);
BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
},0);
}
});
我的回答可能对仍在寻找解决方案的人有用。如果键盘覆盖 BottomSheetDialogFragment 中的编辑文本,则在 setupDialog()
方法中创建 class KeyboardUtil 实例并传递您的根视图。
@Override
public void setupDialog(final Dialog dialog, int style) {
super.setupDialog(dialog, style);
View view = View.inflate(getActivity(), R.layout.reopen_dialog_layout, null);
new KeyboardUtil(getActivity(), view);
}
新建一个class
public class KeyboardUtil {
private View decorView;
private View contentView;
//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);
}
}
}
};
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
if (Build.VERSION.SDK_INT >= 19) {
decorView.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener);
}
}
/**
* 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);
}
}
public void enable() {
if (Build.VERSION.SDK_INT >= 19) {
decorView.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener);
}
}
public void disable() {
if (Build.VERSION.SDK_INT >= 19) {
decorView.getViewTreeObserver().removeOnGlobalLayoutListener(onGlobalLayoutListener);
}
}
}
这可能是一个多余的答案。虽然只是指出问题。
如果您使用 BottomSheetDialogFragment
,唯一的方法是将属性 android:windowIsFloating 设为 true。这将使整个 window 处于试图将 space 置于其后的任何事物之上。
<style name="BottomSheetDialogThemeNoFloating" parent="Theme.Design.Light.BottomSheetDialog">
<item name="android:windowIsFloating">false</item>
<item name="android:windowSoftInputMode">adjustResize|stateVisible</item>
</style>
然后在对话框的 onCreate()
中设置此样式。
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// set the window no floating style
setStyle(DialogFragment.STYLE_NORMAL, R.style.AppRoundedBottomSheetDialogThemeNoFloating)
}
这对于那些经常使用底部工作表并且可能想要处理 EditText
和软键盘相互重叠的人来说非常方便。
注意:mikepenz 的 class KeyboardUtil
有一个问题,在某些手机上,尽管对提供的整个内容视图进行了底部填充,但带有输入字段的内容视图会自动推到键盘上方.
这个有效
BottomSheetDialog dialog = new BottomSheetDialog(this, R.style.DialogStyle);
View sheetView = getLayoutInflater().inflate(R.layout.dialog_remark, null);
Objects.requireNonNull(dialog.getWindow())
.setSoftInputMode(SOFT_INPUT_STATE_VISIBLE);
dialog.setContentView(sheetView);
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialog) {
BottomSheetDialog d = (BottomSheetDialog) dialog;
View bottomSheetInternal = d.findViewById(com.google.android.material.R.id.design_bottom_sheet);
BottomSheetBehavior.from(bottomSheetInternal).setState(BottomSheetBehavior.STATE_EXPANDED);
}
});
dialog.show();
将此样式添加到您的 styles.xml
<style name="DialogStyle" parent="Theme.Design.Light.BottomSheetDialog">
<item name="android:windowIsFloating">false</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:windowSoftInputMode">adjustPan</item>
</style>
像这样添加布局
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:id="@+id/scrollview"
android:layout_height="match_parent">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="8dp"
android:fontFamily="@font/montserratmedium"
android:text="Add Remarks"
android:textColor="@android:color/black"
android:textSize="18sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="24dp"
android:fontFamily="@font/montserratmedium"
android:text="Branch"
android:textColor="#8B8B8B"
android:textSize="18sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:fontFamily="@font/montserratmedium"
android:text="BLR-CO-SINDHUBHAVAN-384"
android:textColor="@android:color/black"
android:textSize="18sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="24dp"
android:fontFamily="@font/montserratmedium"
android:text="Enter Remarks"
android:textColor="#8B8B8B"
android:textSize="18sp" />
<EditText
android:id="@+id/input_remark"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_marginTop="8dp"
android:background="@drawable/remark_inputbg"
android:gravity="start"
android:inputType="textMultiLine"
android:lines="5" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/action"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="2">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:layout_weight="1"
android:background="@drawable/reset_bg"
android:padding="8dp"
android:text="CANCEL" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:layout_weight="1"
android:background="#4F4DBB"
android:padding="8dp"
android:text="CANCEL"
android:textColor="@android:color/white" />
</LinearLayout>
</RelativeLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
</ScrollView>
一些答案似乎比其他答案更有效,但在使用新的 material 设计组件而不是旧的支持库同时还使用 kotlin
时需要修改希望这会对某人有所帮助。
BottomSheetDialog(this, R.style.DialogStyle).apply {
setContentView(layoutInflater.inflate(R.layout.bottom_sheet, null))
window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
findViewById<EditText>(R.id.time_et)?.requestFocus()
show()
}
layout/bottom_sheet.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView 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="wrap_content"
android:background="#ffffff"
android:padding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<View
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="5"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Time"
android:textColor="#000000"
android:textSize="24sp"
android:textStyle="bold" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:orientation="horizontal">
<EditText
android:id="@+id/time_et"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="numberSigned"
android:minWidth="50dp"
android:text="15" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:text="min" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:background="#000"
android:text="Save"
android:textColor="#fff" />
</LinearLayout>
</ScrollView>
styes.xml(为 v-21 拆分以使用 statusBarColor)
<style name="DialogStyle" parent="Theme.MaterialComponents.Light.BottomSheetDialog">
<item name="android:windowIsFloating">false</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:windowSoftInputMode">adjustResize</item>
</style>
private fun enterMobileNumberPopUp() {
val dialog = BottomSheetDialog(this,R.style.DialogStyle)
val view = layoutInflater.inflate(R.layout.layout_otp, null)
dialog.setContentView(view)
dialog.behavior.state = BottomSheetBehavior.STATE_EXPANDED
dialog.show()}
- 这是处理底部 SHEET 对话框最简单也是最好的方法
您可以在方法
<style name="DialogStyle" parent="Theme.Design.Light.BottomSheetDialog">
<item name="android:windowIsFloating">false</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:windowSoftInputMode">adjustResize</item>
风格参考
为那些使用 Material 组件主题的人更新的答案,以及一个改进的答案,无需在每个对话框的 onCreate()
.
在您的主 AppTheme 样式中,您可以添加属性 bottomSheetDialogTheme
以将样式应用于 BottomSheetDialogFragments 的 all:
<style name="AppTheme" parent="Theme.MaterialComponents.Light.DarkActionBar">
<item name="colorPrimary">@color/primary</item>
<item name="colorPrimaryDark">@color/primary_dark</item>
<item name="colorAccent">@color/accent</item>
<item name="bottomSheetDialogTheme">@style/BottomSheetDialogStyle</item>
</style>
因此,有了上面的内容,无需向 BottomSheetDialogFragment 代码添加任何内容。
然后,如前所述,您的对话框样式,注意也要将样式与相同的 Material 组件库相匹配(否则您会得到一些看起来很奇怪的按钮、编辑文本等):
<style name="BottomSheetDialogStyle" parent="Theme.MaterialComponents.Light.BottomSheetDialog">
<item name="android:windowIsFloating">false</item>
<item name="android:windowSoftInputMode">adjustResize</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="colorPrimary">@color/primary</item>
<item name="colorPrimaryDark">@color/primary_dark</item>
<item name="colorAccent">@color/accent</item>
</style>
请注意,我在此处添加了我的应用主题颜色;由于您不能在 Android 样式中进行多重继承,因此您可能希望在此处定义这些颜色,以便任何按钮和重音与应用程序的其余部分保持一致。
Kotlin,+viewBinding,+通过使用已接受答案的对话框样式
val bottomSheet = BottomSheetDialog(this, R.style.BottomSheetDialogStyle)
val binding = [YourSheetBinding].inflate(LayoutInflater.from(YourActivity.this))
bottomSheet.setContentView(binding.root)
bottomSheet.behavior.state = BottomSheetBehavior.STATE_EXPANDED
bottomSheet.show()
参见
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val dialog = super.onCreateDialog(savedInstanceState) as BottomSheetDialog
dialog.behavior.state = BottomSheetBehavior.STATE_EXPANDED
return dialog
}
但如果布局不够高,您可以使用 代替。它将几乎全屏打开 BottomSheetDialog:
<style name="BottomSheetDialogTheme" parent="Theme.MaterialComponents.Light.BottomSheetDialog">
<item name="android:windowIsFloating">false</item>
<item name="android:windowSoftInputMode">adjustResize|stateVisible</item>
</style>
bottomSheetDialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
一定会成功的。
摆弄 BottomSheetDialogFragment 真的不值得。所以我只是将其更改为简单的 DialogFragment
并将其重力设置为底部:
window.setGravity(Gravity.BOTTOM);
工作得很好。
试试这个解决方案:
我使用 NestedScrollView 作为根布局。