11

Was ich versuche zu erreichen, um ein Fragment zu haben, der auf Tablette es als DialogFragment zeigt, während auf dem Smartphone würde es als reguläres Fragment gezeigt werden. Ich bin mir bewusst, dass es bereits eine similar post, aber ich bin nicht in der Lage, diese Arbeit zu machen - wenden Sie den Stil auf Fragment.Android Fragment zeigt als dialogfragment oder gewöhnliches Fragment

Dinge zu zeigen, von oben nach unten, 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 ist nicht viel:

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

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

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

... und das 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 Ich habe versucht, das individuelle Styling zu setzen, aber es scheint nicht für Tablette zu arbeiten.

Styling

res/Werte/styles.xml enthält:

<resources> 

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

    <style name="MyDialogTheme" /> 

</resources> 

während res/Werte-large/styles.xml:

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

I MyDialogTheme verschachtelt haben von Theme.Dialog, aber es scheint nicht zu helfen.

auf Smartphone, wenn sie auf „NEXT“ Aktionsleiste Menüpunkt tippen ich die detaillierte Aktivität sehe (Schnappschuss von einem SG2): snapshot from an SG2

während auf dem gleichen „NEXT“ Menüpunkt aus der Tablette Klopfen es doesn tue nichts (außer das Anzeigen der Nachricht auf Logcat: Yes, I am seeing this line). enter image description here

Was soll ich mehr in styles.xml oder in Code hinzufügen, um DetailedFragment als Dialog für Tablet zu sehen?

EDIT

ich die Lösung kleines Kind versucht haben vorgeschlagen (a DialogFragment enthalten meine erste Fragment zu haben, und zeigen Sie es).So habe ich hinzugefügt eine 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); 
    } 
} 

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

Der Code von MainActivity wechselt zu:

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

aber wenn ich versuche, diese DialogFragment hinzufügen Ich bekomme folgenden Absturz:

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 

Antwort

21

kann dieses Problem leicht behoben werden, wenn anstatt zu versuchen, einen Fragment aussehen wie ein DialogFragment zu machen ich aus dem entgegengesetzten Winkel aussehen würde: ein DialogFragment aussehen wie ein Fragment machen - immerhin ein DialogFragment ist a Fragment!

Der Schlüssel dieses Updates ist oder nicht DialogFragment.setShowsDialog();

So Ändern der DetailedFragment zu nennen:

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

das Layout, wie es bleibt, war DetailedActivity Änderungen:

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

sein Layout auch:

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

und der Anrufer Aktivität tut nur:

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, ich war dort und habe das gemacht. Um eine DialogFragment zu erstellen, benötigen Sie ein Layout, das in XML definiert ist. Sagen Sie, dafür haben Sie LinearLayout als root. In diesem LinearLayout können Sie eine fragment class="...." hinzufügen und wenn Sie Ihre DialogFragment anzeigen, wird es das gleiche sein Fragment Sie nebeneinander auf dem Tablett angezeigt jetzt in einem DialogFragment angezeigt.

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

Wie so. Und aufblasen dies in Ihrem DialogFragment

+0

Ich glaube nicht, dass Sie die Frage verstanden: Ich brauche ein Fragment, das als 'DialogFragment' für Tablet angezeigt wird, aber das gleiche Fragment muss ein Nicht-DialogFragment für das Smartphone bleiben.Die Antwort, die Sie angegeben haben, zeigt, wie ein Fragment angezeigt wird. Ich denke, Sie erhalten eine 'IllegalArgumentException', wenn' FeedFragment' ein 'DialogFragment' ist:' DialogFragment' kann nicht an eine Containeransicht angehängt werden'. Ein DialogFragment kann nur über die Fragment/Trans- ation add/replace-Methode hinzugefügt werden, nachdem der Stamm erstellt wurde. – gunar

+0

Überhaupt nicht. Sie müssen ein anderes Layout für kleine Telefone und für Tablets definieren. Ich hoffe, Ihnen ist bewusst, dass Sie das tun können :) Bei Tablets werden die Fragmente nebeneinander angezeigt. Was Sie verpasst haben ist ... das 'DialogFragment' ** enthält ** das' Fragment'. –

+0

Also wenn ich Sie richtig verstanden habe: Sie schlagen vor, ein DialogFragment zu haben und in ihm das Fragment, das ich zeigen möchte? – gunar

1

Um eine DialogFragment Show als reguläres Fragment zu machen, rufen add() oder replace() eine Ressourcen-ID für das Fragment Behälter, zB

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

Aber Um DialogFragment als Dialog anzuzeigen, rufen Sie add(fragment, "Fragment Tag"). Hinter den Kulissen führt dies zu einem Aufruf an add(resId, fragment), bei dem die Ressourcen-ID für den Fragmentcontainer auf 0 gesetzt wird, wodurch die DialogFragment ihre showAsDialog-Option auf true setzt.

Als Konsequenz können Sie ein Dialogfragment als Dialog oder als normales Fragment verwenden - abhängig von Ihren Anforderungen - ohne dass Sie dafür eine spezielle Logik erstellen müssen.