問題描述
我在 StackOverflow 中發現了大量此類消息.像其他許多人一樣,我在切換選項卡時也遇到了選項卡內容重疊的問題.我發現的所有建議都不適用于我的問題.
I found a ton of these messages in StackOverflow. Like those many other people, I have the same problem with tab contents overlapping when switching tabs. None of the advises I found didn't work with my problem.
當我的應用啟動時,它會正確顯示第一個選項卡的內容.當我單擊另一個選項卡時,舊的內容會保留在屏幕上,并且另一個選項卡的內容也會添加到屏幕上.第二次切換標簽時,所有內容都消失了.切換標簽不會再做任何事情了.
When my app launches, it correctly shows the contents of the first tab. When I click the other tab, the old contents stay on the screen and the other tab's content is added on the screen, too. When switching tabs second time, all the contents disappear. Switching tabs won't do anyhting anymore.
我在這里關注了 Google 的開發者文檔.
I followed Google's Developer document here.
我的應用程序有這個 onCreate
方法.該類從支持庫 android.support.v7.app
擴展了 ActionBarActivity
.
My application has this onCreate
method.. The class extends ActionBarActivity
from the support libary android.support.v7.app
.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActionBar actionBar = getSupportActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
actionBar.setDisplayShowTitleEnabled(false);
Tab tab = actionBar.newTab().setText("TAB1").setTabListener(new TabListener<Tab1Class>(this, "tab1", Tab1Class.class));
actionBar.addTab(tab);
tab = actionBar.newTab().setText("TAB2").setTabListener(new TabListener<Tab2Class>(this, "tab2", Tab2Class.class));
actionBar.addTab(tab);
}
我的 TabListener
類是從我鏈接的頁面復制而來的:
My TabListener
class is copied from the page I linked:
public class TabListener<T extends Fragment> implements ActionBar.TabListener {
private Fragment mFragment;
private final Activity mActivity;
private final String mTag;
private final Class<T> mClass;
public TabListener(Activity activity, String tag, Class<T> clz) {
mActivity = activity;
mTag = tag;
mClass = clz;
}
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
if(mFragment == null) {
mFragment = Fragment.instantiate(mActivity, mClass.getName());
ft.add(android.R.id.content, mFragment, mTag);
} else {
ft.attach(mFragment);
}
}
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
if(mFragment != null) {
ft.detach(mFragment);
}
}
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {}
}
我用作選項卡內容的兩個類都從 android.support.v4.app.Fragment
擴展了 Fragment.他們在 onCreateView
方法中擴充他們的布局.
Both classes I use as the contents of the tabs extend Fragment from android.support.v4.app.Fragment
. They inflate their layouts in onCreateView
methods.
怎么了?
推薦答案
怎么了?
在快速瀏覽了 ActionBarActivity
的代碼后,ICS
和 ActionBar<實現的上述部分似乎存在錯誤/code>(代碼應該適用于
ICS
之前的設備),它還負責處理選項卡.
After a quick look through the code for the ActionBarActivity
, there seems to be a bug for the ICS
and above part of the implementation of the ActionBar
(the code should work for pre ICS
devices) which also takes care of the tabs.
在代表 ICS
設備實現的 ActionBarImplICS
類中,似乎 FragmentTransaction
傳遞給了 onTabUnselected()
回調是完全沒用的,因為它不會在偵聽器的回調返回后的任何地方提交(事務已提交給 TabListener
的其他兩個回調).因此,提交的片段將永遠不會從選項卡選擇上的布局中分離出來,并且它將保持重疊內容(由于 FrameLayout
包含兩個片段).
In the ActionBarImplICS
class which represents the implementation for ICS
devices it seems the FragmentTransaction
passed to the onTabUnselected()
callback is completely useless as it isn't committed anywhere after the listener's callback returns(the transaction is committed for the other two callbacks of the TabListener
). So a committed fragment will never be detached from the layout on a tab selection and it will stay getting the overlapping content(due to the FrameLayout
which holds both fragments).
我已經編寫了 TabListener
接口的另一個實現,它只通過一個不受上述錯誤影響的回調來完成所有工作(onTabSelected()代碼>):
I've written another implementation of the TabListener
interface which does all of its job from only one of the callbacks which isn't affected by the above bug(onTabSelected()
):
public class TabListenerImpl implements ActionBar.TabListener {
private List<TabInfo> mTabs = new ArrayList<TabInfo>();
private Context mContext;
public TabListenerImpl(Context context) {
mContext = context;
}
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
// iterate over all of the tabs, match the tag we have and see if
// we also have a fragment instance for it. If we don't, create one
// and add it to the container, if we have an instance simply attach
// it. Detach every other tag which doesn't match the tag.
for (TabInfo t : mTabs) {
if (tab.getTag() == t.tag) {
if (t.pageFragment == null) {
t.pageFragment = Fragment.instantiate(mContext,
t.clazz.getName());
ft.add(android.R.id.content, t.pageFragment, t.tag);
} else {
ft.attach(t.pageFragment);
}
} else {
if (t.pageFragment != null && !t.pageFragment.isDetached()) {
ft.detach(t.pageFragment);
}
}
}
}
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
// faulty method
}
/**
* Call this method BEFORE you call the actionBar.addTab() method!
*
* @param tag
* a String representing the tag that was set on the tab to
* identify itself
* @param clazz
* the class of the Fragment
*/
public void addTab(String tag, Class<? extends Fragment> clazz) {
TabInfo ti = new TabInfo();
ti.clazz = clazz;
ti.tag = tag;
mTabs.add(ti);
}
// wrapper class
private class TabInfo {
Class<? extends Fragment> clazz;
Fragment pageFragment;
String tag;
}
}
然后你可以用作:
TabListenerImpl listener = new TabListenerImpl(this);
Tab tab = actionBar.newTab().setText("TAB1").setTag("TAB1").setTabListener(listener);
listener.addTab("TAB1", Tab1Class.class);
actionBar.addTab(tab);
tab = actionBar.newTab().setText("TAB2").setTag("TAB2").setTabListener(listener);
listener.addTab("TAB2", Tab2Class.class);
actionBar.addTab(tab);
我建議您將容器設置為內容視圖(以及選項卡內容),而不是使用 android.R.id.content
容器.請記住,我的實現不負責配置更改.
I would advise you to set a container as the content view(and also for the tab content) and not use the android.R.id.content
container. Keep in mind that my implementation doesn't take care of configuration changes.
這篇關于ActionBar 選項卡內容重疊的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!