Android片段显示为dialogfragment或通常的片段

时间:2013-09-02 17:31:41

标签: java android android-layout android-fragments android-dialogfragment

我想要实现的是在平板电脑上显示一个片段,它显示为DialogFragment,而在智能手机上,它会显示为常规片段。我知道已有similar post,但我无法做到这一点 - 将样式应用于片段。

要自上而下显示,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();
        }
    }

}

详细活动并不多:

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>

while 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,但似乎没有帮助。

在智能手机上点击“下一步”操作栏菜单项时,我看到了详细的活动(来自SG2的快照): snapshot from an SG2

从平板电脑上点击相同的“NEXT”菜单项时,它不会执行任何操作(除了在Logcat上查看消息:Yes, I am seeing this line)。 enter image description here

我应该在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

3 个答案:

答案 0 :(得分:23)

如果不是试图让Fragment看起来像DialogFragment,而是从相反的角度看,我可以轻松修复此问题:让DialogFragment看起来像{{1}毕竟,FragmentDialogFragment

此修复的关键是是否致电DialogFragment.setShowsDialog();

Fragment更改为:

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

答案 1 :(得分:1)

好的,我去过那里并做到了。要创建DialogFragment,您需要使用XML定义的布局。说,为此,您以LinearLayout为根。在此LinearLayout中,您可以添加fragment class="....",当您显示DialogFragment时,您在平板电脑上并排显示的Fragment现在显示在DialogFragment中{1}}。

<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

中对此进行充气

答案 2 :(得分:1)

要将DialogFragment节目制作为常规Fragment,请使用片段容器的资源ID调用add()replace(),例如

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

但要将DialogFragment显示为对话框,请调用add(fragment, "Fragment Tag")。在幕后,这会导致调用add(resId, fragment),将片段容器的资源ID设置为0,这会导致DialogFragment将其showAsDialog选项设置为true。

因此,您可以根据需要使用对话框片段作为对话框或常规片段,而无需创建任何特殊逻辑来执行此操作。