(ActionBar)Tabs + Pager + detail ViewPager容器中的碎片

时间:2011-12-08 14:09:10

标签: android tabs android-fragments android-actionbar android-viewpager

对于ActionBarSherlock,我想要(Action Bar)Tabs + Pager。我在该寻呼机容器中使用Fragments。我已经得到了http://actionbarsherlock.com/的示例,但是当我点击第一个片段中的一个listitem时,我无法设法在该寻呼机容器中获取详细信息片段。

不可能有这样的事情:

带标签和寻呼机容器的活动

  • Fragment Tab1下的内部寻呼机容器
    • 点击片段A中的内容并在Tab1下的同一个寻呼机容器中显示片段B.

然后片段A不可见,只有片段B可见,但也可见所有标签。

目前我认为在点击片段A中的某些内容后,只能启动一个新活动(可以在其中包含片段B)。

4 个答案:

答案 0 :(得分:15)

这是我的(Tabs + Fragment + ViewPager)解决方案,它对我来说很有用,我想要的,  希望对你有用

这是xml文件

 <LinearLayout
        android:id="@+id/linearLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal" >

        <android.support.v4.view.ViewPager
            android:id="@+id/pager"
            android:layout_width="0dip"
            android:layout_height="match_parent"
            android:layout_weight="5" />

        <FrameLayout
            android:id="@+id/fragment_details"
            android:layout_width="0px"
            android:layout_height="match_parent"
            android:layout_weight="4.3" />
    </LinearLayout>

<LinearLayout android:id="@+id/linearLayout" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <android.support.v4.view.ViewPager android:id="@+id/pager" android:layout_width="0dip" android:layout_height="match_parent" android:layout_weight="5" /> <FrameLayout android:id="@+id/fragment_details" android:layout_width="0px" android:layout_height="match_parent" android:layout_weight="4.3" /> </LinearLayout>

这里是MainActivity.java的代码我只发布相关代码,所以你必须管理它

public class MainActivity extends FragmentActivity implements
        DialogInterface.OnDismissListener, TabDataResponder {

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

        artistTab = getSupportActionBar().newTab().setText(
                R.string.tab_name_artist);
        albumTab = getSupportActionBar().newTab().setText(
                R.string.tab_name_album);
        songTab = getSupportActionBar().newTab().setText(
                R.string.tab_name_songs);

        map = new HashMap<String, Integer>();
        mViewPager = (ViewPager) findViewById(R.id.pager);
        FrameLayout deatil = (FrameLayout) findViewById(R.id.fragment_details);
        mDualPane = (deatil != null) && (deatil.getVisibility() == View.VISIBLE);
        mTabsAdapter = new TabsAdapter(this, getSupportActionBar(), mViewPager);

        if (savedInstanceState != null) {
            flag = true;
            index = savedInstanceState.getInt("index");
        }

        setUpTabView();

    }


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

    private void setUpTabView() {
        mTabsAdapter.addTab(artistTab, ArtistFragment.class, null);
        mTabsAdapter.addTab(albumTab, AlbumFragment.class, null);
        mTabsAdapter.addTab(songTab, SongFragment.class, null);
        getSupportActionBar().setSelectedNavigationItem(index);
    }

    public static class TabsAdapter extends FragmentPagerAdapter implements
            ViewPager.OnPageChangeListener, ActionBar.TabListener {

        private FragmentActivity mContext;
        private ActionBar mActionBar;
        private final ViewPager mViewPager;

        private final ArrayList<String> mTabs = new ArrayList<String>();
        private TabDataResponder responder;

        public TabsAdapter(FragmentActivity activity, ActionBar actionBar,
                ViewPager pager) {

            super(activity.getSupportFragmentManager());
            mContext = activity;
            mActionBar = actionBar;
            mViewPager = pager;

            // TabDataResponder is an interface which is implemented in MainActivity
            // You can find implementation @ the last

            responder = (TabDataResponder) activity;
            mViewPager.setAdapter(this);
            mViewPager.setOnPageChangeListener(this);

            //I have used map to save state of the fragment
            map.put(SongFragment.TYPE_FRAGMENT.trim(), 0);
            map.put(AlbumFragment.TYPE_FRAGMENT.trim(), 0);
            map.put(ArtistFragment.TYPE_FRAGMENT.trim(), 0);
        }

        public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) {
            mTabs.add(clss.getName());
            // mArgs.add(args);
            mActionBar.addTab(tab.setTabListener(this));
            notifyDataSetChanged();
        }

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

        @Override
        public Fragment getItem(int position) {
            return Fragment
                    .instantiate(mContext, mTabs.get(position), /*
                                                                 * mArgs.get(
                                                                 * position)
                                                                 */null);
        }

        @Override
        public void onPageScrolled(int position, float positionOffset,
                int positionOffsetPixels) {
        }

        @Override
        public void onPageSelected(int position) {
            Log.i(TAG, "PageSelected....");
            mActionBar.setSelectedNavigationItem(position);
        }

        @Override
        public void onPageScrollStateChanged(int state) {
            Log.i(TAG, "ScrollSateChanged....");
        }

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

        @Override
        public void onTabSelected(Tab tab, FragmentTransaction ft) {
            mViewPager.setCurrentItem(tab.getPosition());
            String a = null;
            if (mDualPane) {
                a = mTabs.get(tab.getPosition());
                responder.loadData(a, map.get(a));
            }
        }

        @Override
        public void onTabUnselected(Tab tab, FragmentTransaction ft) {
            Log.i(TAG, "Tab is released now....");
        }
    }

    @Override
    public void onDismiss(DialogInterface dialog) {
        setUpTabView();

    }
