(ActionBar) Tabs + Pager + detail Фрагменты внутри контейнера ViewPager - PullRequest
11 голосов
/ 08 декабря 2011

Для ActionBarSherlock мне бы хотелось иметь (панель действий) вкладки + пейджер. Я использую фрагменты внутри этого контейнера пейджера. Я уже получил примеры работы http://actionbarsherlock.com/, но мне не удается получить фрагмент подробностей внутри этого контейнера пейджера, когда я нажимаю, скажем, элемент списка в первом фрагменте.

Разве невозможно иметь что-то подобное:

Активность с вкладками и контейнером с пейджером

  • Фрагмент A внутри контейнера пейджера под Tab1
    • Кликните на что-нибудь во Фрагменте A и покажите Фрагмент B в том же контейнере пейджера под Tab1.

Фрагмент A тогда не виден, виден только фрагмент B, но также и все вкладки.

В настоящий момент я думаю, что только новое действие (которое будет содержать фрагмент B внутри него) может быть запущено после нажатия чего-либо во фрагменте A.

Ответы [ 4 ]

15 голосов
/ 15 декабря 2011

Вот мое решение для (Tabs + Fragment + ViewPager), оно работает для меня, как я и хотел, надеюсь, что это работает и для вас

вот XML-файл </p> <pre><code> <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 Я опубликую только соответствующий код, поэтому вам придется управлять им

</p> <pre><code>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); } } }

и вот как я справляюсь с фрагментом детали, не очень эффективным, но вроде работающим

</p> <pre><code>public class DetailFragment extends Fragment{ public static DetailFragment newInstance(int index, String TYPE_FRAGMENT) { DetailFragment f = new DetailFragment(); // Supply index input as an argument. Bundle args = new Bundle(); args.putInt("index", index); args.putString("type", TYPE_FRAGMENT); f.setArguments(args); return f; } public int getShownIndex() { return getArguments().getInt("index", 0); } public String getTypeFragment(){ String a = getArguments().getString("type"); return a; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { //template is blank layout View view = inflater.inflate(R.layout.template, container, false); if(getTypeFragment().equals(ArtistFragment.TYPE_FRAGMENT)){ view = null; view = inflater.inflate(R.layout.artist_details, container, false); //.... } else if(getTypeFragment().equals(AlbumFragment.TYPE_FRAGMENT)){ //do's for album fragment } else if(getTypeFragment().equals(SongFragment.TYPE_FRAGMENT)){ //do's for song fragment } return view; } }

не сохраняют состояниевкладка в их отдельном фрагменте будет конфликтовать, мы уже делаем это здесь

2 голосов
/ 13 декабря 2011

РЕДАКТИРОВАТЬ:
Приветствовал слишком рано.Теперь details_container не является пейджером, и я не могу использовать его для «пролистывания вкладок».

Нашел!Просто нужно было определить два 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();

Очень просто, и я не понимаю, почему мне потребовались часы, чтобы понятьэто из ..

0 голосов
/ 11 декабря 2011

Я нашел другой хороший пример той же реализации в слышать ... https://github.com/UweTrottmann/SeriesGuide

В этом примере в пакете com.battlelancer.seriesguide.ui

вы можете найти UpcomingRecentActivity.java, и UpcomingFragment.java

и макет upcoming_multipan.xml

этот пример работает для меня ...

У меня возникла одна проблема при добавлении другого содержимого для фрагмента детализации.на разных вкладках это дает мне исключение приведения класса

, поэтому я реализовал общий класс detalFragment и создал отдельный макет в методе onCreateView

, но единственная проблема, которую я обнаружил, заключается в том, что компоновка не меняется нас переключением табуляции, возможно, потребуется сделать это путем реализации некоторого слушателя

Я скажу вам, когда найду ответ.

0 голосов
/ 09 декабря 2011

Я все еще не нашел возможности иметь контейнер Pager, в который следует загружать фрагменты, а также хранить вкладки (ActionBar).Однако я нашел действительно грязное решение для достижения этой цели, начиная интенсивность (Основное действие с вкладками) и заканчивая предыдущими, когда кнопка больше не нужна.

Я адаптировал код из ABS: Поддержка демонстраций - вкладки и пейджер.Но опять же, это действительно грязно:

LoaderCursorSupport.CursorLoaderListFragment в Tab2

@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());
    }

Можно ли сделать это проще?Или я должен просто отказаться от вкладок вместе с историей фрагментов?Это было сделано до Android 3.0 с ActivityGroups и Activity, но, похоже, этого нельзя сделать с фрагментами.

...