【问题标题】:Handling orientation changes with Fragments使用 Fragments 处理方向变化
【发布时间】:2011-05-28 21:05:14
【问题描述】:

我目前正在使用 HC 兼容性包的多窗格 Fragment-ised 视图测试我的应用程序,并且有很多难以处理的方向更改。

我的Host 活动有 2 个横向窗格(menuFramecontentFrame),只有纵向的 menuFrame,加载了适当的片段。如果我在两个窗格中都有一些东西,然后将方向更改为纵向,我会得到一个 NPE,因为它试图在片段中加载视图,该片段将位于(不存在的)contentFrame 中。在内容片段中使用 setRetainState() 方法不起作用。如何解决这个问题以防止系统加载不会显示的片段?

非常感谢!

【问题讨论】:

    标签: android android-3.0-honeycomb android-fragments


    【解决方案1】:

    onCreateViewMethod 似乎引起了问题;如果容器为空,它必须返回空:

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {   
        if (container == null) // must put this in
            return null;
        return inflater.inflate(R.layout.<layout>, container, false);
    }
    

    【讨论】:

    • 这并没有摆脱片段。它只是防止它被绘制。它仍在内存中,每次旋转时都会复制片段。
    【解决方案2】:

    可能不是理想的答案,但如果您有 contentFrame 用于纵向,并且在您的活动中仅在 savedInstanceState 为空时加载 menuFrame,那么您的内容框架片段将在方向更改时显示。

    虽然不理想,但如果您点击后退按钮(根据需要多次),那么您将永远看不到菜单片段,因为它没有加载到 contentFrame

    很遗憾,FragmentLayout API 演示没有在方向更改时保留正确的片段状态。无论如何,在考虑过这个问题并尝试了各种事情之后,我不确定是否有一个简单的答案。到目前为止,我想出的最佳答案(未经测试)是在纵向和横向上具有相同的布局,但在 detailsFrame 中有内容时隐藏 menuFrame。同样显示,frameLayout为空时隐藏。

    【讨论】:

      【解决方案3】:

      仅为第一次创建新实例。

      这就是诀窍:
      创建一个新的 Fragment 实例,当 活动首次启动,否则重用旧片段。
      你怎么能做到这一点?
      FragmentManager是关键

      这里是sn-p的代码:

      if(savedInstanceState==null) {
          userFragment = UserNameFragment.newInstance();
          fragmentManager.beginTransaction().add(R.id.profile, userFragment, "TAG").commit();
      }
      else {
          userFragment = fragmentManager.findFragmentByTag("TAG");
      }
      

      在片段端保存数据

      如果您的片段有 EditText、TextViews 或任何其他类变量 改变方向时要保存的。保存 onSaveInstanceState() 并在 onCreateView() 方法中检索它们

      这里是sn-p的代码:

      // Saving State
      
      @Override
      public void onSaveInstanceState(Bundle outState) {
           super.onSaveInstanceState(outState);
           outState.putString("USER_NAME", username.getText().toString());
           outState.putString("PASSWORD", password.getText().toString());
      }
      
      @Override
      public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
      
           View view = inflater.inflate(R.layout.user_name_fragment, parent, false);
      
           username = (EditText) view.findViewById(R.id.username);
           password = (EditText) view.findViewById(R.id.password);
      
      
           // Retriving value
      
           if (savedInstanceState != null) {
               username.setText(savedInstanceState.getString("USER_NAME"));
               password.setText(savedInstanceState.getString("PASSWORD"));
           }
      
           return view;
      }
      

      你可以看到完整的工作代码HERE

      【讨论】:

        猜你喜欢
        • 2010-11-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-11
        • 2018-09-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多