14

我想要实现的是在平板电脑上显示一个片段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();
        }
    }

}

详细活动没什么:

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

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

在平板电脑上点击相同的“NEXT”菜单项时,它什么也不做(除了在 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
4

3 回答 3

27

这个问题可以很容易地解决,如果不是试图让一个Fragment看起来像DialogFragment我会从相反的角度看:让一个DialogFragment看起来像 a Fragment- 毕竟,aDialogFragment是一个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");
    }
}
于 2013-09-04T12:00:53.210 回答
1

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

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

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

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

于 2016-06-05T20:31:23.030 回答
0

好的,我去过那里并做到了。要制作一个DialogFragment您需要在 XML 中定义的布局。说,为此你有LinearLayout根。在此LinearLayout您可以添加一个fragment class="....",当您显示您的时DialogFragment,它将与Fragment您在平板电脑上并排显示的相同,现在显示在 a 中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

于 2013-09-02T18:13:03.147 回答