我有一个使用片段和 ActionBarSherlock 构建的选项卡式应用程序。我有 7 个标签。这是正在发生的事情。
当我选择任何选项卡时,将按预期调用关联片段的 onCreate 方法。问题是下一个相邻选项卡也会调用 onCreate 方法。例如:
- 应用程序在 tab1 中启动并按预期调用 onCreate
- tab2 onCreate 也被调用(不应该发生)
- --------
- 单击 tab2 并按预期调用 onCreate(即使它已经被调用)
- tab3 onCreate 也被调用(不应该发生)
- --------
- 点击tab6,按预期调用onCreate
- tab7 onCreate 也被调用(不应该发生)
- --------
- 真的很奇怪,点击tab7(最后一个标签)
- tab6 (倒数第二个标签) onCreate 也被调用(不应该发生)
我已经阅读了几个可能的问题并检查以确保它没有在这里发生:
- 不为每个选项卡使用唯一标签(它们是唯一的)
- 模拟器有两次调用 onCreate 的错误(我的 ICS 设备上的行为相同)
所以这不是前两种可能性,我完全没有想法。该程序运行良好,但加载两个片段(它们是 web 视图)需要太多时间,这不是我预期的行为。
这是我创建选项卡主机的主要活动 onCreate 的代码:已 编辑:
public class SynergyWorldwideActivity extends SherlockFragmentActivity
{
//TabHost mTabHost;
ViewPager mViewPager;
TabsAdapter mTabsAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set up the view pager
setContentView(R.layout.fragment_tabs_pager);
mViewPager = (ViewPager)findViewById(R.id.pager);
// Set up action bar
final ActionBar bar = getSupportActionBar();
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
bar.setDisplayShowTitleEnabled(true);
//bar.setDisplayShowHomeEnabled(false);
// Creat tabs with bundled URLs
Bundle tab1Args=new Bundle(), tab2Args=new Bundle(), tab3Args=new Bundle(),
tab4Args=new Bundle(), tab5Args=new Bundle(), tab6Args=new Bundle(), tab7Args=new Bundle();
tab1Args.putString("tabURL", getString(R.string.webtab1_URL));
tab2Args.putString("tabURL", getString(R.string.webtab2_URL));
tab3Args.putString("tabURL", getString(R.string.webtab3_URL));
tab4Args.putString("tabURL", getString(R.string.webtab4_URL));
tab5Args.putString("tabURL", getString(R.string.webtab5_URL));
tab6Args.putString("tabURL", getString(R.string.webtab6_URL));
tab7Args.putString("tabURL", getString(R.string.webtab7_URL));
mTabsAdapter = new TabsAdapter(this, mViewPager);
mTabsAdapter.addTab(bar.newTab().setText(getString(R.string.webtab1_name)),
WebTabFragment.MyWebviewFragment.class, tab1Args);
mTabsAdapter.addTab(bar.newTab().setText(getString(R.string.webtab2_name)),
WebTabFragment.MyWebviewFragment.class, tab2Args);
mTabsAdapter.addTab(bar.newTab().setText(getString(R.string.webtab3_name)),
WebTabFragment.MyWebviewFragment.class, tab3Args);
mTabsAdapter.addTab(bar.newTab().setText(getString(R.string.webtab4_name)),
WebTabFragment.MyWebviewFragment.class, tab4Args);
mTabsAdapter.addTab(bar.newTab().setText(getString(R.string.webtab5_name)),
WebTabFragment.MyWebviewFragment.class, tab5Args);
mTabsAdapter.addTab(bar.newTab().setText(getString(R.string.webtab6_name)),
WebTabFragment.MyWebviewFragment.class, tab6Args);
mTabsAdapter.addTab(bar.newTab().setText(getString(R.string.webtab7_name)),
WebTabFragment.MyWebviewFragment.class, tab7Args);
if (savedInstanceState != null) {
bar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("tab", getActionBar().getSelectedNavigationIndex());
}
/**
* This is a helper class that implements the management of tabs and all
* details of connecting a ViewPager with associated TabHost. It relies on a
* trick. Normally a tab host has a simple API for supplying a View or
* Intent that each tab will show. This is not sufficient for switching
* between pages. So instead we make the content part of the tab host
* 0dp high (it is not shown) and the TabsAdapter supplies its own dummy
* view to show as the tab content. It listens to changes in tabs, and takes
* care of switch to the correct paged in the ViewPager whenever the selected
* tab changes.
*/
public static class TabsAdapter extends FragmentPagerAdapter implements ActionBar.TabListener, ViewPager.OnPageChangeListener{
private final Context mContext;
//private final TabHost mTabHost;
private final ActionBar mActionBar;
private final ViewPager mViewPager;
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
static final class TabInfo {
private final Class<?> clss;
private final Bundle args;
TabInfo(Class<?> _class, Bundle _args) {
clss = _class;
args = _args;
}
}
public TabsAdapter(FragmentActivity activity, ViewPager pager) {
super(activity.getSupportFragmentManager());
mContext = activity;
mActionBar = ((SherlockFragmentActivity) activity).getSupportActionBar();
mViewPager = pager;
mViewPager.setAdapter(this);
mViewPager.setOnPageChangeListener(this);
}
public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) {
TabInfo info = new TabInfo(clss, args);
tab.setTag(info);
tab.setTabListener(this);
mTabs.add(info);
mActionBar.addTab(tab);
notifyDataSetChanged();
}
@Override
public int getCount()
{
int iCount = mTabs.size();
return iCount;
}
@Override
public Fragment getItem(int position)
{
TabInfo info = mTabs.get(position);
return Fragment.instantiate(mContext, info.clss.getName(), info.args);
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
{
}
@Override
public void onPageSelected(int position)
{
mActionBar.setSelectedNavigationItem(position);
}
@Override
public void onPageScrollStateChanged(int state)
{
}
@Override
public void onTabSelected(Tab tab)
{
Object tag = tab.getTag();
for (int i=0; i<mTabs.size(); i++) {
if (mTabs.get(i) == tag) {
mViewPager.setCurrentItem(i);
}
}
}
@Override
public void onTabUnselected(Tab tab)
{
}
@Override
public void onTabReselected(Tab tab)
{
}
}
}
这是选项卡片段的代码:已 编辑:
public class WebTabFragment extends SherlockFragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState == null)
{
FragmentManager fm = getSupportFragmentManager();
if (fm.findFragmentById(android.R.id.content) == null) {
MyWebviewFragment myWebView = new MyWebviewFragment();
fm.beginTransaction().add(android.R.id.content, myWebView).commit();
}
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
//outState.putString("tabNumber", mTabNumber);
}
public static class MyWebviewFragment extends SherlockFragment {
final static private String tag = MyWebviewFragment.class.getSimpleName();
String mTabURL;
private WebView mWebView = null;
static final int REFRESH_ID = Menu.FIRST;
private ProgressDialog spinnerDlg;
@Override
public void onSaveInstanceState(Bundle outState)
{
if(mWebView.saveState(outState) == null)
Log.i(tag,"Saving state FAILED!");
else
Log.i(tag, "Saving state succeeded.");
}
@Override
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
setHasOptionsMenu(true);
}
@Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.add(Menu.NONE, REFRESH_ID, 0, getString(R.string.refresh_string))
.setIcon(R.drawable.ic_action_refresh)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
}
@Override public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case REFRESH_ID:
if(mWebView != null)
mWebView.reload();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
/**
* When creating, retrieve this instance's number from its arguments.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Tell the framework to try to keep this fragment around
// during a configuration change.
setRetainInstance(true);
mTabURL = getArguments() != null ? getArguments().getString("tabURL") : "http://www.google.com";
}
/**
* The Fragment's UI is just a simple text view showing its
* instance number.
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Create view object to return
View v = inflater.inflate(R.layout.webview_layout, container, false);
// Set up webview object
if (mWebView != null) {
mWebView.destroy();
}
mWebView = (WebView)v.findViewById(R.id.webview_fragment);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.setOnKeyListener(new OnKeyListener(){
@Override
public boolean onKey(View v, int keyCode, KeyEvent event)
{
if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {
mWebView.goBack();
return true;
}
return false;
}
});
// Check to see if it has been saved and restore it if true
if(savedInstanceState != null)
{
if (savedInstanceState.isEmpty())
Log.i(tag, "Can't restore state because bundle is empty.");
else
{
if (mWebView.restoreState(savedInstanceState) == null)
Log.i(tag, "Restoring state FAILED!");
else
Log.i(tag, "Restoring state succeeded.");
}
}
else
{
// Load web page
mWebView.setWebViewClient(new MyWebViewClient());
mWebView.getSettings().setPluginsEnabled(true);
mWebView.getSettings().setBuiltInZoomControls(false);
mWebView.getSettings().setSupportZoom(false);
mWebView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
mWebView.getSettings().setAllowFileAccess(true);
mWebView.getSettings().setDomStorageEnabled(true);
mWebView.loadUrl(mTabURL);
}
return v;
}
@Override
public void onDestroy()
{
super.onDestroy();
}
@Override
public void onDestroyView()
{
super.onDestroyView();
}
@Override
public void onPause()
{
super.onPause();
}
@Override
public void onResume()
{
super.onResume();
}
@Override
public void onConfigurationChanged(Configuration newConfig)
{
// TODO Auto-generated method stub
super.onConfigurationChanged(newConfig);
}
public class MyWebViewClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// YouTube video link
if (url.startsWith("http://youtu.be"))
{
String urlSubString = url.substring("http://youtu.be/".length());
String newURL = String.format("http://www.youtube.com/v/%s", urlSubString);
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(newURL)));
return (true);
}
return (false);
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
if(spinnerDlg == null)
{
spinnerDlg = new ProgressDialog(getActivity());
spinnerDlg.setMessage("Loading....");
spinnerDlg.show();
}
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
if(spinnerDlg != null)
{
spinnerDlg.dismiss();
}
spinnerDlg = null;
}
}
}
}