问题描述如下:
我现在有一个TabHost ,装在的页面从左到右依次是Aactivity,Bactivity,Cactivity,Dactivity,Eactivity。 当我指定要跳转到 B, C, D 或者E Aactivity时候,tabHost总是都会先去加载A页面,这并不是我想要的,我想要的是指定哪个页面就去加载哪个页面。
通过查看源代码发现,我们在tabHost.addTab(spec);的时候,源码如下:
/**
* Add a tab.
* @param tabSpec Specifies how to create the indicator and content.
*/
public void addTab(TabSpec tabSpec) {
if (tabSpec.mIndicatorStrategy == null) {
throw new IllegalArgumentException("you must specify a way to create the tab indicator.");
}
if (tabSpec.mContentStrategy == null) {
throw new IllegalArgumentException("you must specify a way to create the tab content");
}
View tabIndicator = tabSpec.mIndicatorStrategy.createIndicatorView();
tabIndicator.setOnKeyListener(mTabKeyListener);
// If this is a custom view, then do not draw the bottom strips for
// the tab indicators.
if (tabSpec.mIndicatorStrategy instanceof ViewIndicatorStrategy) {
mTabWidget.setStripEnabled(false);
}
mTabWidget.addView(tabIndicator);
mTabSpecs.add(tabSpec);
if (mCurrentTab == -1) {
setCurrentTab(0);
}
}
注意查看这段代码
if (mCurrentTab == -1) {
setCurrentTab(0);
}
找到mCurrentTab的定义
protected int mCurrentTab = -1; 默认为-1,所有我们在添加切换卡页面的时候,总是会默认先执行 setCurrentTab(0); 这就是为什么Tabhost总是会先默认加载第一个页面的原因。
找到问题就好办了,我们可以在tabHost.addTab(spec);方法之前,通过反射机制对Tabhost的变量 mCurrentTab进行赋值。
Field mCurrentTab = null;
try {
mCurrentTab = tabHost.getClass()
.getDeclaredField("mCurrentTab");
mCurrentTab.setAccessible(true);
mCurrentTab.setInt(tabHost, -2);
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
mCurrentTab.setInt(tabHost, -2); 我们对mCurrentTab进行赋值只要mCurrent的值不等于-1就行。在我们添加完所有的activity之后。还有一次对mCurrentTab进行赋值操作。否则会报错
try {
if (mtabIndex == 0) {
mCurrentTab.setInt(tabHost, 1);
}
else {
mCurrentTab.setInt(tabHost, 0);
}
}
catch (Exception e){
e.printStackTrace();
}
原因如下;
当我们执行 tabHost.setCurrentTab(mtabIndex); //设置默认显示界面 查看源码如下:
public void setCurrentTab(int index) {
if (index < 0 || index >= mTabSpecs.size()) {
return;
}
if (index == mCurrentTab) {
return;
}
// notify old tab content
if (mCurrentTab != -1) {
mTabSpecs.get(mCurrentTab).mContentStrategy.tabClosed();
}
mCurrentTab = index;
final TabHost.TabSpec spec = mTabSpecs.get(index);
// Call the tab widget's focusCurrentTab(), instead of just
// selecting the tab.
mTabWidget.focusCurrentTab(mCurrentTab);
// tab content
mCurrentView = spec.mContentStrategy.getContentView();
if (mCurrentView.getParent() == null) {
mTabContent
.addView(
mCurrentView,
new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
}
if (!mTabWidget.hasFocus()) {
// if the tab widget didn't take focus (likely because we're in touch mode)
// give the current tab content view a shot
mCurrentView.requestFocus();
}
//mTabContent.requestFocus(View.FOCUS_FORWARD);
invokeOnTabChangeListener();
}
从上面代码中有2个地方我们需要注意的是
if (index == mCurrentTab) {
return;
}
注意 传入的index不能和mCurrentTab值相等,否则直接就return了
// notify old tab content
if (mCurrentTab != -1) {
mTabSpecs.get(mCurrentTab).mContentStrategy.tabClosed();
}
注意红色部分 mCurrentTab不能小于0 并且不能大于等于mTabSpecs 的size() 否则就会数组越界。
这就是为什么会在最后对mCurrentTab进行重新赋值的原因
下面是一个连续代码如下:
Field mCurrentTab = null;
try {
mCurrentTab = tabHost.getClass()
.getDeclaredField("mCurrentTab");
mCurrentTab.setAccessible(true);
mCurrentTab.setInt(tabHost, -2);
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
// tabActivity实施了跳转界面
intent = new Intent().setClass(this, AActivity.class);
spec = tabHost.newTabSpec("A").setIndicator(disCoverTab).setContent(intent);
tabHost.addTab(spec);
intent = new Intent().setClass(this, BActivity.class);
spec = tabHost.newTabSpec("B").setIndicator(experienceTab).setContent(intent);
tabHost.addTab(spec);
intent = new Intent().setClass(this, CActivity.class);
spec = tabHost.newTabSpec("C").setIndicator(homeTab).setContent(intent);
tabHost.addTab(spec);
intent = new Intent().setClass(this, DActivity.class);
spec = tabHost.newTabSpec("D").setIndicator(tab3).setContent(intent);
tabHost.addTab(spec);
intent = new Intent().setClass(this, EActivity.class);
spec = tabHost.newTabSpec("E").setIndicator(tab5).setContent(intent);
tabHost.addTab(spec);
try {
if (mtabIndex == 0) {
mCurrentTab.setInt(tabHost, 1);
}
else {
mCurrentTab.setInt(tabHost, 0);
}
}
catch (Exception e){
e.printStackTrace();
}
tabHost.setCurrentTab(mtabIndex); //设置默认显示界面