2

Infinite ViewPagerViewPagerの回答と同様のコードで、いくつかの ListViews を含むを使用しています。アイデアは、Googleカレンダーアプリの日ビューのようなものを用意することです(そのソースは利用できないようです。デフォルトのカレンダーアプリのみが使用されています)-ユーザーが左右に無限にスワイプできるようにしたいですが、実際には には 3 つの項目しかありません。ユーザーがページ 0 または 2 にアクセスすると、1 を現在のページとして設定し、それに応じて更新します。ViewSwitcherViewPager

これですべて動作します。ただし、奇妙なことに、電話が回転してアクティビティが再構築されると (configChanges今のところ使用を避けています)、アプリ内のページが再びインスタンス化されますが、順序が正しくありません。0->1->2 の代わりに、1->0->2 の順序になり、これによりアプリ内のページの順序が台無しになります。

私のフラグメント、onActivityCreated():

mPagerAdapter = new ContinuousPagerAdapter(R.layout.my_listview, this);

// set the adapter
mViewPager = (ViewPager) getView().findViewById(R.id.agendaViewPager);
mViewPager.setOffscreenPageLimit(3);
mViewPager.setOnPageChangeListener(this);
mViewPager.setAdapter(mPagerAdapter);
mViewPager.setSaveEnabled(false);
// ...
mViewPager.setCurrentItem(1, false);
loadData();

ページャー アダプター:

import android.content.Context;
import android.os.Parcelable;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;

public class ContinuousPagerAdapter extends PagerAdapter {

    OnPageInstantiatedListener pListener;
    ViewPager container;
    int childLayoutResId;

    @SuppressWarnings("unused")
    private ContinuousPagerAdapter() {
    }

    /**
     * @param childLayoutResId Layout resource ID of the children to be inflated
     */
    public ContinuousPagerAdapter(int childLayoutResId, OnPageInstantiatedListener pListener) {
        this.childLayoutResId = childLayoutResId;
        this.pListener = pListener;
    }

    @Override
    public int getCount() {
        return 3;
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;
    }

    @Override
    public Object instantiateItem(View container, int position) {
        this.container = (ViewPager) container;

        // inflate a new child view
        LayoutInflater li = (LayoutInflater) container.getContext().getSystemService(
                Context.LAYOUT_INFLATER_SERVICE);
        View childView = li.inflate(childLayoutResId, null, false);

        // add it to the view pager and return
        int count = this.container.getChildCount();
        int actualPos = count > position ? position : count;
        this.container.addView(childView, actualPos);
        pListener.onPageInstantiated(actualPos); // sometimes use 0 instead of actualPos, with different but still inconsistent results
        return childView;
    }

    @Override
    public void destroyItem(View container, int position, Object object) {
        ((ViewPager) container).removeViewAt(position);
    }

    public static interface OnPageInstantiatedListener {
        public void onPageInstantiated(int position);
    }

    /**
     * Needed to ensure all the items are instantiated
     */
    @Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }

    @Override
    public Parcelable saveState() {
        return null;
    }

    @Override
    public void restoreState(Parcelable state, ClassLoader loader) {
    }

    @Override
    public void finishUpdate(View container) {
    }
}

回転後にページが 1->0->2 の順序でインスタンス化される理由がわかりません。私も状態を保存していません。これに関する洞察は役に立ちます。

4

2 に答える 2

4

アプリを注意深くデバッグし、ViewPagerソースを調べたところ、問題が見つかりました。

アプリが初めて起動しmViewPager.setAdapter(mPagerAdapter)て呼び出されると、ページが即座に開始され、アプリは正常に動作します。ただし、電話を回転させると、ウィンドウの準備ができていないためnullが返されるsetAdapter()ため、呼び出しはページのインスタンス化を延期します。インスタンス化は、ループで呼び出されたgetWindowToken()でも遅延します。 onResume()

呼び出すsetCurrentItem(1, false)と、最初のページがプライマリページになり、その結果、他のページの前にインスタンス化され、最初は奇妙な1->0->2のインスタンス化になります。

ソリューション?他のページがインスタンス化された後、を使用してデータHandlerを実行およびロードします。setCurrentItem()

new Handler().post(new Runnable() {
    @Override
    public void run() {
        mViewPager.setCurrentItem(1, false);
        cleanupAndShowData();
    }
});

通常はsの使用を避けたいと思いますがHandler、ページ自体がルーパーに追加されているため、これまでに見つけた唯一のオプションのようです。

編集:上記でさえいくつかの問題がありました。mViewPager.setCurrentItem(1, false)すべてのページが(で)インスタンス化された後でのみ、電話をかけることになりましたonPageInstantiated()

于 2012-11-29T09:33:14.203 に答える
1
actualPos= position%getCount();

これで解決しない場合は、追加のコードを教えてください。

ちょっとした改造もおすすめ

mViewPager.setOffscreenPageLimit(2);   //use 2 instead of 3 unless neccessary
于 2012-11-28T07:14:55.847 に答える