Фрагмент Android отображается как диалоговый фрагмент или обычный фрагмент

То, что я пытаюсь достичь, – это иметь фрагмент, который на планшете он отображается как DialogFragment , а на смартфоне он будет показан как обычный фрагмент. Я знаю, что уже есть аналогичная запись , но я не могу сделать эту работу – примените стиль к фрагменту.

Чтобы показать вещи сверху вниз, MainActivity.java:

 public class MainActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == R.id.action_next) { decideToNext(); return true; } return super.onOptionsItemSelected(item); } private void decideToNext() { String device = getString(R.string.device); if ("normal".equalsIgnoreCase(device)) { Intent intent = new Intent(this, DetailedActivity.class); startActivity(intent); } else if ("large".equalsIgnoreCase(device)) { Log.d("SOME_TAG", "Yes, I am seeing this line on tablet only"); DetailedFragment fragment = DetailedFragment.newInstance(); getSupportFragmentManager().beginTransaction().add(fragment, "MAGIC_TAG").commit(); } } } 

DetailedActivity – это не что иное:

 public class DetailedActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.detailed_activity); } } 

Его расположение:

 <fragment xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/root_container" android:name="com.myapps.sampleandroid.DetailedFragment" android:layout_width="match_parent" android:layout_height="match_parent" /> 

И интересный DetailedFragment :

 public class DetailedFragment extends Fragment { public static DetailedFragment newInstance() { return new DetailedFragment(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Context contextThemeWrapper = new ContextThemeWrapper(getActivity(), R.style.MyDialogTheme); LayoutInflater localInflater = inflater.cloneInContext(contextThemeWrapper); return localInflater.inflate(R.layout.detailed_fragment, container, false); } } 

… и его расположение:

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Regular Text" /> <TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Large Text" android:textAppearance="?android:attr/textAppearanceLarge" /> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button Dummy" /> </LinearLayout> 

В onCreateView я попытался установить пользовательский стиль, но он не работает на планшет.

стайлинг

Res / values ​​/ styles.xml содержит:

 <resources> <style name="AppTheme" parent="@style/Theme.AppCompat.Light.DarkActionBar"> </style> <style name="MyDialogTheme" /> </resources> 

В то время как res / values-large / styles.xml:

 <resources> <!-- Is there anything I should add here? --> <style name="MyDialogTheme" parent="@android:style/Theme.Dialog"/> </resources> 

Я MyDialogTheme из Theme.Dialog , но, Theme.Dialog , это не помогает.

На смартфоне, когда вы нажимаете на пункт меню «СЛЕДУЮЩИЙ», я вижу подробную активность (моментальный снимок с SG2): Моментальный снимок с SG2

При нажатии на тот же пункт меню «СЛЕДУЮЩИЙ» с планшета он ничего не делает (кроме просмотра сообщения на Logcat: Yes, I am seeing this line ). Введите описание изображения здесь

Что нужно добавить еще в styles.xml или в коде, чтобы увидеть DetailedFragment как диалог для планшета?

РЕДАКТИРОВАТЬ

Я пробовал решение Little Child, предлагаемое (чтобы иметь DialogFragment содержащий мой первоначальный фрагмент и показать его). Итак, я добавил WrapperDetailedFragment :

 public class WraperDetailedFragment extends DialogFragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.wrap_detailed_fragment, container, false); } } 

Его расположение:

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/root_container_dialog" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <fragment android:id="@+id/wrapped_fragment_id" android:layout_width="match_parent" android:layout_height="match_parent" class="com.myapps.sampleandroid.DetailedFragment" /> </LinearLayout> 

Код из MainActivity изменится на:

 private void decideToNext() { String device = getString(R.string.device); if ("normal".equalsIgnoreCase(device)) { Intent intent = new Intent(this, DetailedActivity.class); startActivity(intent); } else if ("large".equalsIgnoreCase(device)) { Log.d("SOME_TAG", "Yes, I am seeing this line ..."); WraperDetailedFragment fragment = new WraperDetailedFragment(); fragment.show(getSupportFragmentManager(), "MAGICAL_TAG"); } } 

