48

API からサンプル コードを試してみましたが、実際には機能しなかったため、独自のコードを実装しました。

FragmentPagerサポート

public class FragmentPagerSupport extends FragmentActivity {

static final int NUM_ITEMS = 10;
MyAdapter mAdapter;
ViewPager mPager;

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

    mAdapter = new MyAdapter(getSupportFragmentManager());
    Log.i("Pager", "mAdapter = " + mAdapter.toString());

    mPager = (ViewPager)findViewById(R.id.pager);
    if (mPager == null)
        Log.i("Pager", "mPager = null");
    else 
        Log.i("Pager", "mPager = " + mPager.toString());

    Log.i("Pager", "Setting Pager Adapter");
    mPager.setAdapter(mAdapter);
}

public static class MyAdapter extends FragmentPagerAdapter {
    public MyAdapter(FragmentManager fm) {
        super(fm);
        Log.i("Pager", "MyAdapter constructor");
    }

    @Override
    public int getCount() {
        Log.i("Pager", "MyAdapter.getCount()");
        return NUM_ITEMS;            
    }

    @Override
    public Fragment getItem(int position) {
        Log.i("Pager", "MyAdapter.getItem()");

        return TestFragment.newInstance(position);
    }
}

public static class TestFragment extends Fragment {

    public static TestFragment newInstance(int position) {
        Log.i("Pager", "TestFragment.newInstance()");

        TestFragment fragment = new TestFragment();

        Bundle args = new Bundle();
        args.putInt("position", position);
        fragment.setArguments(args);

        return fragment;
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        Log.i("Pager", "TestFragment.onCreateView()");

        LinearLayout layout = (LinearLayout)inflater.inflate(R.layout.fragment_item, null);
        int position = getArguments().getInt("position");

        TextView tv = (TextView)layout.findViewById(R.id.text);
        tv.setText("Fragment # " + position);
        tv.setTextColor(Color.WHITE);
        tv.setTextSize(30);

        return layout;
    }

}

}

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <android.support.v4.view.ViewPager
    android:id="@+id/pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    />
</LinearLayout>

fragment_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <TextView  
    android:id="@+id/text"
    android:layout_width="match_parent" 
    android:layout_height="match_parent"
    android:gravity="center" 
    android:text="@string/hello"
    />
</LinearLayout>

私の質問は、Fragmentユーザーが左右にスワイプするたびに新しいインスタンスを作成する代わりに、フラグメントの状態を (何らかのデータ構造に) 保存してから復元するにはどうすればよいですか?

API デモには、コードを保存する状態情報がまったくないようです。

4

6 に答える 6

126

ViewPager.setOffscreenPageLimit()で使用FragmentActivity

ViewPager pager = (ViewPager) findViewById(R.id.viewPager);
pager.setOffscreenPageLimit(2);

詳細については、カスタム FragmentPagerAdapter にフラグメントの破棄を停止するように指示するにはどうすればよいですか? を参照してください。

于 2013-11-11T07:48:12.500 に答える
15

更新: MyAdapter の getItem で、フラグメントの新しいインスタンスを返します。Android は、すべてのスワイプで getItem を呼び出すわけではありません。getItem を呼び出して新しいインスタンスを取得するだけですが、既存のインスタンスが利用可能である限り再利用します。

デモの状態部分について。私はあなたを助けることができません。フラグメント/アクティビティの状態を復元するための通常の手法がここに適用されると思うので、ViewPager にロードするときに特別なことは何もありません (ただし、間違っている可能性があります)。

于 2011-08-01T14:31:28.080 に答える
14

オーバーライドする場合

public void destroyItem(View container, int position, Object object)

super を呼び出さないと、フラグメントは破棄されず、再利用されます。

于 2011-10-27T09:25:20.093 に答える
4

アダプターは FragmentPageAdapter ではなく FragmentStatePagerAdapter から拡張する必要があり、アダプターは位置からフラグメント項目への参照を保持します。アクティビティまたはフラグメントの親で、PageIndicator のリスナー OnPageChangeListener を設定して、アクティブ化されたフラグメント アイテムの位置を検出し、関連するデータの状態を更新します。

フラグメントアイテムのデータ状態については、アクティビティまたはフラグメントの親から状態を保存/復元する必要があると思います。

アダプターは、次のようなコードを追加できます。

public static class MyAdapter extends FragmentStatePagerAdapter {
    private SparseArray<TestFragment> mPageReferenceMap 
                              = new SparseArray<TestFragment>();
    ...

    @Override 
    public Object instantiateItem(ViewGroup viewGroup, int position) {
        Object obj = super.instantiateItem(viewGroup, position);

        //Add the reference when fragment has been create or restore
        if (obj instanceof TestFragment) {
                TestFragment f= (TestFragment)obj;
                mPageReferenceMap.put(position, f);
        }

        return obj;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        //Remove the reference when destroy it
        mPageReferenceMap.remove(position);

        super.destroyItem(container, position, object);
    }

    public TestFragment getFragment(int key) {

        return mPageReferenceMap.get(key);
    }
    ...
}

この助けを願っています。

于 2013-06-05T16:03:53.597 に答える