TL; DR - DialogFragment недостаточно для чего-либо кроме полностью полного экрана. Вместо этого используйте действие.
Можно сделать полный экран (ActionBar
), но он содержит множество раздражений.
DialogFragment
есть, как следует из названия, в Dialog
и Fragment
в одном лице: его можно рассматривать и как Dialog
, используя show()
и dismiss()
, или в качестве Fragment
, используя его с FragmentManager
.
Как official documentation suggests, что делает диалог полностью полноэкранный (накладывания всё) достигается путем присоединения диалога с точки зрения корневой android.R.id.content
:
public void showDialog() {
FragmentManager fragmentManager = getSupportFragmentManager();
CustomDialogFragment newFragment = new CustomDialogFragment();
if (mIsLargeLayout) {
// The device is using a large layout, so show the fragment as a dialog
newFragment.show(fragmentManager, "dialog");
} else {
// The device is smaller, so show the fragment fullscreen
FragmentTransaction transaction = fragmentManager.beginTransaction();
// For a little polish, specify a transition animation
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
// To make it fullscreen, use the 'content' root view as the container
// for the fragment, which is always the root view for the activity
transaction.add(android.R.id.content, newFragment)
.addToBackStack(null).commit();
}
}
Чтобы получить диалоговое окно появится ниже ActionBar
, FrameLayout
, который используется вместо корневой компоновки:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawer_layout"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:fitsSystemWindows="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.design.widget.CoordinatorLayout
android:id="@+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- Use ThemeOverlay to make the toolbar and tablayout text
white -->
<android.support.design.widget.AppBarLayout
android:id="@+id/abl_top"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:fitsSystemWindows="true"
android:layout_height="wrap_content"
android:layout_width="match_parent"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:layout_scrollFlags="scroll|enterAlways"/>
</android.support.design.widget.AppBarLayout>
</android.support.design.widget.CoordinatorLayout>
<FrameLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
<android.support.design.widget.NavigationView
android:id="@+id/nav_view"
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="@layout/nav_header"
app:menu="@menu/nav_view"/>
</android.support.v4.widget.DrawerLayout>
Теперь наступает боль.
В зависимости от того, как настраивается основная навигация приложения, нужно будет перепрыгнуть различные обручи, чтобы все работало отлично.
Приведенный выше пример имеет NavigationView
. Поскольку главная кнопка android.R.id.home
обрабатывается в главном окне, для этого необходимо проверить, отображается ли наш диалог, чтобы кнопка «home», которая теперь находится X
, закроет диалоговое окно. Возврат false
позволяет разрешить событие в диалоговом окне.
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
FragmentManager fm = getSupportFragmentManager();
Fragment f = fm.findFragmentById(R.id.content);
if (f instanceof MyDialogFragment) {
return false;
}
mDrawerLayout.openDrawer(GravityCompat.START);
return true;
}
return super.onOptionsItemSelected(item);
}
Кроме того, кнопка назад нуждается в подобную логике, чтобы определить, является ли закрывание NavigationView
потребности или переустановка ActionBar
содержания.
@Override
public void onBackPressed() {
if (mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
mDrawerLayout.closeDrawer(GravityCompat.START);
} else {
FragmentManager fm = getSupportFragmentManager();
Fragment f = fm.findFragmentById(R.id.content);
if (f instanceof MyDialogFragment) {
final ActionBar ab = getSupportActionBar();
ab.setHomeAsUpIndicator(R.drawable.ic_menu);
ab.setTitle(R.string.app_name);
}
super.onBackPressed();
}
}
В DialogFragment
сама логика для закрытия диалога (и злоупотребления ActionBar
) должна быть реализована.
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
if (mActionBar != null) {
mActionBar.setHomeAsUpIndicator(R.drawable.ic_menu);
mActionBar.setTitle(R.string.app_name);
}
getActivity().getSupportFragmentManager().popBackStack();
case R.id.action_save:
if (mOnAcceptListener != null) {
mOnAcceptListener.onAccept();
}
if (mActionBar != null) {
mActionBar.setHomeAsUpIndicator(R.drawable.ic_menu);
mActionBar.setTitle(R.string.app_name);
}
getActivity().getSupportFragmentManager().popBackStack();
return true;
}
return super.onOptionsItemSelected(item);
}
Все это чувствует себя действительно kludgy. Конечно, если вы используете TabLayout
, забудьте все, что я только что сказал.
С TabLayout
вы можете просто обрабатывать все в DialogFragment
, но если вы используете ViewPager
, это будет невозможно получить диалог, чтобы покрыть вкладки, но не бар действия. См. Show DialogFragment over TabLayout.
Этот вопрос (у меня) имеет ответ, который предлагает то же самое, что и @Jdruwe, чтобы забыть безнадежность DialogFragment
и вместо этого использовать Activity
.
Каков ваш макет файла вашего дочернего фрагмента? – windchime
http://pastebin.com/bhscbGu2 – Jdruwe
Я видел ответы и другие вопросы, которые используют FragmentTransaction для добавления диалога, но я еще не получил его работу. – Jon