Но когда я пытаюсь добавить этот DialogFragment, я получаю следующий сбой:

 android.view.InflateException: Binary XML file line #8: Error inflating class fragment at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704) at android.view.LayoutInflater.rInflate(LayoutInflater.java:746) at android.view.LayoutInflater.inflate(LayoutInflater.java:489) at android.view.LayoutInflater.inflate(LayoutInflater.java:396) at com.myapps.sampleandroid.WraperDetailedFragment.onCreateView(WraperDetailedFragment.java:12) at android.support.v4.app.Fragment.performCreateView(Fragment.java:1478) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:927) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1082) at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:304) at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:676) at android.view.LayoutInflater.rInflate(LayoutInflater.java:746) at android.view.LayoutInflater.inflate(LayoutInflater.java:489) at android.view.LayoutInflater.inflate(LayoutInflater.java:396) at com.myapps.sampleandroid.WraperDetailedFragment.onCreateView(WraperDetailedFragment.java:12) at android.support.v4.app.Fragment.performCreateView(Fragment.java:1478) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:927) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104) at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682) at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1460) at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:440) at android.os.Handler.handleCallback(Handler.java:615) at android.os.Handler.dispatchMessage(Handler.java:92) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:4745) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) at dalvik.system.NativeStart.main(Native Method) Caused by: java.lang.IllegalArgumentException: Binary XML file line #8: Duplicate id 0x7f050047, tag null, or parent id 0x0 with another fragment for com.myapps.sampleandroid.DetailedFragment at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:290) at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:676) ... 28 more 

Solutions Collecting From Web of "Фрагмент Android отображается как диалоговый фрагмент или обычный фрагмент"

Эта проблема может быть легко исправлена, если вместо того, чтобы сделать Fragment похожим на DialogFragment я бы посмотрел с противоположного угла: сделайте DialogFragment похожим на Fragment – в конце концов, DialogFragment – это Fragment !

Ключом этого исправления является вызов или не DialogFragment.setShowsDialog();

Поэтому, изменив параметр DetailedFragment на:

 public class DetailedFragment extends DialogFragment { private static final String ARG_SHOW_AS_DIALOG = "DetailedFragment.ARG_SHOW_AS_DIALOG"; public static DetailedFragment newInstance(boolean showAsDialog) { DetailedFragment fragment = new DetailedFragment(); Bundle args = new Bundle(); args.putBoolean(ARG_SHOW_AS_DIALOG, showAsDialog); fragment.setArguments(args); return fragment; } public static DetailedFragment newInstance() { return newInstance(true); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Bundle args = getArguments(); if (args != null) { setShowsDialog(args.getBoolean(ARG_SHOW_AS_DIALOG, true)); } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.detailed_fragment, container, false); } } 

Его макет остается таким, каким он есть, DetailedActivity меняет:

 public class DetailedActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.detailed_activity); if (savedInstanceState == null) { DetailedFragment fragment = DetailedFragment.newInstance(false); getSupportFragmentManager().beginTransaction().add(R.id.root_layout_details, fragment, "Some_tag").commit(); } } } 

Его расположение также:

 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/root_layout_details" android:layout_width="match_parent" android:layout_height="match_parent" /> 

И активность вызывающего абонента делает только:

 private void decideToNext() { String device = getString(R.string.device); if ("normal".equalsIgnoreCase(device)) { Intent intent = new Intent(this, DetailedActivity.class); startActivity(intent); } else if ("large".equalsIgnoreCase(device)) { DetailedFragment fragment = DetailedFragment.newInstance(); fragment.show(getSupportFragmentManager(), "Tablet_specific"); } } 

Хорошо, я был там и сделал это. Для создания DialogFragment вам нужен макет, определенный в XML. Скажем, для этого у вас есть LinearLayout как root. В этом LinearLayout вы можете добавить fragment class="...." и при отображении вашего DialogFragment это будет тот же Fragment вы показывали бок о бок на планшете, который теперь отображается в DialogFragment .

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <fragment class="com.example.tqafragments.FeedFragment" android:id="@+id/feedFragment" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1"/> </LinearLayout> 

Вот так. И DialogFragment это в своем DialogFragment

Чтобы сделать DialogFragment как обычный Fragment , вызовите add() или replace() используя идентификатор ресурса для контейнера фрагмента, например

 beginTransaction().add(R.id.fragment_container, fragment) 

Но чтобы диалог DialogFragment отображался как диалог, назовите add(fragment, "Fragment Tag") . За кулисами это приводит к призыву add(resId, fragment) , установив идентификатор ресурса для контейнера фрагмента DialogFragment 0, что приводит к тому, что DialogFragment устанавливает showAsDialog параметра showAsDialog значение true.

Как следствие, вы можете использовать фрагмент диалога как диалог или обычный фрагмент – в зависимости от ваших потребностей – без необходимости создавать какую-либо специальную логику для этого.