11

Quello che sto cercando di ottenere è un frammento che sul tablet mostri come DialogFragment, mentre su smartphone verrà visualizzato come un normale frammento. Sono consapevole che c'è già un similar post, ma non sono in grado di farlo funzionare - applicare lo stile al frammento.Il frammento di Android viene visualizzato come dialogfragment o frammento normale

Per mostrare le cose verso il basso, 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 c'è molto:

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

suo layout:

<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" /> 

e l'interessante 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); 
    } 
} 

... e il suo layout:

<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> 

In onCreateView ho cercato di impostare lo stile personalizzato, ma non sembra funzionare per tablet.

Styling

res/valori/styles.xml contiene:

<resources> 

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

    <style name="MyDialogTheme" /> 

</resources> 

mentre res/valori-large/styles.xml:

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

ho nidificati MyDialogTheme da Theme.Dialog, ma non sembra aiutare.

Su smartphone quando si tocca su "NEXT" voce di menu barra delle operazioni che sto vedendo l'attività dettagliata (snapshot da uno SG2): snapshot from an SG2

mentre toccando la stessa voce di menu "NEXT" dalla tavoletta doesn fare qualsiasi cosa (eccetto la visualizzazione del messaggio su Logcat: Yes, I am seeing this line). enter image description here

Cosa devo aggiungere di più in styles.xml o nel codice per vedere DetailedFragment come una finestra di dialogo per tablet?

EDIT

Ho provato la soluzione Piccolo Bambino proposto (per avere un DialogFragment contenere la mia frammento iniziale e vederlo).Così, ho aggiunto un 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); 
    } 
} 

suo layout:

<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> 

Il codice da MainActivity cambia in:

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"); 
    } 
} 

ma quando sto cercando di aggiungere questo DialogFragment Sto ottenendo il seguente arresto:

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 

risposta

21

Questo problema può essere facilmente risolto se invece di cercare di fare un look Fragment come un DialogFragment Vorrei guardare dal punto di vista opposto: fare un look DialogFragment come un Fragment - dopo tutto, un DialogFragment è a Fragment!

La chiave di questa correzione è chiamare o no DialogFragment.setShowsDialog();

Quindi cambiando la DetailedFragment a:

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); 
    } 
} 

il suo layout rimane com'era, DetailedActivity modifiche:

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(); 
     } 
    } 
} 

il suo layout pure:

<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" /> 

e l'attività chiamante fa solo:

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"); 
    } 
} 
1

OK, ci sono stato e l'ho fatto. Per creare un numero DialogFragment è necessario un layout definito in XML. Dì, per questo hai LinearLayout come root. In questo LinearLayout puoi aggiungere un fragment class="...." e quando visualizzi il tuo DialogFragment, sarà lo stesso Fragment visualizzato parallelamente sul tablet ora visualizzato in un 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> 

Mi piace così. E gonfiare questo nella vostra DialogFragment

+0

Non penso che tu abbia capito la domanda: ho bisogno di un frammento per essere visualizzato come 'DialogFragment' per tablet, ma lo stesso frammento deve rimanere un non-DialogFragment per smartphone.La risposta che hai fornito mostra come visualizzare un frammento, ma credo che otterrai "IllegalArgumentException" se "FeedFragment" è un "DialogFragment':" DialogFragment' non può essere collegato a una vista del contenitore ". Un DialogFragment può essere aggiunto solo tramite il metodo di aggiunta/sostituzione FragmentTransation dopo la creazione della radice. – gunar

+0

Niente affatto. Dovrai definire un layout diverso per i telefoni piccoli e per i tablet. Spero tu sappia che puoi farlo :) Per i tablet, i frammenti verranno visualizzati fianco a fianco. Quello che ti sei perso è ... il 'DialogFragment' ** conterrà ** il' Fragment'. –

+0

Quindi se capisco che hai ragione: stai suggerendo di avere un DialogFragment e al suo interno il Frammento che mi interessa mostrare? – gunar

1

per fare uno Show DialogFragment come un normale Fragment, chiamano add() o replace() utilizzando un ID di risorsa per il contenitore frammento, ad esempio

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

Ma per visualizzare DialogFragment come una finestra di dialogo, chiamare add(fragment, "Fragment Tag"). Dietro le quinte si ottiene una chiamata a add(resId, fragment), impostando l'ID risorsa per il contenitore del frammento su 0, che fa sì che DialogFragment imposti l'opzione showAsDialog su true.

Di conseguenza è possibile utilizzare un frammento di finestra di dialogo come una finestra di dialogo o un normale frammento, a seconda delle esigenze, senza la necessità di creare alcuna logica speciale per farlo.

Problemi correlati