因此,我有一个搜索条件片段,可以输入搜索条件,并且在执行搜索时,搜索结果显示在搜索结果片段中。在平板电脑的风景中,两个片段自然可以并排显示。到目前为止,这很容易实现。
在纵向和手机上,我希望搜索条件片段显示为弹出对话框,而不是搜索结果旁边。在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的静态副本并在Activity中调用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框架从未被设计用于执行这种片段重用。如何在Portrait中显示一个很好的旋转工作,我将DialogFragment显示为对话框,而在Landscape中它是嵌入式的?我可以让框架更自动地执行此类操作吗?
我尝试设置searchCriteriaFragment.setRetainInstance(true)并且所有地狱都崩溃了,所以我立即删除了该行。
感谢您帮助我走上正确的道路。
答案 0 :(得分:0)
我会说这个。
在手机上将SearchFormFragment设为Activity,并为其指定主题Dialog。 然后,SearchResultsFragment也是一个单独的Activity。
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" . . . >
这可以使用onSaveInstanceState
和onRestoreInstanceState
以及活动生命周期简化方向更改。
然后在平板电脑上,你有另外两个片段的活动。
<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>
简化。