片段在旋转时是否可以从对话框切换到嵌入式?

问题描述:

所以,我有一个搜索标准片段,可以输入搜索条件,并且执行搜索时,搜索结果显示在搜索结果片段中。在平板电脑的横向上,这两个片段自然可以并排显示。到目前为止,这很简单。片段在旋转时是否可以从对话框切换到嵌入式?

在纵向和手机上,我希望搜索条件片段显示为弹出式对话框而不是搜索结果。在DialogFragment的Selecting Between Dialog or Embedding部分,我看到我可以嵌入片段,或将其显示为对话框。如果方向改变并不复杂,这可能适用于我。

如果我在活动的布局中使用< fragment> XML标记,当我进行方向更改时,会遇到各种麻烦。

编辑:今天我决定尝试,看看我是否可以得到一个简单的工作流程使用DialogFragment切换显示对话框和嵌入取决于设备的方向之间切换。事实证明这是相当困难的,我仍然没有找到有效的东西。这是迄今为止我所拥有的。

package org.nsdev.experiments; 

import android.os.Bundle; 
import android.support.v4.app.DialogFragment; 
import android.support.v4.app.FragmentActivity; 
import android.view.Menu; 
import android.view.MenuItem; 
import android.view.View; 

public class FragmentSearchTestActivity extends FragmentActivity 
{ 
    private static SearchCriteriaFragment searchCriteriaFragment; 

    @Override 
    public void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     View container = findViewById(R.id.search_criteria_container); 

     android.support.v4.app.FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); 

     if (searchCriteriaFragment == null) 
     { 
      searchCriteriaFragment = SearchCriteriaFragment.newInstance(); 
      searchCriteriaFragment.setStyle(DialogFragment.STYLE_NO_TITLE, 0); 
     } 

     android.support.v4.app.Fragment f = getSupportFragmentManager().findFragmentByTag("search_criteria"); 
     if (f != null) 
     { 
      ft.remove(f); 
     } 

     if (container == null) 
     { 
      searchCriteriaFragment.setCancelable(true); 
      searchCriteriaFragment.setHasOptionsMenu(false); 
      searchCriteriaFragment.show(getSupportFragmentManager(), "search_criteria"); 
     } 
     else 
     { 
      ft.remove(searchCriteriaFragment); 
      ft.add(R.id.search_criteria_container, searchCriteriaFragment, "search_criteria"); 
      ft.commit(); 
     } 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) 
    { 
     getMenuInflater().inflate(R.menu.main_menu, menu); 
     return super.onCreateOptionsMenu(menu); 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) 
    { 
     if (item.getItemId() == R.id.menu_item_search) 
     { 
      searchCriteriaFragment.show(getSupportFragmentManager(), "search_criteria"); 
     } 
     return super.onOptionsItemSelected(item); 
    } 
} 

具体我无法得到任何工作,除非我不停的SearchCriteriaFragment的静态副本,并重新使用它时的onCreate在活动被调用。这对我来说似乎是非常错误的。

SearchResultsFragment.java:

package org.nsdev.experiments; 

import android.os.Bundle; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 

public class SearchResultsFragment extends android.support.v4.app.Fragment 
{ 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
    { 
     return inflater.inflate(R.layout.results, container); 
    } 

} 

SearchCriteriaFragment.java:

package org.nsdev.experiments; 

import android.os.Bundle; 
import android.util.Log; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 

public class SearchCriteriaFragment extends android.support.v4.app.DialogFragment 
{ 

    private static final String TAG = "SearchCriteriaFragment"; 
    View v; 

    static SearchCriteriaFragment newInstance() 
    { 
     Log.e(TAG, "newInstance"); 
     SearchCriteriaFragment d = new SearchCriteriaFragment(); 
     return d; 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
    { 
     if (v == null) 
     { 
      v = inflater.inflate(R.layout.criteria, container, false); 
     } 
     else 
     { 
      if (v.getParent() instanceof ViewGroup) 
      { 
       Log.e(TAG, "Removing from viewgroup"); 
       ((ViewGroup)v.getParent()).removeAllViews(); 
      } 
     } 

     return v; 
    } 

} 

你可以看到,在这里,我不得不解决一个问题的观点被重复使用。有一个错误,说明该视图已经有了一个父项,并且在它被添加到另一个父项之前需要将其从中删除。再次,这似乎是我必须以错误的方式来做。

RES /布局/ main.xml中:

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" > 

