如何防止自定义 DialogFragment 在显示时隐藏键盘
How to prevent custom DialogFragment from hiding keyboard when being shown
有两种方法可以通过 DialogFragment
创建自定义对话框。
- 使用
AlertDialog.Builder
覆盖 onCreateDialog
和 return 对话框。
- 覆盖
onCreateView
.
我们注意到,如果我们覆盖onCreateDialog
,之前显示的软键盘将不会被隐藏。
但是,如果我们覆盖onCreateView
,之前显示的软键盘将被隐藏。
onCreateDialog 不会隐藏软键盘
onCreateView 会隐藏软键盘
隐藏软键盘不是我们想要的行为。我们希望软键盘保持原样。
但是,由于 ViewPager in DialogFragment - IllegalStateException: Fragment does not have a view 提到的限制,我们无法使用 onCreateDialog
方式。简而言之,如果您需要 ViewPager
在对话框中正常工作,则无法使用 onCreateDialog
.
实现自定义对话框
如果我们使用 onCreateView
,除了 "not hiding soft keyboard".
,我们可以实现所有想要的
你知道为什么覆盖 onCreateView
来创建自定义对话框,会隐藏键盘吗?我们怎样才能防止这种行为?
代码
我的对话风格是:
<style name="CustomDialog" parent="@style/Theme.AppCompat.Light.Dialog">
<item name="android:windowNoTitle">false</item>
</style>
ColorDialogFragment.java:
public class ColorDialogFragment extends DialogFragment {
private TabLayout tabLayout;
private ViewPager viewPager;
private ColorFragmentPagerAdapter colorFragmentPagerAdapter;
public static ColorDialogFragment newInstance() {
ColorDialogFragment colorDialogFragment = new ColorDialogFragment();
// We provide custom style, because we need title.
colorDialogFragment.setStyle(DialogFragment.STYLE_NORMAL, R.style.CustomDialog);
return colorDialogFragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public void onResume() {
super.onResume();
getDialog().getWindow().setLayout(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
}
private View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container) {
View view = inflater.inflate(R.layout.color_dialog_fragment, container, false);
this.tabLayout = view.findViewById(R.id.tab_layout);
this.viewPager = view.findViewById(R.id.view_pager);
this.colorFragmentPagerAdapter = new ColorFragmentPagerAdapter(this.getChildFragmentManager());
this.viewPager.setAdapter(this.colorFragmentPagerAdapter);
this.tabLayout.setupWithViewPager(this.viewPager);
return view;
}
// We overwrite onCreateView because ViewPager in DialogFragment, can hardly play well with
// onCreateDialog + AlertDialog.Builder.
//
//
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return onCreateView(inflater, container);
}
// We overwrite onCreateDialog, because we need title.
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
dialog.setTitle(R.string.select_a_color);
return dialog;
}
}
经过一天的实验,我找到了解决办法!
同时覆盖 onCreateDialog
和 onCreateView
。将在 onCreateDialog
处创建的视图存储在成员变量中,并让 onCreateView
return 该成员变量。
参考:
这是完整的代码。
public class ColorDialogFragment extends DialogFragment {
private View view;
private TabLayout tabLayout;
private ViewPager viewPager;
private ColorFragmentPagerAdapter colorFragmentPagerAdapter;
public static ColorDialogFragment newInstance() {
ColorDialogFragment colorDialogFragment = new ColorDialogFragment();
return colorDialogFragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public void onResume() {
super.onResume();
getDialog().getWindow().setLayout(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
// TODO: Read from WeNoteOptions.
final int position = 0;
this.viewPager.setCurrentItem(position);
updateButtonVisibility(position);
}
private View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container) {
View view = inflater.inflate(R.layout.color_dialog_fragment, container, false);
this.tabLayout = view.findViewById(R.id.tab_layout);
this.viewPager = view.findViewById(R.id.view_pager);
this.colorFragmentPagerAdapter = new ColorFragmentPagerAdapter(this.getChildFragmentManager());
this.viewPager.setAdapter(this.colorFragmentPagerAdapter);
this.tabLayout.setupWithViewPager(this.viewPager);
this.viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
updateButtonVisibility(position);
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
return view;
}
private void updateButtonVisibility(int position) {
if (position == 1) {
((AlertDialog)getDialog()).getButton(DialogInterface.BUTTON_POSITIVE).setVisibility(View.VISIBLE);
} else {
((AlertDialog)getDialog()).getButton(DialogInterface.BUTTON_POSITIVE).setVisibility(View.INVISIBLE);
}
}
//
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return this.view;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
LayoutInflater layoutInflater = getActivity().getLayoutInflater();
this.view = onCreateView(layoutInflater, null);
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity())
.setTitle(R.string.select_a_color)
.setView(this.view)
.setPositiveButton(R.string.select_color, (dialogInterface, i) -> {
});
return alertDialogBuilder.create();
}
}
有两种方法可以通过 DialogFragment
创建自定义对话框。
- 使用
AlertDialog.Builder
覆盖onCreateDialog
和 return 对话框。 - 覆盖
onCreateView
.
我们注意到,如果我们覆盖onCreateDialog
,之前显示的软键盘将不会被隐藏。
但是,如果我们覆盖onCreateView
,之前显示的软键盘将被隐藏。
onCreateDialog 不会隐藏软键盘
onCreateView 会隐藏软键盘
隐藏软键盘不是我们想要的行为。我们希望软键盘保持原样。
但是,由于 ViewPager in DialogFragment - IllegalStateException: Fragment does not have a view 提到的限制,我们无法使用 onCreateDialog
方式。简而言之,如果您需要 ViewPager
在对话框中正常工作,则无法使用 onCreateDialog
.
如果我们使用 onCreateView
,除了 "not hiding soft keyboard".
你知道为什么覆盖 onCreateView
来创建自定义对话框,会隐藏键盘吗?我们怎样才能防止这种行为?
代码
我的对话风格是:
<style name="CustomDialog" parent="@style/Theme.AppCompat.Light.Dialog">
<item name="android:windowNoTitle">false</item>
</style>
ColorDialogFragment.java:
public class ColorDialogFragment extends DialogFragment {
private TabLayout tabLayout;
private ViewPager viewPager;
private ColorFragmentPagerAdapter colorFragmentPagerAdapter;
public static ColorDialogFragment newInstance() {
ColorDialogFragment colorDialogFragment = new ColorDialogFragment();
// We provide custom style, because we need title.
colorDialogFragment.setStyle(DialogFragment.STYLE_NORMAL, R.style.CustomDialog);
return colorDialogFragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public void onResume() {
super.onResume();
getDialog().getWindow().setLayout(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
}
private View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container) {
View view = inflater.inflate(R.layout.color_dialog_fragment, container, false);
this.tabLayout = view.findViewById(R.id.tab_layout);
this.viewPager = view.findViewById(R.id.view_pager);
this.colorFragmentPagerAdapter = new ColorFragmentPagerAdapter(this.getChildFragmentManager());
this.viewPager.setAdapter(this.colorFragmentPagerAdapter);
this.tabLayout.setupWithViewPager(this.viewPager);
return view;
}
// We overwrite onCreateView because ViewPager in DialogFragment, can hardly play well with
// onCreateDialog + AlertDialog.Builder.
//
//
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return onCreateView(inflater, container);
}
// We overwrite onCreateDialog, because we need title.
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
dialog.setTitle(R.string.select_a_color);
return dialog;
}
}
经过一天的实验,我找到了解决办法!
同时覆盖 onCreateDialog
和 onCreateView
。将在 onCreateDialog
处创建的视图存储在成员变量中,并让 onCreateView
return 该成员变量。
参考:
这是完整的代码。
public class ColorDialogFragment extends DialogFragment {
private View view;
private TabLayout tabLayout;
private ViewPager viewPager;
private ColorFragmentPagerAdapter colorFragmentPagerAdapter;
public static ColorDialogFragment newInstance() {
ColorDialogFragment colorDialogFragment = new ColorDialogFragment();
return colorDialogFragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public void onResume() {
super.onResume();
getDialog().getWindow().setLayout(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
// TODO: Read from WeNoteOptions.
final int position = 0;
this.viewPager.setCurrentItem(position);
updateButtonVisibility(position);
}
private View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container) {
View view = inflater.inflate(R.layout.color_dialog_fragment, container, false);
this.tabLayout = view.findViewById(R.id.tab_layout);
this.viewPager = view.findViewById(R.id.view_pager);
this.colorFragmentPagerAdapter = new ColorFragmentPagerAdapter(this.getChildFragmentManager());
this.viewPager.setAdapter(this.colorFragmentPagerAdapter);
this.tabLayout.setupWithViewPager(this.viewPager);
this.viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
updateButtonVisibility(position);
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
return view;
}
private void updateButtonVisibility(int position) {
if (position == 1) {
((AlertDialog)getDialog()).getButton(DialogInterface.BUTTON_POSITIVE).setVisibility(View.VISIBLE);
} else {
((AlertDialog)getDialog()).getButton(DialogInterface.BUTTON_POSITIVE).setVisibility(View.INVISIBLE);
}
}
//
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return this.view;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
LayoutInflater layoutInflater = getActivity().getLayoutInflater();
this.view = onCreateView(layoutInflater, null);
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity())
.setTitle(R.string.select_a_color)
.setView(this.view)
.setPositiveButton(R.string.select_color, (dialogInterface, i) -> {
});
return alertDialogBuilder.create();
}
}