Присвоение фрагментов вкладкам в ActionBar с различной ориентацией
У меня есть 3 фрагмента и активность. Я хочу включить вкладки в ActionBar
и назначить Fragment
каждой из трех вкладок. Как правильно это сделать?
ОРИГИНАЛЬНАЯ ПОЧТА
У меня есть приложение, которое я разрабатываю с помощью приложения ввода-вывода Google в качестве руководства. Я внедрил вкладки в ActionBar
. Кажется, что они работают до изменения ориентации планшета. Например, все 3 вкладки имеют Fragment
. Я могу переключаться между ними очень хорошо, но когда я меняю ориентацию, независимо от того, что Fragment
я последний раз смотрел, видимо, но нажатие на вкладки больше не меняет вид... как будто они отключены. Как и ожидалось, возврат к исходной ориентации не "исправляет" его.
Я изучил состояние сохранения и восстановления, но я не вижу, как это поможет.
EDIT
Уровень модуля
:
Fragment mFragmentA = (Fragment) new AFragmentTab();
Fragment mFragmentB = (Fragment) new BFragmentTab();
Fragment mFragmentC = (Fragment) new CFragmentTab();
У меня есть что-то подобное в активности onCreate
:
ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
actionBar.setDisplayShowTitleEnabled(false);
ActionBar.Tab tabA = actionBar.newTab().setText("text a");
ActionBar.Tab tabB = actionBar.newTab().setText("text b");
ActionBar.Tab tabC = actionBar.newTab().setText("text c");
tabA.setTabListener(this);
tabB.setTabListener(this);
tabC.setTabListener(this);
actionBar.addTab(tabA);
actionBar.addTab(tabB);
actionBar.addTab(tabC);
и a TabListener
следующим образом:
EDIT удалено
class MyTabListener implements ActionBar.TabListener {
private Fragment mFragment;
// Called to create an instance of the listener when adding a new tab
public MyTabListener(Fragment fragment) {
mFragment = fragment;
}
public void onTabSelected(Tab tab, FragmentTransaction ft) {
ft.add(R.id.fragment_content, mFragment, null);
}
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
ft.remove(mFragment);
}
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// do nothing
}
}
ИЗМЕНИТЬ
Я переместил TabListener
. Вместо того, чтобы быть отдельным классом, я реализую TabListener
в Activity
. Затем в методах Selected
и Unselected
у меня есть что-то вроде:
public void onTabSelected(Tab tab, FragmentTransaction ft) {
switch (tab.getPosition()) {
case 0:
ft.add(R.id.fragment_content, mFragmentA, null);
break;
case 1:
ft.add(R.id.fragment_content, mFragmentB, null);
break;
case 2:
ft.add(R.id.fragment_content, mFragmentC, null);
break;
}
}
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
switch (tab.getPosition()) {
case 0:
ft.remove(mFragmentA);
break;
case 1:
ft.remove(mFragmentB);
break;
case 2:
ft.remove(mFragmentC);
break;
}
}
Он по-прежнему делает то же самое. Я действительно не знаю, что происходит.
Ответы
Ответ 1
Похоже, что мой ответ можно найти здесь: http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/app/FragmentTabs.html
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.apis.app;
import com.example.android.apis.R;
import android.app.ActionBar;
import android.app.ActionBar.Tab;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.widget.Toast;
/**
* This demonstrates the use of action bar tabs and how they interact
* with other action bar features.
*/
public class FragmentTabs extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final ActionBar bar = getActionBar();
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
bar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);
bar.addTab(bar.newTab()
.setText("Simple")
.setTabListener(new TabListener<FragmentStack.CountingFragment>(
this, "simple", FragmentStack.CountingFragment.class)));
bar.addTab(bar.newTab()
.setText("Contacts")
.setTabListener(new TabListener<LoaderCursor.CursorLoaderListFragment>(
this, "contacts", LoaderCursor.CursorLoaderListFragment.class)));
bar.addTab(bar.newTab()
.setText("Apps")
.setTabListener(new TabListener<LoaderCustom.AppListFragment>(
this, "apps", LoaderCustom.AppListFragment.class)));
bar.addTab(bar.newTab()
.setText("Throttle")
.setTabListener(new TabListener<LoaderThrottle.ThrottledLoaderListFragment>(
this, "throttle", LoaderThrottle.ThrottledLoaderListFragment.class)));
if (savedInstanceState != null) {
bar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("tab", getActionBar().getSelectedNavigationIndex());
}
public static class TabListener<T extends Fragment> implements ActionBar.TabListener {
private final Activity mActivity;
private final String mTag;
private final Class<T> mClass;
private final Bundle mArgs;
private Fragment mFragment;
public TabListener(Activity activity, String tag, Class<T> clz) {
this(activity, tag, clz, null);
}
public TabListener(Activity activity, String tag, Class<T> clz, Bundle args) {
mActivity = activity;
mTag = tag;
mClass = clz;
mArgs = args;
// Check to see if we already have a fragment for this tab, probably
// from a previously saved state. If so, deactivate it, because our
// initial state is that a tab isn't shown.
mFragment = mActivity.getFragmentManager().findFragmentByTag(mTag);
if (mFragment != null && !mFragment.isDetached()) {
FragmentTransaction ft = mActivity.getFragmentManager().beginTransaction();
ft.hide(mFragment);
ft.commit();
}
}
public void onTabSelected(Tab tab, FragmentTransaction ft) {
if (mFragment == null) {
mFragment = Fragment.instantiate(mActivity, mClass.getName(), mArgs);
ft.add(android.R.id.content, mFragment, mTag);
} else {
ft.show(mFragment);
}
}
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
if (mFragment != null) {
ft.hide(mFragment);
}
}
public void onTabReselected(Tab tab, FragmentTransaction ft) {
Toast.makeText(mActivity, "Reselected!", Toast.LENGTH_SHORT).show();
}
}
}
Ответ 2
Ссылка, предоставленная @Metallicraft, мертва, поэтому вот некоторая помощь тем, кто все еще спотыкается на этот пост. Go здесь для справки по реализации вкладок.
Чтобы просмотреть/прочитать исходный образец, вы можете перейти в следующую папку, если вы установили среду разработки Android: android-sdk\samples\android-14\ApiDemos\src\com\example\android\apis\app\FragmentTabs.java
Кроме того, если у вас возникла проблема с перекрытием фрагментов после изменения ориентации, то это связано с соответствующим образом связанным с savedinstancestate. Вот скопировать копию из google tutorial, которая объясняет проблему перекрытия фрагментов и как ее избежать:
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
public class MainActivity extends FragmentActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.news_articles);
// Check that the activity is using the layout version with
// the fragment_container FrameLayout
if (findViewById(R.id.fragment_container) != null) {
// However, if we're being restored from a previous state,
// then we don't need to do anything and should return or else
// we could end up with overlapping fragments.
if (savedInstanceState != null) {
return;
}
// Create an instance of ExampleFragment
HeadlinesFragment firstFragment = new HeadlinesFragment();
// In case this activity was started with special instructions from an Intent,
// pass the Intent extras to the fragment as arguments
firstFragment.setArguments(getIntent().getExtras());
// Add the fragment to the 'fragment_container' FrameLayout
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, firstFragment).commit();
}
}
}
Ответ 3
Создайте новый проект Android Sample, выберите образец Support4Demos. Здесь вы найдете образец FragmentTabs.
Ответ 4
У меня была более или менее та же проблема, но приведенные выше решения, похоже, не работали в моей ситуации. В конце концов я нашел следующее решение:
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
if (mFragment == null) {
mFragment = Fragment.instantiate(mActivity, mClass.getName());
ft.replace(android.R.id.content, mFragment, mTag); // Use replace iso add
}
else {
ft.attach(mFragment);
}
}
Ответ 5
Это отлично поработало для меня! У меня была эта проблема, когда действия перекрывались каждый раз, когда я менял вкладки:
mFragment = mActivity.getFragmentManager().findFragmentByTag(mTag);
if (mFragment != null && !mFragment.isDetached()) {
FragmentTransaction ft = mActivity.getFragmentManager().beginTransaction();
ft.detach(mFragment);
ft.commit();
Еще раз спасибо!
Ответ 6
@Override
public void onTabSelected(ActionBar.Tab tab, android.support.v4.app.FragmentTransaction fragmentTransaction) {
// Check if the fragment is already initialized
if (mFragment == null) {
// If not, instantiate and add it to the activity
// Toast.makeText(getApplicationContext(),"TAb "+tab.getPosition(),Toast.LENGTH_LONG).show();
if(tab.getPosition() == 1) {
mFragment = new HolderFragment();
fragmentTransaction.add(android.R.id.content, mFragment, mTag);
}
else if(tab.getPosition() == 0)
{
mFragment = new FragmentKnowledge();
fragmentTransaction.add(android.R.id.c`enter code here`ontent, mFragment, mTag);
}
/*else
{
mFragment = Fragment.instantiate(mActivity, mClass.getName());
fragmentTransaction.add(android.R.id.content, mFragment, mTag);
}
*/
} else {
// If it exists, simply attach it in order to show it
fragmentTransaction.attach(mFragment);
}
}