片段和 onConfigurationChanged

Posted

技术标签:

【中文标题】片段和 onConfigurationChanged【英文标题】:fragments and onConfigurationChanged 【发布时间】:2013-04-23 08:39:37 【问题描述】:

我正在尝试用活动做一些事情,但在一个片段内。 我所做的是使用活动:

旋转设备时首先停止活动重新启动 android:configChanges="keyboardHidden|orientation|screenSize"

在我的活动中添加:

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

 setContentView(R.layout.main);

所以拿到activity并没有重启,而是重新加载main.xml,来使用layout-land

现在我有一个显示 viewpager 的活动,其中包含三个片段。 一切正常。旋转检测是在片段中

public class FRG_map_web extends Fragment  

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

        Log.i("myLogs", "Rotation");

    

问题是片段没有使用 setContentView(R.layout.main);这是代码:

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) 
        view = inflater.inflate(R.layout.frg.myFragment, null); 

我尝试使用:

LayoutInflater inflater = inflater = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);

view = inflater.inflate(R.layout.frg.myFragment, null); 

...

LayoutInflater vi = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);

view = inflater.inflate(R.layout.frg.myFragment, null); 

...

LayoutInflater inflater = (LayoutInflater) context.getSystemService( Context.LAYOUT_INFLATER_SERVICE );

view = inflater.inflate(R.layout.frg.myFragment, null); 

...

LayoutInflater li = LayoutInflater.from(context);

和不同的方式,但总是没有成功 我无法正常充气。

谁能告诉我该怎么做?

在此先感谢,感谢您的帮助

问候

【问题讨论】:

你的问题一点都不清楚。您是否尝试在旋转后重新创建片段? 我的意图是旋转设备后不重启activity,而是fragment的onConfigurationChanged,重新加载布局xml 你会遇到android:configChanges 的问题,因为在大多数情况下,你不应该使用它。您没有考虑到许多类型的配置更改。 onSavedInstanceState 是你的朋友。 我在片段中使用位图,如果每次旋转设备时片段都会重新加载,我会遇到“内存不足”的问题。第一次加载是受控的,而不是其余的(如何旋转),所以我只需要加载一次 因为位图而覆盖 android:configChanges 是一个糟糕的借口。您必须通过onSavedInstanceState 在配置更改之间保留位图。 【参考方案1】:

如果我理解正确,您不希望片段在每次旋转时重新加载。相反,您希望重新布局视图并使用您已有的信息更新它们。

public void onConfigurationChanged(Configuration newConfig) 
    super.onConfigurationChanged(newConfig);

    // Get a layout inflater (inflater from getActivity() or getSupportActivity() works as well)
    LayoutInflater inflater = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View newView = inflater.inflate(R.layout.frg.myFragment, null);
    // This just inflates the view but doesn't add it to any thing.
    // You need to add it to the root view of the fragment
    ViewGroup rootView = (ViewGroup) getView();
    // Remove all the existing views from the root view.
    // This is also a good place to recycle any resources you won't need anymore
    rootView.removeAllViews();
    rootView.addView(newView);
    // Viola, you have the new view setup

根据文档 (getView()),getView() 返回的视图与您从 onCreateView() 返回的视图相同,但事实并非如此。它实际上返回您在 onCreateView() 中返回的视图的父级,这正是您所需要的。 getView() 将返回一个 NoSaveStateFrameLayout 的实例,该实例专门用于 Fragments 作为其根视图。

希望这会有所帮助。

【讨论】:

我认为这是一个很好的解决方案,但我得到一个力关闭,不知道为什么。我放了一个关于日志的日志 ul.to/arq9y8gj 的链接,我也尝试过不使用 actionbarsherlock,错误仍然存​​在 从错误日志中检查,您似乎遇到了重复片段的错误。检查此解决方案***.com/questions/14083950/… 感谢 lika a Charm 工作 如果您的视图有任何其他布局而不是左上角,您需要在新视图上再次设置布局参数。不过,您可以从上一个得到这个:ViewGroup.LayoutParams lp = rootView.getChildAt(0).getLayoutParams(); newView.setLayoutParams(lp); 我试过了:查看 newView = inflater.inflate(R.layout.frg.myFragment, null);但收到警告,所以我稍微修改了代码:(1)我先声明 rootView(2)改为调用它“View newView = inflater.inflate(R.layout.my frag, rootView, false);”最终结果相同,但没有警告。 :)【参考方案2】:

您是否考虑过保留您的片段实例?见Fragment#setRetainInstance。

允许重新创建您的 Activity(不要指定 android:configChanges),但在方向更改时保留您的片段实例。如果所有繁重的工作都发生在 Fragment#onCreate 这应该可以正常工作。 onCreate() 不会被再次调用,因为片段没有被重新创建。

【讨论】:

onCreateView() 被再次调用以创建新的视图层次结构。应该可以保留位图并在新创建的视图中重用它们。【参考方案3】:

我可以通过在 onConfigurationChanged 中重新附加片段来做到这一点:

   @Override
   public void onConfigurationChanged(Configuration newConfig)
    
        getActivity().detachFragment(this);

        super.onConfigurationChanged(newConfig);

        ....

        getActivity().attachFragment(this);
    

请记住,通过分离和附加您的片段,您将只使用它的视图。但是片段状态在片段管理器中被“保存”了。

【讨论】:

Activity.[detach|attach]Fragment() 方法不存在,必须使用 FragmentManager.beginTransaction().[detach|attach]()。【参考方案4】:

您可以尝试分离附加片段:

@Override
public void onConfigurationChanged(Configuration newConfig) 
    FragmentManager fragmentManager = getFragmentManager();
    if (fragmentManager != null) 
        fragmentManager.beginTransaction().detach(this).commitAllowingStateLoss();
    
    super.onConfigurationChanged(newConfig);
    if (fragmentManager != null) 
        fragmentManager.beginTransaction().attach(this).commitAllowingStateLoss();
    

【讨论】:

【参考方案5】:

也许你可以尝试使用

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) 
    view = inflater.inflate(R.layout.frg.myFragment, container, false);

。无论如何,fragment 还是要被销毁和重新创建的,为什么不让 Android 通过重启 Activity 来自动处理呢?如果有需要保留的数据,可以保存在onSavedInstanceState()。不建议在 Android 中设置android:configChanges="keyboardHidden|orientation|screenSize"

【讨论】:

以上是关于片段和 onConfigurationChanged的主要内容,如果未能解决你的问题,请参考以下文章

onConfigurationChanged 未触发

移动到 1/3 屏幕宽度时未调用 onConfigurationChanged

内存泄漏通过onConfigurationChanged()

onConfigurationChanged 屏幕停止在设备上旋转。在模拟器上工作

Android开发,重写了onConfigurationChanged方法。横屏切换竖屛不会重建,而竖屛切换横屏却仍会重建活动

Kotlin & 'onConfigurationChanged' overrides nothing