我正在尝试修改HoneyCombGallery示例代码,以便在更改选项卡时更改显示的视图。在Google提供的示例中,切换标签时显示的片段始终相同。仅显示的数据发生变化。但是,我想要做的是更改标签更改时显示的片段和类。
以下是我在HoneyCombGallery示例中修改过的代码:(MainActivity.java)
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
int nTabSelected = tab.getPosition();
switch (nTabSelected) {
case 0:
setContentView(R.layout.settings_fragment);
break;
case 1:
setContentView(R.layout.main);
break;
}
其他一切都差不多。 (另请注意,如前所述,MainActivity.onCreate调用setContentView(R.layout.main) - 我没有听说过多次调用setContentView是不允许的。我打算在每个标签中单击这样做)
这是在代码中膨胀的布局(settings_fragment.xml)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/frags2">
<fragment class="com.example.android.hcgallery.SettingsFragment"
android:id="@+id/settings_fragment2"
android:visibility="gone"
android:layout_marginTop="?android:attr/actionBarSize"
android:layout_width="@dimen/titles_size"
android:layout_height="match_parent" />
</LinearLayout>
“settings fragment”是我的类,它扩展了Fragment:(SettingsFragment.java)
public class SettingsFragment extends Fragment {
private View v;
@Override
public View onCreateView(final LayoutInflater inflater,
final ViewGroup container, final Bundle savedInstanceState) {
if (v != null)
return v;
v = inflater.inflate(R.layout.settings_layout, container, false);
return v;
}
}
xml也非常简单(settings_layout.xml):
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/settings_layout" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingTop="10dip">
<TextView android:text="1.0.0" android:id="@+id/tv_version2"
android:layout_marginTop="?android:attr/actionBarSize"
android:textSize="15dp" android:textStyle="bold" android:typeface="sans"
android:layout_height="wrap_content" android:layout_width="200dp"
android:paddingTop="10dip" android:gravity="right" >
</TextView>
</RelativeLayout>
这似乎很简单,当应用程序启动时,settings_fragment可见,因为默认选择了第0个选项卡。当我们选择下一个选项卡时,我希望执行setContentView(R.layout.main),我将看到主要布局(这与Google示例中的相同:无修改)。但是,我得到的是这个例外:
12-15 16:49:28.501: ERROR/AndroidRuntime(31485): FATAL EXCEPTION: main
12-15 16:49:28.501: ERROR/AndroidRuntime(31485): android.view.InflateException: Binary XML file line #23: Error inflating class fragment
12-15 16:49:28.501: ERROR/AndroidRuntime(31485): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:688)
12-15 16:49:28.501: ERROR/AndroidRuntime(31485): at android.view.LayoutInflater.rInflate(LayoutInflater.java:724)
12-15 16:49:28.501: ERROR/AndroidRuntime(31485): at android.view.LayoutInflater.inflate(LayoutInflater.java:479)
12-15 16:49:28.501: ERROR/AndroidRuntime(31485): at android.view.LayoutInflater.inflate(LayoutInflater.java:391)
12-15 16:49:28.501: ERROR/AndroidRuntime(31485): at android.view.LayoutInflater.inflate(LayoutInflater.java:347)
12-15 16:49:28.501: ERROR/AndroidRuntime(31485): at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:224)
12-15 16:49:28.501: ERROR/AndroidRuntime(31485): at android.app.Activity.setContentView(Activity.java:1777)
12-15 16:49:28.501: ERROR/AndroidRuntime(31485): at com.example.android.hcgallery.MainActivity.onTabSelected(MainActivity.java:109)
12-15 16:49:28.501: ERROR/AndroidRuntime(31485): at com.android.internal.app.ActionBarImpl.selectTab(ActionBarImpl.java:462)
12-15 16:49:28.501: ERROR/AndroidRuntime(31485): at com.android.internal.app.ActionBarImpl$TabImpl.select(ActionBarImpl.java:787)
12-15 16:49:28.501: ERROR/AndroidRuntime(31485): at com.android.internal.widget.ActionBarView$TabClickListener.onClick(ActionBarView.java:950)
12-15 16:49:28.501: ERROR/AndroidRuntime(31485): at android.view.View.performClick(View.java:3100)
12-15 16:49:28.501: ERROR/AndroidRuntime(31485): at android.view.View$PerformClick.run(View.java:11644)
12-15 16:49:28.501: ERROR/AndroidRuntime(31485): at android.os.Handler.handleCallback(Handler.java:587)
12-15 16:49:28.501: ERROR/AndroidRuntime(31485): at android.os.Handler.dispatchMessage(Handler.java:92)
12-15 16:49:28.501: ERROR/AndroidRuntime(31485): at android.os.Looper.loop(Looper.java:126)
12-15 16:49:28.501: ERROR/AndroidRuntime(31485): at android.app.ActivityThread.main(ActivityThread.java:3997)
12-15 16:49:28.501: ERROR/AndroidRuntime(31485): at java.lang.reflect.Method.invokeNative(Native Method)
12-15 16:49:28.501: ERROR/AndroidRuntime(31485): at java.lang.reflect.Method.invoke(Method.java:491)
12-15 16:49:28.501: ERROR/AndroidRuntime(31485): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
12-15 16:49:28.501: ERROR/AndroidRuntime(31485): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
12-15 16:49:28.501: ERROR/AndroidRuntime(31485): at dalvik.system.NativeStart.main(Native Method)
12-15 16:49:28.501: ERROR/AndroidRuntime(31485): Caused by: java.lang.IllegalArgumentException: Binary XML file line #23: Duplicate id 0x7f09000a, tag null, or parent id 0x7f090009 with another fragment for com.example.android.hcgallery.TitlesFragment
12-15 16:49:28.501: ERROR/AndroidRuntime(31485): at android.app.Activity.onCreateView(Activity.java:4095)
12-15 16:49:28.501: ERROR/AndroidRuntime(31485): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:664)
12-15 16:49:28.501: ERROR/AndroidRuntime(31485): ... 21 more
错误似乎是“android.view.InflateException:二进制XML文件行#23:错误膨胀类片段”
这是什么意思?当选择不同的标签时,我可以不按照我的意愿更改片段和布局吗? 如果这不是为不同标签设置不同布局的正确方法,那么正确的方法是什么?
我已将整个源代码压缩上传到HoneycombGallery_Modified.zip - https://docs.google.com/open?id=0B0FHtQOpOYx6YWFiMDcxYmEtOGFkMy00NWU2LTk2MzMtZWY0YzdmZWUzMDU0(如果您要下载整个zip文件,请点击“文件 - &gt;下载原件”)
答案 0 :(得分:3)
我成功地实现了你所需要的。
我的情况:我有一个带有多个标签的操作栏,这些标签需要不同的布局才能正常显示。 我也使用ActionBarSherlock来实现向后兼容,但我认为原始类可以使用相同的原则。
我有2种标签:
这是我的方式,我有一个名为ActionBarActivity的类,它初始化选项卡并包含TabListener。
这是我的ActionBarActivity:
public class ActionBarActivity
extends SherlockFragmentActivity
{
/**
* The current layoutId on the screen
*/
private int layoutId;
protected final int LAYOUT_LIST = R.layout.list_container;
protected final int LAYOUT_WEBVIEW = R.layout.webview_container;
@Override
public void onCreate( Bundle savedInstanceState )
{
super.onCreate( savedInstanceState );
ActionBar actionBar = getSupportActionBar();
actionBar.setNavigationMode( ActionBar.NAVIGATION_MODE_TABS );
getSupportActionBar().removeAllTabs();
// we pass the layout to use for each tab
addTab("Tab 1", LAYOUT_LIST, ListFragment.class);
addTab("Tab 2", LAYOUT_WEBVIEW, WebViewFragment.class);
// in case of screen orientation
if ( savedInstanceState != null ) {
actionBar.setSelectedNavigationItem( savedInstanceState.getInt( "tab", 0 ) );
}
// initial setting of the content
updateContentView( actionBar.getSelectedTab() );
}
private void addTab( String title, int contentLayoutId, Class<? extends Fragment> tabClass )
{
Tab t = getSupportActionBar().newTab();
t.setText( tabTitle );
t.setTag( contentLayoutId );
t.setTabListener( new TabListener( this, tabTitle, activity, null ) );
getSupportActionBar().addTab( t );
}
// that's how I deal to replace the layout used to display the tab's content
protected void updateContentView( Tab t )
{
FragmentManager fgtManager = getSupportFragmentManager();
int tabLayoutId = ( Integer ) t.getTag();
if ( tabLayoutId == LAYOUT_WEBVIEW ) {
Fragment details = fgtManager.findFragmentById( R.id.detail_fragment);
if(details != null && details.isInLayout()){
FragmentTransaction transact = fgtManager.beginTransaction();
transact.remove( details );
transact.commit();
details = null;
}
}
if ( this.layoutId != tabLayoutId ) {
layoutId = tabLayoutId;
setContentView( layoutId );
}
}
@Override
protected void onSaveInstanceState( Bundle outState )
{
super.onSaveInstanceState( outState );
outState.putInt( "tab", getSupportActionBar().getSelectedNavigationIndex() );
}
// see APIDemos.app.FragmentTabs for more details
public static class TabListener
implements ActionBar.TabListener
{
private SherlockFragmentActivity mActivity;
public void onTabSelected( Tab tab, FragmentTransaction ft )
{
// When we select a tab we udpate the content of the ActionBarActivity
((ActionBarActivity)mActivity).updateContentView( tab );
mFragment = mActivity.getSupportFragmentManager().findFragmentByTag( mTag );
if ( mFragment == null ) {
mFragment = Fragment.instantiate( mActivity, mClass.getName(), mArgs );
ft.add( R.id.content_fragment, mFragment, mTag );
} else {
ft.attach( mFragment );
}
}
}
}
我的两个布局:
布局/ list_container.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="0.6"
android:id="@+id/content_fragment"/>
<fragment
android:id="@+id/detail_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="0.4"
class="my.webview.WebViewFragment">
</fragment>
</LinearLayout>
布局/ webview_container.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:id="@+id/content_fragment"/>
</LinearLayout>
PS:这是我的第一个贡献,所以我很高兴有一些批评者。
PPS:我是法国人,所以我可能忘记了一些英语错误,对不起。
答案 1 :(得分:1)
答案 2 :(得分:0)
我认为你不应该再次设置内容,它只能设置一次。 使用fragmentTransaction.replace()
将适当的片段设置到片段容器中