【问题标题】:implementing tabs with simple views and fragments使用简单的视图和片段实现选项卡
【发布时间】:2013-07-24 01:01:54
【问题描述】:

在与实现 TabActivity 和 Fragments 和 viewPager 等标签的常用方法进行了一周的斗争后,我未能获得活动实例或标签片段,并且找不到解决问题的方法。所以我决定以不同的方式实现它。首先,我用一个简单的按钮制作了一个 tabWidget。在 android 开发者网站中,我找到了一种在运行时替换片段的方法。所以唯一剩下的就是如何访问选项卡片段以从我的 FragmentActivity 调用方法。

这是我使用 pageViewer 的 FragmentActivity。当我想在setup() 方法中获取标签的片段对象时,我得到了空指针:

public class MainActivity extends FragmentActivity implements
    OnTabChangeListener, OnPageChangeListener {
    private TabHost mTabHost;
private ViewPager mViewPager;
private HashMap<String, TabInfo> mapTabInfo = new HashMap<String, MainActivity.TabInfo>();
private PagerAdapter mPagerAdapter;
private TabInfo mLastTab = null;

private class TabInfo {
    private String tag;
    private Class clss;
    private Bundle args;
    private Fragment fragment;

    TabInfo(String tag, Class clazz, Bundle args) {
        this.tag = tag;
        this.clss = clazz;
        this.args = args;
    }

}

class TabFactory implements TabContentFactory {

    private final Context mContext;

    /**
     * @param context
     */
    public TabFactory(Context context) {
        mContext = context;
    }

    /**
     * (non-Javadoc)
     * 
     * @see android.widget.TabHost.TabContentFactory#createTabContent(java.lang.String)
     */
    public View createTabContent(String tag) {
        View v = new View(mContext);
        v.setMinimumWidth(0);
        v.setMinimumHeight(0);
        return v;
    }

}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.requestWindowFeature(Window.FEATURE_NO_TITLE);
    Log.d("checking", "setup tabs...");
    setContentView(R.layout.activity_main);
    // //
    initialiseTabHost(savedInstanceState);
    if (savedInstanceState != null) {
        mTabHost.setCurrentTabByTag(savedInstanceState.getString("tab")); 
    }
    intialiseViewPager();
    // //
    setup();
    // ///
}

protected void onSaveInstanceState(Bundle outState) {
    outState.putString("tab", mTabHost.getCurrentTabTag()); // save the tab
                                                            // selected
    super.onSaveInstanceState(outState);
}

private void intialiseViewPager() {

    List<Fragment> fragments = new Vector<Fragment>();
    fragments
            .add(Fragment.instantiate(this, CoachFragment.class.getName()));
    fragments
            .add(Fragment.instantiate(this, LogingFragment.class.getName()));
    fragments.add(Fragment.instantiate(this,
            HistoryFragment.class.getName()));
    this.mPagerAdapter = new PagerAdapter(
            super.getSupportFragmentManager(), fragments);
    //
    this.mViewPager = (ViewPager) super.findViewById(R.id.viewpager);
    this.mViewPager.setAdapter(this.mPagerAdapter);
    this.mViewPager.setOnPageChangeListener(this);
    mViewPager.setOffscreenPageLimit(1000000);
}