    <fragment 
     android:id="@+id/search_results" 
     android:name="org.nsdev.experiments.SearchResultsFragment" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" /> 

</RelativeLayout> 

RES /布局,土地/ main.xml中:

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" > 

    <FrameLayout 
     android:id="@+id/search_criteria_container" 
     android:layout_width="wrap_content" 
     android:layout_height="fill_parent" /> 

    <fragment 
     android:id="@+id/search_results" 
     android:layout_toRightOf="@+id/search_criteria_container" 
     android:name="org.nsdev.experiments.SearchResultsFragment" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" /> 

</RelativeLayout> 

可以从以下两个布局看,我试图做的。在正常的方向上,FrameLayout不存在,所以我们可以检测到它并显示DialogFragment。否则,我们可以将DialogFragment嵌入到FrameLayout中。

最后两个布局,我只是把占位符的结果和标准布局:

RES /布局/ criteria.xml:

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" android:background="#300F"> 

    <CheckBox 
     android:id="@+id/checkBox" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignParentLeft="true" 
     android:layout_alignParentTop="true" 
     android:layout_marginLeft="21dp" 
     android:paddingRight="30dp" 
     android:text="Test Criteria" /> 

</RelativeLayout> 

RES /布局/ results.xml:

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" android:background="#f00"> 

    <TextView 
     android:id="@+id/textView1" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignParentLeft="true" 
     android:layout_alignParentTop="true" 
     android:layout_marginLeft="16dp" 
     android:layout_marginTop="16dp" 
     android:text="Results" 
     android:textAppearance="?android:attr/textAppearanceLarge" /> 

</RelativeLayout> 

我想我已经想通了,直到我开始旋转设备和检查的ICS设备上的复选框。请注意,我已将颜色设置为针对criteria.xml RelativeLayout背景的半透明。我注意到的是,在横向,嵌入视图实际上是保留旧版本的视图的左右,而这些将与每次我切换到肖像,然后再返回视图的新副本覆盖。这是我试图保留从SeachCriteriaFragment的onCreateView返回的视图的一个副本的原因之一。这不能解决这个问题。

我只能得出一个结论:我必须这样做不对。我怀疑Fragments框架从来没有被设计用来做这种片段重用。我怎样才能得到一个不错的旋转工作在哪里在肖像我显示DialogFragment作为一个对话框,并在景观它嵌入?我可以让框架更自动地做这样的事吗?

我试着设置searchCriteriaFragment.setRetainInstance(真)和全乱套了,所以我立即删除该行。

谢谢你把我在这里在正确的轨道上的任何帮助。

+0

我觉得有可能是一些关于你的configChanges属性或可能会造成您的片段消失旋转活动代码。我认为你会尽可能地分享尽可能多的代码。 – nmr 2012-02-11 02:03:14

我会说这个。

在手机上做SearchFormFragment的活动,并给它的主题对话。 然后SearchResultsFragment也是它自己的独立活动。

的SearchForm XML看起来像:

<LinearLayout > 
    <fragment class="com.your.package.ui.fragment.SearchFormFragment" /> 
</LinearLayout> 

要获得Dialog theme

<manifest . . . > 
     <application . . . > 
     <activity 
      android:name=".ui.phone.SearchFormFragmentActivity" 
      android:theme="@android:style/Theme.Dialog" . . . > 
     <activity 
      android:name=".ui.phone.SearchResultsFragmentActivity" . . . > 

这使得使用onSaveInstanceStateonRestoreInstanceState和活动周期方向改变的简单。

然后在平板电脑上,你有你的两个片段另一个活动

  <activity 
      android:name=".ui.tablet.SearchFragmentActivity" . . . > 

SearchFragmentActivity.xml:

<LinearLayout > 
    <fragment class="com.your.pacakage.ui.fragment.SearchFormFragment"/> 
    <fragment class="com.your.package.ui.fragment.SearchResultsFragment" /> 
    </LinearLayout> 

简化。

+0

理想我想使用Android兼容性库,并实际用于片段的UI元素。 – Thorinside 2012-02-11 00:33:39

+0

那正是我的意思吗?编辑片段XML把它清除掉(它只是pseado反正) – Blundell 2012-02-11 00:36:00

+0

但我想知道如何使管理两个片段适当的,而不是三个活动一个活动。 – Thorinside 2012-02-11 00:36:51