31

FragmentPagerAdapter に接続された ViewPager を最初にホストするアクティビティがあります。

ユーザーが ViewPager の子フラグメント内の項目をクリックすると、FragmentTransaction を使用して、空のコンテナー ビューを移動先の新しい Fragment に置き換えます。

トランザクションで addToBackStack() を使用し、トランザクションをコミットしてから戻ると、ViewPager のビュー (初期レイアウト) に戻りません。

トランザクションで addToBackStack() を使用せず、トランザクションをコミットしてから戻ると、アプリケーションが終了します。

ViewPager がバックスタックに追加されていないことは明らかです (それ自体はフラグメントではないため、それほど驚くべきことではありません)。ビュー (ViewPager)。

私が読んだ内容に基づいて、おそらくフラグメント トランザクションが行われているために、ViewPager または PagerAdapter がどのフラグメントを表示すべきかを見失っているようです。

私はこれに本当に混乱していますが、onBackPress をオーバーライドし、viewpager ビューを表示および非表示にするコードの巨大な混乱を作成することになりました。デフォルトの動作を使用して適切なナビゲーションを実行する簡単な方法があると思います。

tl;dr

A は、フラグメントをホストする Viewpager です。B は新しいフラグメントです。

A を B に置き換えてから戻ると、A に戻ることが期待されますが、そうはなりません。

アドバイスをいただければ幸いです。

コード:

主な活動:

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

        headingLayout = (RelativeLayout) findViewById(R.id.headingLayout);
        headingLayout.setVisibility(View.GONE);

        // Set up the ViewPager, attaching the adapter and setting up a listener
        // for when the
        // user swipes between sections.
        mViewPager = (ViewPager) findViewById(R.id.pager);

        mViewPager.setPageMargin(8);

        /** Getting fragment manager */
        FragmentManager fm = getSupportFragmentManager();

        /** Instantiating FragmentPagerAdapter */
        MyFragmentPagerAdapter pagerAdapter = new MyFragmentPagerAdapter(fm);

        /** Setting the pagerAdapter to the pager object */
        mViewPager.setAdapter(pagerAdapter);
.
.
.
}

    public void onListItemClicked(Fragment fragment) {
        fromPlayer = false;
        InitiateTransaction(fragment, true);

    }


    public void InitiateTransaction(Fragment fragment, boolean addToBackStack) {

        invalidateOptionsMenu();

        FragmentManager fm = getSupportFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();

        ft.replace(R.id.fragmentContainer, fragment).addToBackStack(null)
                .commit();

    }

PagerAdapter:

package another.music.player;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import another.music.player.fragments.AlbumListFragment;
import another.music.player.fragments.ArtistListFragment;
import another.music.player.fragments.SongListFragment;

public class MyFragmentPagerAdapter extends FragmentPagerAdapter {

    final int PAGE_COUNT = 3;

    /** Constructor of the class */
    public MyFragmentPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    /** This method will be invoked when a page is requested to create */
    @Override
    public Fragment getItem(int i) {
        switch (i) {
        case 0:
            ArtistListFragment artistListFragment = new ArtistListFragment();
            Bundle artistData = new Bundle();
            artistData.putInt("current_page", i + 1);
            artistListFragment.setArguments(artistData);
            return artistListFragment;

        case 1:
            AlbumListFragment albumListFragment = new AlbumListFragment();
            Bundle albumData = new Bundle();
            albumData.putInt("current_page", i + 1);
            albumData.putBoolean("showHeader", false);
            albumListFragment.setArguments(albumData);
            return albumListFragment;

        default:

            SongListFragment songListFragment = new SongListFragment();
            Bundle songData = new Bundle();
            songData.putInt("current_page", i + 1);
            songListFragment.setArguments(songData);
            return songListFragment;
        }
    }

    /** Returns the number of pages */
    @Override
    public int getCount() {
        return PAGE_COUNT;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        switch (position) {
        case 0:
            return "Artists";

        case 1:
            return "Albums";

        default:
            return "Songs";
        }
    }
}

メイン xml (fragmentContainer と ViewPager を含む):

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/app_background_ics" >

    <RelativeLayout
        android:id="@+id/headingLayout"
        android:layout_width="match_parent"
        android:layout_height="56dp" >
    </RelativeLayout>

    <FrameLayout
        android:id="@+id/fragmentContainer"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_below="@+id/headingLayout" />

    <android.support.v4.view.ViewPager
        android:id="@+id/pager"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >

        <android.support.v4.view.PagerTabStrip
            android:id="@+id/pager_title_strip"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#33b5e5"
            android:paddingBottom="4dp"
            android:paddingTop="4dp"
            android:textColor="#fff" />
    </android.support.v4.view.ViewPager>

</RelativeLayout>
4

5 に答える 5

43

私もこれとまったく同じ問題を長い間抱えていました。解決策は非常に単純で、ViewPager Visibility をハックする必要はありません。私はこの他のSO関連の質問で説明されています: ViewPagerのフラグメントはpopBackStack後に復元されません

ただし、簡単にするために必要なのは、ViewPager アダプターで getSupportFragmentManager() の代わりに getChildFragmentManager() を使用することだけです。したがって、これの代わりに:

    /** Getting fragment manager */
    FragmentManager fm = getSupportFragmentManager();

    /** Instantiating FragmentPagerAdapter */
    MyFragmentPagerAdapter pagerAdapter = new MyFragmentPagerAdapter(fm);

    /** Setting the pagerAdapter to the pager object */
    mViewPager.setAdapter(pagerAdapter);

