68

たくさんの写真を表示するViewPagerを使用したアクティビティがあります。開始時に、ViewPagerの位置は、ユーザーが前のアクティビティで選択したものに基づいて設定されます。ギャラリーに似ています。

新しいページが選択されるたびに、つまりアクティビティが最初に開かれたとき、またはユーザーが新しいページにスライドしたときに、onPageSelectedが呼び出されるようにします。

私は次のように開始点を設定しました:

 mPager.setCurrentItem(index);

インデックスが0に設定されたsetCurrentItemが呼び出された場合を除いて、すべてが機能します。これは、onPageSelectedをトリガーしないためです。

mPager.setOnPageChangeListener(new OnPageChangeListener() {
  @Override
  public void onPageSelected(int index) {
    Log.d(TAG, "onPageSelected " + index);
  }
  ...
}

だから私の質問は; これはバグですか?もしそうなら、私はそれについて何ができますか?

4

10 に答える 10

89

これまでに見つけた最もクリーンな解決策は、ViewPager に設定した onPageChangeListener への参照を取得し (ViewPager.getOnPageChangeListener() メソッドがあるとは思わないため)、ViewPager のアダプターを設定した後です。 、 電話:

onPageChangeListener.onPageSelected(viewPager.getCurrentItem());

ただし、現在のインデックスにあるページのフラグメントはまだインスタンス化されていないため (少なくとも FragmentStatePagerAdapter を使用している場合)、実行可能な ala でラップする必要がある場合があります。

viewPager.post(new Runnable(){
@Override
    public void run() {
        onPageChangeListener.onPageSelected(viewPager.getCurrentItem());
    }
});

また、onPageSelected ハンドラー内でフラグメントへの参照が必要な場合は、自分で行う必要があります。FragmentStatePagerAdapter の抽象基本クラスを使用して、インスタンス化メソッドと破棄メソッドをオーバーライドし、SparseArray からフラグメントを追加/削除します。

于 2013-11-29T19:10:13.613 に答える
35

わかりました。これがバグ (または機能) であるかどうかを判断できませんでした。しかし、問題の解決策がどのように見えるかを共有したいと思いました..

アクティビティのメソッドで実行したい機能を記述し、これを onPageSelected メソッドで呼び出します。

mPager.setOnPageChangeListener(new OnPageChangeListener() {
    @Override
    public void onPageSelected(int index) {
        myOnPageSelectedLogic(index);
    }
    ...
}

そして、電話した直後

setCurrentItem(index);

アクティビティで、次の if ステートメントを追加します

if(index == 0) {
    myOnPageSelectedLogic(0);
}

とてもきれいではありませんが、誰かの役に立てば幸いです:)

于 2012-08-22T09:43:47.387 に答える
25

実際、これはバグだと思います。ViewPager のソース コードを確認したところ、 onPageSelected の唯一のトリガーが見つかりまし

if (dispatchSelected && mOnPageChangeListener != null) {
            mOnPageChangeListener.onPageSelected(item);
        }

上記では、変数dispatchSelectedはコードによって決定されます。

final boolean dispatchSelected = mCurItem != item; 
//item is what you passed to setCurrentItem(item)

また、変数mCurItemは次のように定義および初期化されます。

private int mCurItem; // Index of currently displayed page.

したがって、mCurItemのデフォルトは 0 です。setCurrentItem(0) を呼び出すと、dispatchSelectedは false になるため、onPageSelected() はディスパッチされません。

ここで、setCurrentItem(0) の呼び出しが問題であり、setCurrentItem(1、または 2、3...) の呼び出しが問題ではない理由を理解する必要があります。

この問題を解決する方法:

  1. ViewPager のコードを自分のプロジェクトにコピーして修正します。

    from 
    final boolean dispatchSelected = mCurItem != item; //the old line
    to
    final boolean dispatchSelected = mCurItem != item || mFirstLayout; //the new line
    

    次に、独自の ViewPager を使用します。

  2. 意識的に setCurrentItem(0) を呼び出し、OnPageChangedListener への参照があるため、自分で onPageSelected() をディスパッチします。

  3. 听楼下怎么说...

于 2013-07-17T08:18:12.793 に答える
0

onPageSelected最初に開かれたページではトリガーされません。この場合、必要なすべてのアクションを手動で実行します。また、への呼び出しもonPageSelected(0)機能するはずだと思います。

于 2012-08-03T11:47:58.510 に答える
0

ViewPager位置が 0 から 0 に変更されたときに、リスナーを拡張して自分で呼び出すことができます

public class BetterViewPager extends ViewPager {

    public BetterViewPager(Context context, AttributeSet attrs) {
            super(context, attrs);
        }

        // we some the listner
        protected OnPageChangeListener listener;

        @Override
        public void setOnPageChangeListener(OnPageChangeListener listener) {
            super.setOnPageChangeListener(listener);
            this.listener = listener;
        }

        @Override
        public void setCurrentItem(int item) {
            // when you pass set current item to 0,
            // the listener won't be called so we call it on our own
            boolean invokeMeLater = false;

            if(super.getCurrentItem() == 0 && item == 0)
                invokeMeLater = true;

            super.setCurrentItem(item);

            if(invokeMeLater && listener != null)
                listener.onPageSelected(0);
        }

}
于 2013-07-16T09:14:29.833 に答える
0

ViewPager がフラグメント内にある場合は、onViewCreated メソッドで mPager.setOnPageChangeListener(this) を呼び出します。

于 2018-05-15T00:10:32.127 に答える