티스토리 뷰

반응형
SMALL

ViewPager Rx 이용하여 Auto Scroll 기능 구현

 

implementation 'io.reactivex:rxandroid:1.2.1'

 

자동 롤링을 하기 위해 무한 스크롤 구현 

간단하게 사용할 수 있는 방법으론 

아이템 갯수를 100개 혹은 1000개를 만들고, ViewPager 처음 셋팅 할 때 50 혹은 500 에 셋팅 해 놓고 시작.

양쪽으로 50번 혹은 500 번을 가야 끝나는 스크롤 이라 사용자 입장으론 무한 스크롤 인 것 처럼 보임.

메모리는 PagerAdapter 에서 destoryItem 에서 관리하므로 괜찮

 

그럼 

 

1. Timer 를 이용하여 시간 이후 setCurrentItem 으로 페이징 처리.

무한 스크롤을 처음 시작 하는 곳과 끝나는 곳을 정확히 정해줘야 함.

 

아래 코드는 Switch 를 사용하여 on / off 일 때 끄고 키는 방향으로 하고, 

혹시나 모를 사용자가 스와이프 및 스크롤 할 때에는 오토스크롤 기능을 잠시 꺼두는 방향으로 코드 적용.

private Subscription mSubscription;
private boolean isAutoScroll;

// 오토 스크롤 스위치
        sw_rxjava.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    isAutoScroll = true;
                    autoScrollStart(isAutoScroll);
                } else {
                    isAutoScroll = false;
                    autoScrollStop();
                }
            }
        });
        
        rxjava_viewpager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            }

            @Override
            public void onPageSelected(int position) {
            }

            @Override
            public void onPageScrollStateChanged(int state) {
                switch (state) {
                    case ViewPager.SCROLL_STATE_IDLE: {
                        autoScrollStart(isAutoScroll);  // 스크롤이 끝났다거나, 아니면 현재 멈춰져 있을 경우 오토 스크롤 시작.
                        break;
                    }
                    case ViewPager.SCROLL_STATE_DRAGGING: { // 사용자가 손으로 스크롤 시 오토 스크롤 잠깐 정지.
                        autoScrollStop();
                        break;
                    }
                }
            }
        });
        

private void autoScrollStart(boolean isAutoScroll) {
        if (isAutoScroll) {
            if (mSubscription != null) mSubscription.unsubscribe();
            mSubscription = Observable.timer(500, TimeUnit.MILLISECONDS)    // 0.5초 뒤에 스크롤 시작.
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Action1<Long>() {
                                   @Override
                                   public void call(Long aLong) {
                                       rxjava_viewpager.setCurrentItem(rxjava_viewpager.getCurrentItem() + 1);
                                   }
                               }
                    );
        }
}

private void autoScrollStop() {
    if (mSubscription != null) {
        mSubscription.unsubscribe();
    }
}

 

반응형

2. 오토 스크롤 일 때 스크롤 시간 설정

Scroller를 커스텀 하고, ViewPager 에 커스텀 된 Scroller 를 적용 한다.. 

사실 이 부분은 아직 이해가 안되지만, 나중에 쓸일이 있을 까봐 기록 해둠.

 

public class ScrollerCustomDuration extends Scroller {

    private int mScrollFactor;

    public ScrollerCustomDuration(Context context) {
        super(context);
    }

    public ScrollerCustomDuration(Context context, Interpolator interpolator) {
        super(context, interpolator);
    }

    public ScrollerCustomDuration(Context context, Interpolator interpolator, boolean flywheel) {
        super(context, interpolator, flywheel);
    }

    /**
     * Set the factor by which the duration will change
     */
    public void setScrollDurationFactor(int scrollFactor) {
        mScrollFactor = scrollFactor;
    }

    @Override
    public void startScroll(int startX, int startY, int dx, int dy, int duration) {
        // duration default 200
        if (mScrollFactor != 0) {
            super.startScroll(startX, startY, dx, dy, (int) (mScrollFactor));
        } else {
            super.startScroll(startX, startY, dx, dy, (int) (duration));
        }

    }

}

 

package com.example.viewpagerexample.auto_scroll;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Interpolator;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.viewpager.widget.ViewPager;

import java.lang.reflect.Field;

public class WrapViewPager extends ViewPager {

    public WrapViewPager(@NonNull Context context) {
        super(context);
        postInitViewPager();
    }

    public WrapViewPager(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        postInitViewPager();
    }

    private ScrollerCustomDuration mScroller = null;

    /**
     * Override the Scroller instance with our own class so we can change the
     * duration
     */
    private void postInitViewPager() {
        try {
            Field scroller = ViewPager.class.getDeclaredField("mScroller");
            scroller.setAccessible(true);
            Field interpolator = ViewPager.class.getDeclaredField("sInterpolator");
            interpolator.setAccessible(true);

            mScroller = new ScrollerCustomDuration(getContext(),
                    (Interpolator) interpolator.get(null));
            scroller.set(this, mScroller);
        } catch (Exception e) {
        }
    }

    public void setScrollDurationFactor(int scrollFactor) {
        mScroller.setScrollDurationFactor(scrollFactor);
    }


}

 

viewpager.setScrollDurationFactor(1000);	// MILLISECONDS Duration

viewpager.setScrollDurationFactor(0);	// Default Duration

 

Sample Example Github

 

 

참고 : https://stackoverflow.com/questions/10812009/change-viewpager-animation-duration-when-sliding-programmatically

반응형
LIST
댓글