//This interface must be call from fragment class 
//@ the time of event you want to show detail 
// pass the class name in the type argument using class.getName() method
    @Override
    public void loadData(String type, int index) {
        DetailFragment viewer = (DetailFragment) getSupportFragmentManager()
                .findFragmentById(R.id.fragment_details);
        if (mDualPane) {
            if (viewer == null || viewer.getShownIndex() != index
                    || viewer.getTypeFragment() != type) {

                DetailFragment df = DetailFragment.newInstance(index, type);
                getSupportFragmentManager()
                        .beginTransaction()
                        .replace(R.id.fragment_details, df)
                        .setTransition(
                                FragmentTransaction.TRANSIT_FRAGMENT_FADE)
                        .commit();
                map.put(type.trim(), index);

            }

        } else {
            Intent intent = new Intent();
            intent.setClass(MainActivity.this, DetailActivity.class);
            intent.putExtra("index", index);
            intent.putExtra("type", type);
            startActivity(intent);
        }
    }
}
以下是我如何处理细节片段效率不高但工作有点

public class MainActivity extends FragmentActivity implements DialogInterface.OnDismissListener, TabDataResponder { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); artistTab = getSupportActionBar().newTab().setText( R.string.tab_name_artist); albumTab = getSupportActionBar().newTab().setText( R.string.tab_name_album); songTab = getSupportActionBar().newTab().setText( R.string.tab_name_songs); map = new HashMap<String, Integer>(); mViewPager = (ViewPager) findViewById(R.id.pager); FrameLayout deatil = (FrameLayout) findViewById(R.id.fragment_details); mDualPane = (deatil != null) && (deatil.getVisibility() == View.VISIBLE); mTabsAdapter = new TabsAdapter(this, getSupportActionBar(), mViewPager); if (savedInstanceState != null) { flag = true; index = savedInstanceState.getInt("index"); } setUpTabView(); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putInt("index", getSupportActionBar() .getSelectedNavigationIndex()); } private void setUpTabView() { mTabsAdapter.addTab(artistTab, ArtistFragment.class, null); mTabsAdapter.addTab(albumTab, AlbumFragment.class, null); mTabsAdapter.addTab(songTab, SongFragment.class, null); getSupportActionBar().setSelectedNavigationItem(index); } public static class TabsAdapter extends FragmentPagerAdapter implements ViewPager.OnPageChangeListener, ActionBar.TabListener { private FragmentActivity mContext; private ActionBar mActionBar; private final ViewPager mViewPager; private final ArrayList<String> mTabs = new ArrayList<String>(); private TabDataResponder responder; public TabsAdapter(FragmentActivity activity, ActionBar actionBar, ViewPager pager) { super(activity.getSupportFragmentManager()); mContext = activity; mActionBar = actionBar; mViewPager = pager; // TabDataResponder is an interface which is implemented in MainActivity // You can find implementation @ the last responder = (TabDataResponder) activity; mViewPager.setAdapter(this); mViewPager.setOnPageChangeListener(this); //I have used map to save state of the fragment map.put(SongFragment.TYPE_FRAGMENT.trim(), 0); map.put(AlbumFragment.TYPE_FRAGMENT.trim(), 0); map.put(ArtistFragment.TYPE_FRAGMENT.trim(), 0); } public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) { mTabs.add(clss.getName()); // mArgs.add(args); mActionBar.addTab(tab.setTabListener(this)); notifyDataSetChanged(); } @Override public int getCount() { return mTabs.size(); } @Override public Fragment getItem(int position) { return Fragment .instantiate(mContext, mTabs.get(position), /* * mArgs.get( * position) */null); } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { Log.i(TAG, "PageSelected...."); mActionBar.setSelectedNavigationItem(position); } @Override public void onPageScrollStateChanged(int state) { Log.i(TAG, "ScrollSateChanged...."); } @Override public void onTabReselected(Tab tab, FragmentTransaction ft) { } @Override public void onTabSelected(Tab tab, FragmentTransaction ft) { mViewPager.setCurrentItem(tab.getPosition()); String a = null; if (mDualPane) { a = mTabs.get(tab.getPosition()); responder.loadData(a, map.get(a)); } } @Override public void onTabUnselected(Tab tab, FragmentTransaction ft) { Log.i(TAG, "Tab is released now...."); } } @Override public void onDismiss(DialogInterface dialog) { setUpTabView(); } //This interface must be call from fragment class //@ the time of event you want to show detail // pass the class name in the type argument using class.getName() method @Override public void loadData(String type, int index) { DetailFragment viewer = (DetailFragment) getSupportFragmentManager() .findFragmentById(R.id.fragment_details); if (mDualPane) { if (viewer == null || viewer.getShownIndex() != index || viewer.getTypeFragment() != type) { DetailFragment df = DetailFragment.newInstance(index, type); getSupportFragmentManager() .beginTransaction() .replace(R.id.fragment_details, df) .setTransition( FragmentTransaction.TRANSIT_FRAGMENT_FADE) .commit(); map.put(type.trim(), index); } } else { Intent intent = new Intent(); intent.setClass(MainActivity.this, DetailActivity.class); intent.putExtra("index", index); intent.putExtra("type", type); startActivity(intent); } } }

不要将tab的状态保存在它们各自的片段中会发生冲突,我们已经在这里做了

答案 1 :(得分:2)

编辑:
太快欢呼了。现在details_container不是viewpager,我不能用它来“滑动标签”。

发现它!只需要定义两个FrameLayouts,第一个是ViewPager,第二个是可以“加载”细节片段。这是通过动态添加片段并替换它们来完成的。

首先是两个FrameLayouts:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:fadingEdge="none" >
    <FrameLayout
        android:id="@+id/main_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
        <android.support.v4.view.ViewPager
            android:id="@+id/pager"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent" />
    </FrameLayout>
    <FrameLayout
        android:id="@+id/details_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</RelativeLayout>

然后动态替换片段:

// Create new fragment and transaction
Fragment detailsFragment = new ExampleFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();

// Replace whatever is in the fragment container view with this fragment
// and add the transaction to the back stack
transaction.replace(R.id.details_container, detailsFragment);
transaction.addToBackStack(null);

// Commit the transaction
transaction.commit();

非常简单,我不明白为什么我需要花费数小时来解决这个问题。

答案 2 :(得分:0)

我仍然没有找到一个可能加载片段的Pager容器并且还保留(ActionBar)选项卡的可能性。然而,我发现了一个非常肮脏的解决方案来实现这一点,启动强度(带有选项卡的主要活动)并在后退按钮不再需要它时完成之前的操作。

我改编了ABS: Support Demos - Tabs和Pager的代码。但是它真的很脏:

Tab2下的LoaderCursorSupport.CursorLoaderListFragment

@Override public void onListItemClick(ListView l, View v, int position, long id) {
        Intent intent = new Intent();
        intent.setClass(getActivity(), ActionBarTabsPager.class);
        intent.putExtra("index", position);
        intent.putExtra("fragment", "details");
        intent.putExtra("tab", 1);
        ActionBarTabsPager.mPreviousActivity = getActivity();

        startActivity(intent);

ActionBarTabsPager(带标签的主要活动)

public class ActionBarTabsPager extends FragmentActivity {
ViewPager mViewPager;
TabsAdapter mTabsAdapter;
static Activity mPreviousActivity;
static Activity mActivity;
static int mTabPosition = -1;
static Boolean mTabRefreshed = false;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.actionbar_tabs_pager);
    getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

    ActionBar.Tab tab1 = getSupportActionBar().newTab().setText("Tab 1");
    ActionBar.Tab tab2 = getSupportActionBar().newTab().setText("Tab 2");
    ActionBar.Tab tab3 = getSupportActionBar().newTab().setText("Tab 3");
    ActionBar.Tab tab4 = getSupportActionBar().newTab().setText("Tab 4");
    String fragment = "";
    try {
        Bundle bundle = this.getIntent().getExtras();
        fragment = bundle.getString("fragment");
        mTabPosition = bundle.getInt("tab");
    } catch (Exception ex) {
    }

    mViewPager = (ViewPager) findViewById(R.id.pager);
    mTabsAdapter = new TabsAdapter(this, getSupportActionBar(), mViewPager);
    mTabsAdapter.addTab(tab1, FragmentStackSupport.CountingFragment.class);
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ECLAIR) {
        mTabsAdapter.addTab(tab2, FragmentStackSupport.CountingFragment.class);
        mTabsAdapter.addTab(tab3, FragmentStackSupport.CountingFragment.class);
        mTabsAdapter.addTab(tab4, FragmentStackSupport.CountingFragment.class);
    } else {
        if (!fragment.contains("details")) {
            mTabsAdapter.addTab(tab2, LoaderCursorSupport.CursorLoaderListFragment.class);
        } else {
            mTabsAdapter.addTab(tab2, ExampleFragment.class);
        }
        mTabsAdapter.addTab(tab3, LoaderCustomSupport.AppListFragment.class);
        mTabsAdapter.addTab(tab4, LoaderThrottleSupport.ThrottledLoaderListFragment.class);
    }

