ActionBarSherlock、ViewPager、TabsAdapter 嵌套选项卡片段

Posted

技术标签:

【中文标题】ActionBarSherlock、ViewPager、TabsAdapter 嵌套选项卡片段【英文标题】:ActionBarSherlock, ViewPager, TabsAdapter nested Tab Fragments 【发布时间】:2013-01-01 14:59:27 【问题描述】:

我实现了一个带有 ViewPager 和 TabsAdapter 的 ActionBarSherlock。它运行良好,但现在我尝试从加载到“Tab 1”中的框架中“推送”另一个片段。

行为应该是这样的:

我的应用程序中有 3 个选项卡,启动时我看到第一个选项卡,其中有一个带有按钮的片段 按第一个选项卡上的按钮,应替换第一个选项卡上的片段并显示另一个片段

我尝试实现此功能,但替换时出现黑色 Fragment。

代码:

FragmentDemoActivity.java

public class FragmentDemoActivity extends SherlockFragmentActivity 
    CustomViewPager  mViewPager;
    TabsAdapter mTabsAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        ActionBar bar = getSupportActionBar();
        bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        bar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);

        mViewPager = (CustomViewPager)findViewById(R.id.pager);
        mViewPager.setSwipingEnabled(false);

        mTabsAdapter = new TabsAdapter(this, bar, mViewPager);
        mTabsAdapter.addTab(bar.newTab().setText("tab1"),
                FragmentA.class, null);
        mTabsAdapter.addTab(bar.newTab().setText("tab2"),
                FragmentB.class, null);

   setTitle(R.string.app_name);

        if (savedInstanceState != null) 
            bar.setSelectedNavigationItem(savedInstanceState.getInt("tab"));
        
    

    @Override
    protected void onSaveInstanceState(Bundle outState) 
        super.onSaveInstanceState(outState);
        outState.putInt("tab", getSupportActionBar().getSelectedNavigationIndex());
    

    public static class TabsAdapter extends FragmentPagerAdapter
            implements ViewPager.OnPageChangeListener, ActionBar.TabListener 
        private final Context mContext;
        private final ActionBar mBar;
        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, ActionBar bar, ViewPager pager) 
            super(activity.getSupportFragmentManager());
            mContext = activity;
            mBar = bar;
            mViewPager = pager;
            mViewPager.setAdapter(this);
            mViewPager.setOnPageChangeListener(this);
        

        public void addTab(ActionBar.Tab tab, Class<? extends Fragment> clss, Bundle args) 
            TabInfo info = new TabInfo(clss, args);
            tab.setTag(info);
            tab.setTabListener(this);
            mTabs.add(info);
            mBar.addTab(tab);
            notifyDataSetChanged();
        

        @Override
        public int getCount() 
            return mTabs.size();
        

        @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) 
            mBar.setSelectedNavigationItem(position);
        

        @Override
        public void onPageScrollStateChanged(int state) 
        

        @Override
        public void onTabSelected(Tab tab, FragmentTransaction ft) 
            Object tag = tab.getTag();
            for (int i=0; i<mTabs.size(); i++) 
                if (mTabs.get(i) == tag) 
                    mViewPager.setCurrentItem(i,false);
                
            
        

        @Override
        public void onTabUnselected(Tab tab, FragmentTransaction ft) 

        

        @Override
        public void onTabReselected(Tab tab, FragmentTransaction ft) 

        
    


FragmentA.java

public class FragmentA extends Fragment 
    Button button;
    int num;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup group, Bundle saved)
    
        return inflater.inflate(R.layout.frag_a, group, false);
    

    @Override
    public void onActivityCreated (Bundle savedInstanceState)
    
        super.onActivityCreated(savedInstanceState);
        num = 0;
        button = (Button) getActivity().findViewById(R.id.button1);
        button.setOnClickListener(new View.OnClickListener() 

            @Override
            public void onClick(View v) 

                FragmentB f1 = new FragmentB();
                FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
                ft.replace(R.id.pager, f1,"newTag");
                ft.show(f1);
                ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
                ft.addToBackStack(null);
                ft.commit();    

            
        );
    

我是 android 开发的新手,所以如果有人能够帮助我,我会很高兴。我已经调查了很多时间来寻找解决方案,但结果并不如我所愿。

我目前的项目:http://cl.ly/3q1f2t1O2Y3j

【问题讨论】:

您是否在 ABS 的 Fragments 示例项目中看到“Tabs and Pager”示例? 【参考方案1】:

我明白了!

让我解释一下,您需要在要替换的 Layout 上放置一个 id,我的示例:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/Framelay"
    android:layout_
    android:layout_ >

    <TextView
        android:id="@+id/txtSearchTopic"
        android:layout_
        android:layout_
        android:layout_marginLeft="10dp"
        android:layout_marginTop="10dp"
        android:text="TextView" />

</FrameLayout>

所以我只输入我的:android:id="@+id/Framelay" 然后我可以用这个Id来替换新的fragment,我的意思是这个Layout里面的所有内容都会被新的Fragment替换,我叫DetailFragment。

FragmentManager fragmentManager = getFragmentManager();  
FragmentTransaction fragmentTransaction = fragmentManager  
        .beginTransaction();  
DetailFragment fragment3 = new DetailFragment();  
fragmentTransaction.replace(R.id.Framelay, fragment3);  
fragmentTransaction.commit(); 

【讨论】:

当使用 android.R.id.content 而不是 R.id.pager 时,如上所述,它适用于当前视图,但是当执行此代码然后切换到另一个选项卡时,新添加的Fragment 覆盖在另一个 Tab 中显示的 Fragment。 我明白了,你明白了,这是个好问题,我会努力寻找解决方案。 在最初加载的 Fragment 中,我将 id 添加到 LinearLayout 参数中。然后在替换视图时,视图没有被替换,我在新视图下看到了新视图。 我不明白为什么将新视图放在旧视图下,尝试了很多方法并做了同样的事情,我刚刚得到了一个运行良好的示例项目,也许你能比我理解得更好,见github.com/tamsler/android-flash-cards 我有一个更好的解决方案,见4shared.com/rar/zOWrvmyu/ViewpagerandSherlock.html,在每个fragment里面你可以实现Asynctask,看看你能不能看懂。

以上是关于ActionBarSherlock、ViewPager、TabsAdapter 嵌套选项卡片段的主要内容,如果未能解决你的问题,请参考以下文章

ActionBarSherlock:java.lang.NoClassDefFoundError:com.actionbarsherlock.R$styleable

更改 ActionBarSherlock 背景颜色

ActionBarSherlock & ShareActionProvider 导致 InflateException

Gradle 无法构建 ActionBarSherlock

ActionBarSherlock、ViewPager、TabsAdapter 嵌套选项卡片段

ActionBar 菜单项的动态可绘制图标? (安卓,ActionBarSherlock)