BottomSheetDialog/BottomSheetDialogFragment — 使用哪个以及如何使用?
BottomSheetDialog/BottomSheetDialogFragment — which to use and how?
我正在开发 Material 设计应用程序。我想实现的一个功能是某种投票。当用户单击列表的元素时,持久底部 sheet 对话框应该显示如下:
然后,当用户单击任何按钮时,该对话框应该消失,模态底部 sheet 对话框应该出现,为用户提供有关开始时单击的列表项的更多信息。它看起来像这样:
我找不到任何关于 BottomSheetDialog 和 BottomSheetDialogFragment 的明确解释,以及如何正确使用它们,即使在阅读了一些关于 AppCompat 对话框的信息之后也是如此。所以,我的问题是:
- 它们有什么不同,我应该用哪一个
案例?
- 如何在 activity 中获取关于在对话框中按下了哪个按钮的数据?
- 关于实现代码或使用教程的任何链接?
最后,我找到了解决方案并且它有效。如果我做错了什么,请告诉我。它基本上像 this guide 中的 DialogFragment 一样工作,但我做的有点不同。
1) 它们的区别与DialogFragment和Dialog一样,都是模态的。如果您需要持久对话框,请使用 BottomSheetBehaviour instead(我发现这两个对话框在我的应用程序中都必须是模态的)。
2)我得先用一些代码回答第三个问题,然后再回答第二个就很容易了。
3) 创建一个新的public class
,extends BottomSheetDialogFragment
,我称之为FragmentRandomEventPoll。有两件事必须在这里实现。
覆盖方法 onCreateView
。它与 Activities 中的 onCreate
方法几乎相同,除了它 returns 它应该膨胀的视图:
// We will need it later
private static String headerItem;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_random_event_poll, container, false);
header = (TextView) v.findViewById(R.id.uRnd_fragment_bottom_sheet_poll_header);
skip = (Button) v.findViewById(R.id.uRnd_fragment_bottom_sheet_button_skip);
header.setText(...);
// I implemented View.OnClickListener interface in my class
skip.setOnClickListener(this);
return v;
}
静态方法,您可以将必要的数据传递给它并获取此 class 的新实例(可能我可以只使用常规构造函数,我将不得不用它进行试验多一点)。 URandomEventListItem
是数据模型 class.
public static FragmentRandomEventPoll newInstance(URandomEventListItem item) {
FragmentRandomEventPoll fragment = new FragmentRandomEventPoll();
headerItem = item.getHeader();
return fragment;
}
2) 要在 activity 或任何其他地方获取输入事件,定义一个具有必要方法的接口并为其实例创建 setter 方法:
private PollButtonClickListener listener;
public void setListener(PollButtonClickListener listener) {
this.listener = listener;
}
public interface PollButtonClickListener {
void onAnyButtonClick(Object data)
}
并在您想要获取数据的地方("dialog_event_poll" 标签已在布局中指定):
FragmentRandomEventPoll poll = FragmentRandomEventPoll.newInstance(events.get(id));
poll.setListener(new FragmentRandomEventPoll.PollButtonClickListener() {
@Override
public void onAnyButtonClick(Object data) {
// Do what you want with your data
}
});
poll.show(getSupportFragmentManager(), "dialog_event_poll");
}
如果有什么不清楚的地方,我的项目文件可以在Github.
上找到
关于处理来自 DialogFragment/BottomSheetDialogFragment 的事件。
对于有很多活动的应用程序,这个方法很棒:
context as MyDialogFragmentListener
但是我遇到了一个带有单个 activity 和多个片段的应用程序的问题。由于可能有很多片段,通过 main activity 将所有事件转移到必要的片段似乎是一个非常糟糕的选择。因此,我决定这样做:
private inline fun <reified T> findListeners(): ArrayList<T> {
val listeners = ArrayList<T>()
context?.let {
if (it is T) listeners.add(it)
if (it is AppCompatActivity) {
it.supportFragmentManager.fragments.forEach { fragment ->
if (fragment is T) listeners.add(fragment)
fragment.childFragmentManager.fragments.forEach { childFragment ->
if (childFragment is T) listeners.add(childFragment)
}
}
}
}
return listeners
}
DialogFragment 中的代码:
private val listeners by lazy { findListeners<MyDialogFragmentListener>() }
当然,片段可以包含任意数量的其他片段,并且可能需要通过递归进行检查,但在我的例子中这是多余的。
我正在开发 Material 设计应用程序。我想实现的一个功能是某种投票。当用户单击列表的元素时,持久底部 sheet 对话框应该显示如下:
然后,当用户单击任何按钮时,该对话框应该消失,模态底部 sheet 对话框应该出现,为用户提供有关开始时单击的列表项的更多信息。它看起来像这样:
我找不到任何关于 BottomSheetDialog 和 BottomSheetDialogFragment 的明确解释,以及如何正确使用它们,即使在阅读了一些关于 AppCompat 对话框的信息之后也是如此。所以,我的问题是:
- 它们有什么不同,我应该用哪一个 案例?
- 如何在 activity 中获取关于在对话框中按下了哪个按钮的数据?
- 关于实现代码或使用教程的任何链接?
最后,我找到了解决方案并且它有效。如果我做错了什么,请告诉我。它基本上像 this guide 中的 DialogFragment 一样工作,但我做的有点不同。
1) 它们的区别与DialogFragment和Dialog一样,都是模态的。如果您需要持久对话框,请使用 BottomSheetBehaviour instead(我发现这两个对话框在我的应用程序中都必须是模态的)。
2)我得先用一些代码回答第三个问题,然后再回答第二个就很容易了。
3) 创建一个新的public class
,extends BottomSheetDialogFragment
,我称之为FragmentRandomEventPoll。有两件事必须在这里实现。
覆盖方法
onCreateView
。它与 Activities 中的onCreate
方法几乎相同,除了它 returns 它应该膨胀的视图:// We will need it later private static String headerItem; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.fragment_random_event_poll, container, false); header = (TextView) v.findViewById(R.id.uRnd_fragment_bottom_sheet_poll_header); skip = (Button) v.findViewById(R.id.uRnd_fragment_bottom_sheet_button_skip); header.setText(...); // I implemented View.OnClickListener interface in my class skip.setOnClickListener(this); return v; }
静态方法,您可以将必要的数据传递给它并获取此 class 的新实例(可能我可以只使用常规构造函数,我将不得不用它进行试验多一点)。
URandomEventListItem
是数据模型 class.public static FragmentRandomEventPoll newInstance(URandomEventListItem item) { FragmentRandomEventPoll fragment = new FragmentRandomEventPoll(); headerItem = item.getHeader(); return fragment; }
2) 要在 activity 或任何其他地方获取输入事件,定义一个具有必要方法的接口并为其实例创建 setter 方法:
private PollButtonClickListener listener;
public void setListener(PollButtonClickListener listener) {
this.listener = listener;
}
public interface PollButtonClickListener {
void onAnyButtonClick(Object data)
}
并在您想要获取数据的地方("dialog_event_poll" 标签已在布局中指定):
FragmentRandomEventPoll poll = FragmentRandomEventPoll.newInstance(events.get(id));
poll.setListener(new FragmentRandomEventPoll.PollButtonClickListener() {
@Override
public void onAnyButtonClick(Object data) {
// Do what you want with your data
}
});
poll.show(getSupportFragmentManager(), "dialog_event_poll");
}
如果有什么不清楚的地方,我的项目文件可以在Github.
上找到关于处理来自 DialogFragment/BottomSheetDialogFragment 的事件。
对于有很多活动的应用程序,这个方法很棒:
context as MyDialogFragmentListener
但是我遇到了一个带有单个 activity 和多个片段的应用程序的问题。由于可能有很多片段,通过 main activity 将所有事件转移到必要的片段似乎是一个非常糟糕的选择。因此,我决定这样做:
private inline fun <reified T> findListeners(): ArrayList<T> {
val listeners = ArrayList<T>()
context?.let {
if (it is T) listeners.add(it)
if (it is AppCompatActivity) {
it.supportFragmentManager.fragments.forEach { fragment ->
if (fragment is T) listeners.add(fragment)
fragment.childFragmentManager.fragments.forEach { childFragment ->
if (childFragment is T) listeners.add(childFragment)
}
}
}
}
return listeners
}
DialogFragment 中的代码:
private val listeners by lazy { findListeners<MyDialogFragmentListener>() }
当然,片段可以包含任意数量的其他片段,并且可能需要通过递归进行检查,但在我的例子中这是多余的。