如何在方向改变时配置特定片段的方向?

时间:2012-06-13 03:41:33

标签: android orientation android-fragments

我在MainActivity内有多个片段我想仅在DetailFragment

中配置方向更改
public class DetailFragment extends Fragment{
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {

            WindowManager wm = getActivity().getWindowManager();

            Display d = wm.getDefaultDisplay();
            if(d.getWidth() > d.getHeight()){
                mDetailView = inflater.inflate(R.layout.detail, container, false);
            }else{
                mDetailView = inflater.inflate(R.layout.detail_port, container, false);
            }
            gridView = (GridView)mDetailView.findViewById(R.id.grid);
        return mDetailView;
        }
}

所以,我必须在onConfigurationChanged中覆盖SubTopicFragment以下是SubTopicFragment extend ListFragment的某些部分

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    updateDetial(topic_index, args.getString("group_id"), args.getString("group_name"));
}

public void updateDetial(int subTopicPosition,String groupID, String groupName){
    FragmentManager fragmentManager = getFragmentManager();
    FragmentTransaction ft = fragmentManager.beginTransaction();
    DetailFragment detailView = (DetailFragment)getFragmentManager()
                                .findFragmentById(R.id.detailFrame);
    DetailFragment detailFrag = new DetailFragment(topic_index, subTopicPosition, groupID, groupName);

    if(detailView==null){

        ft.add(R.id.detailFrame, detailFrag);
        ft.commit();
    }else{
        ft.replace(R.id.detailFrame, detailFrag);
        ft.commit();
    }
}

效果很好。但问题发生在我移动到另一个活动然后,更改方向并按回按钮,它会导致强制关闭我该如何解决这个问题?

06-13 10:15:54.758: E/AndroidRuntime(1050): FATAL EXCEPTION: main
06-13 10:15:54.758: E/AndroidRuntime(1050): java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
06-13 10:15:54.758: E/AndroidRuntime(1050):     at android.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1192)
06-13 10:15:54.758: E/AndroidRuntime(1050):     at android.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1203)
06-13 10:15:54.758: E/AndroidRuntime(1050):     at android.app.BackStackRecord.commitInternal(BackStackRecord.java:557)
06-13 10:15:54.758: E/AndroidRuntime(1050):     at android.app.BackStackRecord.commit(BackStackRecord.java:541)
06-13 10:15:54.758: E/AndroidRuntime(1050):     at com.april.android.SubTopicFragment.updateDetial(SubTopicFragment.java:120)
06-13 10:15:54.758: E/AndroidRuntime(1050):     at com.april.android.SubTopicFragment.onConfigurationChanged(SubTopicFragment.java:259)
06-13 10:15:54.758: E/AndroidRuntime(1050):     at android.app.FragmentManagerImpl.dispatchConfigurationChanged(FragmentManager.java:1706)
06-13 10:15:54.758: E/AndroidRuntime(1050):     at android.app.Activity.onConfigurationChanged(Activity.java:1402)
06-13 10:15:54.758: E/AndroidRuntime(1050):     at android.app.ActivityThread.performConfigurationChanged(ActivityThread.java:3298)
06-13 10:15:54.758: E/AndroidRuntime(1050):     at android.app.ActivityThread.handleActivityConfigurationChanged(ActivityThread.java:3427)
06-13 10:15:54.758: E/AndroidRuntime(1050):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1113)
06-13 10:15:54.758: E/AndroidRuntime(1050):     at android.os.Handler.dispatchMessage(Handler.java:99)
06-13 10:15:54.758: E/AndroidRuntime(1050):     at android.os.Looper.loop(Looper.java:132)
06-13 10:15:54.758: E/AndroidRuntime(1050):     at android.app.ActivityThread.main(ActivityThread.java:4123)
06-13 10:15:54.758: E/AndroidRuntime(1050):     at java.lang.reflect.Method.invokeNative(Native Method)
06-13 10:15:54.758: E/AndroidRuntime(1050):     at java.lang.reflect.Method.invoke(Method.java:491)
06-13 10:15:54.758: E/AndroidRuntime(1050):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
06-13 10:15:54.758: E/AndroidRuntime(1050):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
06-13 10:15:54.758: E/AndroidRuntime(1050):     at dalvik.system.NativeStart.main(Native Method)

2 个答案:

答案 0 :(得分:0)

您不应该在onCreateView

中加载两个不同的布局ID

为您的布局使用一个布局ID

你能做的是

布局文件夹中的R.layout.detail

R.layout.detail_port将其重命名为R.layout.detail并将其放在res的layout-port文件夹中

然后inflater.inflate(R.layout.detail,container,false);将根据方向自动给出具体布局

阅读此文档http://developer.android.com/guide/topics/resources/providing-resources.html

答案 1 :(得分:0)

几乎所有关于代码的内容都是错误的。

        Display d = wm.getDefaultDisplay();
        if(d.getWidth() > d.getHeight()){
            mDetailView = inflater.inflate(R.layout.detail, container, false);
        }else{
            mDetailView = inflater.inflate(R.layout.detail_port, container, false);
        }
        gridView = (GridView)mDetailView.findViewById(R.id.grid);

不要这样做 - 平台有自己的方式使用命名约定加载布局。您的代码应如下所示:

    mDetailView = inflater.inflate(R.layout.detail, container, false);
    gridView = (GridView)mDetailView.findViewById(R.id.grid);

如果您希望它在不同方向上看起来不同,请在layout-portlayout-land中放置两个detail.xml文件,操作系统将加载正确的文件(并处理扣除所有资源ID)这可能是你的问题)。也:

DetailFragment detailView = (DetailFragment)getFragmentManager()
                            .findFragmentById(R.id.detailFrame);
DetailFragment detailFrag = new DetailFragment(topic_index, subTopicPosition, groupID, groupName);

if(detailView==null){

    ft.add(R.id.detailFrame, detailFrag);
    ft.commit();
}else{
    ft.replace(R.id.detailFrame, detailFrag);
    ft.commit();
}

您可以访问已存在的片段。然后,您创建一个全新的片段。然后在添加新的Fragment之前检查你的第一个Fragment是否为null? .add()和.replace()是不同的,因为add()具体不会删除前一个片段 - 如果没有要删除的先前片段,则replace()不会抛出错误,所以每次都可以使用它

    ft.replace(R.id.detailFrame, new DetailFragment(topic_index, subTopicPosition, groupID, groupName);
    ft.commit();