private void initialiseTabHost(Bundle args) {
    mTabHost = (TabHost) findViewById(android.R.id.tabhost);
    mTabHost.setup();
    mTabHost.getTabWidget().setDividerDrawable(R.drawable.tab_divider);
    TabInfo tabInfo = null;
    View tabView1 = createTabView(this, coach");
    MainActivity.AddTab(this, this.mTabHost, this.mTabHost
            .newTabSpec("Tab1").setIndicator(tabView1),
            (tabInfo = new TabInfo("Tab1", CoachFragment.class, args)));
    this.mapTabInfo.put(tabInfo.tag, tabInfo);
    View tabView2 = createTabView(this, logbook");
    MainActivity.AddTab(this, this.mTabHost, this.mTabHost
            .newTabSpec("Tab2").setIndicator(tabView2),
            (tabInfo = new TabInfo("Tab2", LogingFragment.class, args)));
    this.mapTabInfo.put(tabInfo.tag, tabInfo);
    View tabView3 = createTabView(this, "history");
    MainActivity.AddTab(this, this.mTabHost, this.mTabHost
            .newTabSpec("Tab3").setIndicator(tabView3),
            (tabInfo = new TabInfo("Tab3", HistoryFragment.class, args)));
    this.mapTabInfo.put(tabInfo.tag, tabInfo);
    mTabHost.setOnTabChangedListener(this);
}

private static void AddTab(MainActivity activity, TabHost tabHost,
        TabHost.TabSpec tabSpec, TabInfo tabInfo) {
    // Attach a Tab view factory to the spec
    tabSpec.setContent(activity.new TabFactory(activity));
    tabHost.addTab(tabSpec);
}

public void setup() {
    ....
                        CoachFragment fragment=(CoachFragment) mPagerAdapter.getRegisteredFragment(mViewPager.getCurrentItem());
                        fragment.setTempView(R.id.welcome);
                        fragment.animate();
                    ....
}

public void onTabChanged(String tag) {
    // TabInfo newTab = this.mapTabInfo.get(tag);
    int pos = this.mTabHost.getCurrentTab();
    this.mViewPager.setCurrentItem(pos);
}

private static View createTabView(final Context context, final String text) {
    View view = LayoutInflater.from(context)
            .inflate(R.layout.tabs_bg, null);
    TextView tv = (TextView) view.findViewById(R.id.tabsText);
    tv.setText(text);
    return view;
}


@Override
public void onPageScrollStateChanged(int arg0) {
    // TODO Auto-generated method stub

}

@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
    // TODO Auto-generated method stub

}

@Override
public void onPageSelected(int position) {
    // TODO Auto-generated method stub
    this.mTabHost.setCurrentTab(position);
}

}

我的页面适配器:

public class PagerAdapter extends FragmentPagerAdapter {

private List<Fragment> fragments;
private HashMap<Integer, Fragment> registeredFragments=new HashMap<Integer, Fragment>();
/**
 * @param fm
 * @param fragments
 */
public PagerAdapter(FragmentManager fm, List<Fragment> fragments) {
    super(fm);
    this.fragments = fragments;
}
/* (non-Javadoc)
 * @see android.support.v4.app.FragmentPagerAdapter#getItem(int)
 */
@Override
public Fragment getItem(int position) {
    return this.fragments.get(position);
}


@Override
public Object instantiateItem(ViewGroup container, int position) {
    Fragment fragment = (Fragment) super.instantiateItem(container, position);
    registeredFragments.put(position, fragment);
    return fragment;
}

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
    registeredFragments.remove(position);
    super.destroyItem(container, position, object);
}


public Fragment getRegisteredFragment(int position) {
    return registeredFragments.get(position);
}

/* (non-Javadoc)
 * @see android.support.v4.view.PagerAdapter#getCount()
 */
@Override
public int getCount() {
    return this.fragments.size();
}

}

还有我的 LogingFragment。其他 2 个片段完全相同:

public class LogingFragment extends Fragment{

public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    if (container == null) {
        // We have different layouts, and in one of them this
        // fragment's containing frame doesn't exist.  The fragment
        // may still be created from its saved state, but there is
        // no reason to try to create its view hierarchy because it
        // won't be displayed.  Note this is not needed -- we could
        // just run the code below, where we would create and return
        // the view hierarchy; it would just never be used.
        return null;
    }
    return (LinearLayout)inflater.inflate(R.layout.coach_activity, container, false);
}

}

每件事都完美无缺,所有查看和滑动都可以正常工作,但在 setup() 方法中,我得到了 nullPointer。请帮帮我。

