4

我有一个使用片段和 ActionBarSherlock 构建的选项卡式应用程序。我有 7 个标签。这是正在发生的事情。

当我选择任何选项卡时,将按预期调用关联片段的 onCreate 方法。问题是下一个相邻选项卡也会调用 onCreate 方法。例如:

  1. 应用程序在 tab1 中启动并按预期调用 onCreate
  2. tab2 onCreate 也被调用(不应该发生)
  3. --------
  4. 单击 tab2 并按预期调用 onCreate(即使它已经被调用)
  5. tab3 onCreate 也被调用(不应该发生)
  6. --------
  7. 点击tab6,按预期调用onCreate
  8. tab7 onCreate 也被调用(不应该发生)
  9. --------
  10. 真的很奇怪,点击tab7(最后一个标签)
  11. tab6 (倒数第二个标签) onCreate 也被调用(不应该发生)

我已经阅读了几个可能的问题并检查以确保它没有在这里发生:

  1. 不为每个选项卡使用唯一标签(它们是唯一的)
  2. 模拟器有两次调用 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;
       }
    }
}
}
4

4 回答 4

4

标签计数将从 0 开始,因此在 viewPager 中您必须设置屏幕限制,如下所示

例如,如果您有 3 个选项卡,只需给出

viewPager.setOffscreenPageLimit(2);

于 2015-12-11T16:13:20.543 回答
2

那是标签的属性之一。它会加载第二个,因此您不会滑动到空选项卡。如果您愿意,欢迎您覆盖选项卡类并自己处理:D。

于 2014-02-26T18:09:12.413 回答
0

你说

onCreate 也被调用(不应该发生)

但这正是使用 ViewPager 时应该发生的情况。如果您在第一个和第二个选项卡之间滑动一半,您还能如何看到该片段?

如果您点击选项卡 2,它可能会被重新创建,因为它已被破坏。尝试像这样覆盖 getItemPosition:

    @Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }
于 2012-03-08T20:41:57.770 回答
0

如果您使用片段,请考虑使用 ViewPager。它更容易实施并且响应速度更快。

这里的例子, http://android-developers.blogspot.com/2011/08/horizo​​ntal-view-swiping-with-viewpager.html

于 2012-03-08T00:03:11.130 回答