    if (savedInstanceState != null) {
        getSupportActionBar().setSelectedNavigationItem(savedInstanceState.getInt("index"));
    }

    if (mTabPosition > -1) {
        mTabsAdapter.setPrimaryItem(mTabPosition);

        mActivity = this;

    }
}

在这个类里面有一个TabsAdapter

public static class TabsAdapter extends FragmentPagerAdapter implements ViewPager.OnPageChangeListener, ActionBar.TabListener {
    private final Context mContext;
    private final ActionBar mActionBar;
    private final ViewPager mViewPager;
    private final ArrayList<String> mTabs = new ArrayList<String>();


    @Override
    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        if (mTabPosition > -1 && mTabRefreshed) {
            int tabPosition = tab.getPosition();
            if (mTabPosition != tabPosition) {
                if (mPreviousActivity != null) {
                    mPreviousActivity.finish();
                    mTabRefreshed = false;
                    mPreviousActivity = null;
                    mTabPosition = -1;
                    Intent intent = new Intent();
                    intent.setClass(mContext, ActionBarTabsPager.class);
                    intent.putExtra("fragment", "home");
                    intent.putExtra("tab", tabPosition);
                    mActivity.startActivity(intent);
                    mActivity.finish();

                }
            }
        }
        mViewPager.setCurrentItem(tab.getPosition());
    }

这可以更简单吗?或者我应该放弃使用Tabs和片段历史记录?这是在Android 3.0之前使用ActivityGroups和Activities完成的,但似乎无法通过片段完成。

答案 3 :(得分:0)

我在听到...... https://github.com/UweTrottmann/SeriesGuide

时找到了相同实现的另一个好例子

在com.battlelancer.seriesguide.ui包中的示例中

你可以找到UpcomingRecentActivity.java和UpcomingFragment.java

和布局coming_multipan.xml

这个例子对我有用......

我在为不同的标签添加不同的内容时遇到了一个问题,它给了我类 - 强制转换异常

所以我实现了一个常见的detalFragment类,并在onCreateView方法中创建了单独的布局

但我发现的唯一一个问题是布局在切换时没有改变,可能需要通过实现一些监听器来实现

当我找到答案时,我会告诉你的。