【问题讨论】:

    标签: android android-viewpager fragment


    【解决方案1】:

    我强烈建议运行和测试使用 Tabs 和 ViewPager 的示例 Effective Navigation

    http://developer.android.com/training/implementing-navigation/index.html

    【讨论】:

    • 萨拉姆·莫森。感谢您的回答。我完全完成了使用 PageViewer 实现我的选项卡。我的问题是,当我想更改片段选项卡布局时,我需要选项卡的片段对象,但在每种方法中,我都会得到 null。我将发布我的整个活动和片段。请告诉我我的问题到底在哪里。非常感谢兄弟...
    【解决方案2】:

    终于搞清楚了nullpointer的原因。寻呼机适配器应该是这样的:

    public class PagerAdapter extends FragmentPagerAdapter {
    
    Fragment screens[];
    public PagerAdapter(FragmentManager fm, MainActivity context) {
        super(fm);
        screens = new Fragment[3];
        screens[0] = Fragment.instantiate(context,CoachFragment.class.getName() );
        screens[1] = Fragment.instantiate(context,LogingFragment.class.getName() );
        screens[2] = Fragment.instantiate(context,HistoryFragment.class.getName() );
    }
    
    @Override
    public Fragment getItem(int index) {
        if(index <= screens.length)
        {
            return screens[index];
        }
        return null;
    }
    
    @Override
    public int getCount() {
        return screens.length;
    }
    

    }

    所以实例化视图寻呼机更改如下:

    private void intialiseViewPager() {
    
    
        this.mPagerAdapter = new PagerAdapter(super.getSupportFragmentManager(),this);
        //
        this.mViewPager = (ViewPager) super.findViewById(R.id.viewpager);
        this.mViewPager.setAdapter(this.mPagerAdapter);
        this.mViewPager.setOnPageChangeListener(this);
        //
        this.mViewPager = (ViewPager) super.findViewById(R.id.viewpager);
        this.mViewPager.setAdapter(this.mPagerAdapter);
        this.mViewPager.setOnPageChangeListener(this);
    }
    

    感谢@Bruno Mateus

    【讨论】:

      【解决方案3】:

      在我看来你是 android 新手,所以让我指出正确的方向(如果你不是 android 新手,我很抱歉):

      如果你想在你的应用中使用标签,最新最好的方法是使用Action Bar tabs

      这仅涉及编辑您的menu.xml 文件并将onCreateOptionsMenu() 方法添加到您的主要活动中。

      另外,回答你的问题,

      所以唯一剩下的就是如何访问选项卡片段以从我的 FragmentActivity 调用方法

      您不应该使用您的片段从您的片段活动中调用方法。

      再次,我将通过此视频为您指明正确的方向, "Programming Android with fragments"。有点长,但是会解释如何使用片段。

      使用视频的片段示例并将其与操作栏标签页中的示例代码结合起来。

      祝你好运

      **快速编辑澄清:您应该使用操作栏选项卡,因为这是使用选项卡的最新和最简单的方法。这是新的“最佳实践”。 TabWidget 和 TabActivity 更老、更复杂,据我所知甚至可能被弃用。

      【讨论】:

      • 我使用的是 10 级 API,所以我认为我无法使用 ActionBar 选项卡。
      • 在这种情况下,我建议你认真考虑使用操作栏 sherlock。
      • @Mohamad Ghadourian ^^是的,我忘记了。 action bar sherlock 为较低的 api 级别提供了对 action bar 的支持。
      • 对我发布的代码有任何帮助吗?使用操作栏时,我的问题没有任何改变。请告诉我哪里做错了。
      • 那么您是否更改了代码以使用操作栏和操作栏选项卡?如果是这样,请使用该新代码更新您的问题,以便我们查看问题所在。如果没有,我无法为您提供帮助,因为我对 android 太陌生,无法了解旧的标签实现方式。
      【解决方案4】:

      试试GrilledUI 库。它会为您完成所有繁琐的工作,甚至从 XML 加载选项卡列表。

      【讨论】:

        猜你喜欢
        • 2016-02-04
        • 2013-04-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-13
        • 1970-01-01
        相关资源
        最近更新 更多