IT Share you

setCurrentItem (0)을 호출 할 때 onPageSelected가 트리거되지 않습니다.

shareyou 2020. 12. 3. 20:49
반응형

setCurrentItem (0)을 호출 할 때 onPageSelected가 트리거되지 않습니다.


많은 사진을 표시하는 ViewPager가있는 활동이 있습니다. ViewPager가 시작되면 사용자가 이전 활동에서 선택한 항목에 따라 ViewPager의 위치가 설정됩니다. 갤러리와 비슷합니다.

새 페이지가 선택 될 때마다, 즉 활동이 처음 열릴 때 또는 사용자가 새 페이지로 슬라이드 할 때마다 onPageSelected가 호출되기를 원합니다.

다음과 같이 시작점을 설정했습니다.

 mPager.setCurrentItem(index);

onPageSelected를 트리거하지 않기 때문에 인덱스가 0으로 설정된 setCurrentItem이 호출되는 경우를 제외하고 모든 것이 작동합니다.

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

그래서 제 질문은; 이것이 버그입니까? 그렇다면 어떻게해야합니까?


지금까지 찾은 가장 깨끗한 솔루션은 ViewPager에서 설정 한 onPageChangeListener에 대한 참조를 가져 오는 것입니다 (ViewPager.getOnPageChangeListener () 메서드가 있다고 생각하지 않기 때문에), 그런 다음 ViewPager의 어댑터를 설정 한 후 , 전화 :

onPageChangeListener.onPageSelected(viewPager.getCurrentItem());

그러나 현재 인덱스에있는 페이지의 조각은 아직 인스턴스화되지 않았으므로 (적어도 FragmentStatePagerAdapter를 사용하는 경우) 실행 가능한 ala로 래핑해야 할 수 있습니다.

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

또한 onPageSelected 처리기 내에서 조각에 대한 참조가 필요한 경우 직접 수행해야합니다. 인스턴스화 및 제거 메서드를 재정의하고 SparseArray에서 조각을 추가 / 제거하는 FragmentStatePagerAdapter에 추상 기본 클래스를 사용합니다.


좋아, 그래서 이것이 버그 (또는 기능)인지 알아낼 수 없었다. 하지만 문제에 대한 가능한 해결책이 어떻게 보일 수 있는지를 공유하고 싶습니다 ..

Activity의 메서드에서 수행하려는 기능을 작성한 다음 onPageSelected 메서드에서이를 호출합니다.

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

그리고 전화 직후

setCurrentItem(index);

활동에서 다음 if 문을 추가하십시오.

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

너무 예쁘지는 않지만 누군가에게 도움이되기를 바랍니다. :)


사실 나는 이것이 BUG라고 생각합니다. 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. 听 楼下 怎么 说 ...


다음 솔루션이 저에게 효과적입니다. 즉, 뷰 페이저가 처음로드 될 때와 사용자 스크롤 또는 setCurrentItem (x) 호출에서 모든 후속 선택에 대해 위치 0에서 콜백을받습니다. 나는 원하지 않는 행동을 관찰하지 않았습니다.

viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

                if (positionOffsetPixels == 0) {
                 //Do something on selected page at position
                }

            }

            @Override
            public void onPageSelected(int position) {}

            @Override
            public void onPageScrollStateChanged(int state) {}
        });

onPageSelected is not triggered for page which is opened first. For this case I manually perform all needed actions. Also, I suppose that call to onPageSelected(0) should work too.


You can extend the ViewPager and call the Listener by yourself when the position is changed from 0 to 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);
        }

}

public class PageChangeListener implements ViewPager.OnPageChangeListener {
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    @Override
    public void onPageSelected(int position) {
    }

    @Override
    public void onPageScrollStateChanged(int state) {
        if (state == ViewPager.SCROLL_STATE_IDLE && getCurrentItem() == 0) {
         //this indicate viewpager finish scroll and page at position 0 is selected.
        }

The simplest solution will be using of function e.g.

    viewpager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {

        @Override
        public void onPageScrollStateChanged(int state) {}

        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}

        @Override
        public void onPageSelected(int position) {
            onPage(position);
        }
    });

    // call first time
    onPage(0); 

    private void onPage(int position) {
        //...
    }

If the ViewPager is in a fragment, in the onViewCreated method, call mPager.setOnPageChangeListener(this)


if you don't care screen animotion try

pager.setCurrentItem(1);
pager.setCurrentItem(0);

참고URL : https://stackoverflow.com/questions/11794269/onpageselected-isnt-triggered-when-calling-setcurrentitem0

반응형