これをして:

    /** Getting fragment manager */
    FragmentManager fm = getChildFragmentManager();

    /** Instantiating FragmentPagerAdapter */
    MyFragmentPagerAdapter pagerAdapter = new MyFragmentPagerAdapter(fm);

    /** Setting the pagerAdapter to the pager object */
    mViewPager.setAdapter(pagerAdapter);
于 2013-06-27T18:54:05.447 に答える
9

更新:
これは「Android のやり方」ではなく、リストビューの場合はユーザー エクスペリエンスが低下します。代わりに、新しいアクティビティを作成してください。

この問題の簡単な解決策を探している人のために、私が行ったことを要約します。

私のアーキテクチャ:

  • FragmentActivity の ViewPager (実際には、ActionBarActivity は ActionBar をサポートするためのものですが、ActionBarActivity は FragmentActivity を実装しています)。

  • 2 つのタブ :

    • Fragmentを拡張するFragmentContainer1。
    • Fragmentを拡張するFragmentContainer2。

FragmentContainer ごとに、たとえば onCreate メソッドで getChildFragmentManager を呼び出し、このコンテナに表示するフラグメントを追加します。

FragmentToShow fragment = new FragmentToShow();

getChildFragmentManager()
        .beginTransaction()
        .add(R.id.container, fragment)
        .commit();

戻るボタンを押したときにフラグメント コンテナーを表示したくないため、最初のフラグメントをフラグメント コンテナーのバックスタックに追加したくありません。

次に、 FragmentToShow を FragmentToShow クラスの別のフラグメントに置き換えたい場合 (listView など):

Fragment itemFragment = new ItemFragment();

getFragmentManager()
        .beginTransaction()
        .replace(R.id.container, itemFragment)
        .addToBackStack(null)
        .commit();

ここでは、子フラグメント マネージャーを取得し、itemFragment をバック スタックに追加します。

ここで、戻るボタンを押して listView (FragmentToShow インスタンス) に戻る必要があります。私たちのアクティビティ (FragmentActivity) は戻るボタンを認識する唯一のアクティビティであるため、このアクティビティで onBackPressed() メソッドをオーバーライドする必要があります。

@Override
public void onBackPressed() {

    // We retrieve the fragment manager of the activity
    FragmentManager frgmtManager = getSupportFragmentManager();

    // We retrieve the fragment container showed right now
    // The viewpager assigns tags to fragment automatically like this
    // mPager is our ViewPager instance
    Fragment fragment = frgmtManager.findFragmentByTag("android:switcher:" + mPager.getId() + ":" + mPager.getCurrentItem());

    // And thanks to the fragment container, we retrieve its child fragment manager
    // holding our fragment in the back stack
    FragmentManager childFragmentManager = fragment.getChildFragmentManager();

    // And here we go, if the back stack is empty, we let the back button doing its job
    // Otherwise, we show the last entry in the back stack (our FragmentToShow) 
    if(childFragmentManager.getBackStackEntryCount() == 0){
        super.onBackPressed();
    } else {
        childFragmentManager.popBackStack();
    }
}

アクティビティで getSupportFragmentManager を呼び出すので、子フラグメントで getFragmentManager を呼び出すことができます。これにより、サポート FragmentManager インスタンスが返されます。

以上です!私は専門家ではありませんので、アドバイスやコメントがあればお気軽にどうぞ。

于 2013-08-02T15:04:20.057 に答える
3

これを達成するために私が見つけた唯一の方法は、次のことです。

viewPager から移動するときは、Visiblity.GONE を使用して viewPager をビューから外します。フラグメント トランザクションをバックスタックに追加します。

(バック プレスを介して) viewPager 画面に戻るときは、onBackPressed をオーバーライドします。バックスタックにあるフラグメントの数を確認できます。viewPager がフラグメント トランザクションが発生する前の最初のビューであった場合、フラグメント バックスタック エントリ数が 0 であるかどうかを確認できます。

fragmentManager.getBackStackEntryCount() == 0、バックスタックにフラグメントはありません。

そのステートメントが true の場合は、Visibility.VISIBLE を使用して viewPager をビューに戻します。

于 2012-09-24T03:51:04.193 に答える
0

startViewPagerを含むを使用している場合、上に移動したり、上に移動したりしたときに、 の位置に適切に戻る方法を次に示します ( に対して上向きのナビゲーションが宣言されていると仮定します)。FragmentsActivitiesViewPagerActivityActivities

ViewPager最初に、 の現在の位置をExtra として渡してIntent、新しい を開始する必要がありますActivity

Activity次に、これを行う親にその位置を返します。

Intent upIntent = NavUtils.getParentActivityIntent(this);
upIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
upIntent.putExtra(FeedPagerActivity.EXTRA_POSITION, position);
NavUtils.navigateUpTo(this, upIntent);

そのコードを中に入れます

onOptionsItemSelected(メニュー項目)

于 2014-05-28T16:47:34.057 に答える
0

私は非常によく似た問題を抱えていたと思います。

FragmentManagers はいくぶん階層的な方法で動作するようです。私がこの問題を解決した方法は、ViewPager 内のフラグメントから取得できるものではなく、コンテナと ViewPager をホストするアクティビティから「メイン」 FragmentManager を使用することでした。

これを行うために、私は使用しました:

this.getActivity().getSupportFragmentManager()

thisFragment のインスタンスです。

ここで、ViewPager の項目から「置換」トランザクションを使用して他のフラグメントに移動すると、戻ったときに ViewPager がそのままの状態で表示されます。

より完全なコード サンプルは次のようになります。

FragmentManager fragmentManager =  MyCurrentFragment.this.getActivity().getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();

transaction.replace(R.id.container, newFragment);
transaction.addToBackStack(null);

transaction.commit();
于 2014-11-05T08:42:18.490 に答える