1. Infinite Scroll이란

Infinite Scroll은 무한스크롤, 즉 유튜브나 페이스북, 트위터 등에서 스크롤이 끊임없이 이어지는 것을 말합니다.
브라우저 같은 경우 자바스크립트로 구현할 수 있겠고 안드로이드도 그런 식으로 만드는 것이 가능하겠으나 많이 사용되고 있으므로 여러가지 툴이 존재합니다. 그 중 구글이 제공하는 Recycler View를 이용해서 만들어보겠습니다.

2. Recycler View 이용


우선 Recycler View 라고 구글에서 제공해주는 좋은 재료가 있습니다.


import android.support.v7.widget.RecyclerView;
cs


그 다음 Listener를 달아줍니다.


public abstract class EndlessScrollListener extends RecyclerView.OnScrollListener {
}
cs


이렇게 RecyclerView.onScrollListener를 extends하여 구현합니다.

여기에 작업을 해주면 됩니다. 세부적인 옵션을 설정하겠습니다.


    private int visibleThreshold = 2;
    private int currentPage = 1;
    private int previousTotalItemCount = 0;
    private boolean loading = true;
    private int startingPageIndex = 1;
    private RecyclerView.LayoutManager mLayoutManager;
cs


변수의 이름대로 옵션을 설정했습니다.

그 다음엔 Scroll에 필요한 Listener를 등록하기 위해 layoutManager를 작성합니다.


    protected EndlessScrollListener(LinearLayoutManager layoutManager) {
        this.mLayoutManager = layoutManager;
    }
    
    public EndlessScrollListener(GridLayoutManager layoutManager) {
        this.mLayoutManager = layoutManager;
        visibleThreshold = visibleThreshold * layoutManager.getSpanCount();
    }
    
    public EndlessScrollListener(StaggeredGridLayoutManager layoutManager) {
        this.mLayoutManager = layoutManager;
        visibleThreshold = visibleThreshold * layoutManager.getSpanCount();
    }
cs

이렇게 여러가지 매니저를 처리하도록 합니다. visibleThreshold와 layoutManager의 getSpanCount()를 이용해서 visibleThreshold에 다시 값을 지정합니다.


그 다음 스크롤 후 마지막 항목 차례에서 벌어질 이벤트를 처리합니다. 이 부분을 통해 무한으로 스크롤되는 유저 경험을 제공합니다. 마지막으로 보이게 되는 아이템과 그 아이템의 위치를 이용해서 for 문을 구성하고 maxSize 변수에 값을 넣어 이벤트를 만들 것입니다.


    @Contract(pure = true)
    private int getLastVisibleItem(int[] lastVisibleItemPositions) {
        int maxSize = 0;
        for (int i = 0; i < lastVisibleItemPositions.length; i++) {
            if (i == 0) {
                maxSize = lastVisibleItemPositions[i];
            } else if (lastVisibleItemPositions[i] > maxSize) {
                maxSize = lastVisibleItemPositions[i];
            }
        }
        return maxSize;
    }
cs


3. 마지막 항목에서의 이벤트

마지막 항목까지 스크롤 되었을 때의 이벤트를 조금 더 세부적으로 설정합니다. lastVisibleItemPosition 변수를 만들어서 처리합니다.


    @Override
    public void onScrolled(RecyclerView view, int dx, int dy) {
        int lastVisibleItemPosition = 0;
        int totalItemCount = mLayoutManager.getItemCount();
        
        if (mLayoutManager instanceof StaggeredGridLayoutManager) {
            int[] lastVisibleItemPositions = ((StaggeredGridLayoutManager) mLayoutManager).findLastVisibleItemPositions(null);
            // get maximum element within the list
            lastVisibleItemPosition = getLastVisibleItem(lastVisibleItemPositions);
        } else if (mLayoutManager instanceof GridLayoutManager) {
            lastVisibleItemPosition = ((GridLayoutManager) mLayoutManager).findLastVisibleItemPosition();
        } else if (mLayoutManager instanceof LinearLayoutManager) {
            lastVisibleItemPosition = ((LinearLayoutManager) mLayoutManager).findLastVisibleItemPosition();
        }
        
        if (totalItemCount < previousTotalItemCount) {
            this.currentPage = this.startingPageIndex;
            this.previousTotalItemCount = totalItemCount;
            if (totalItemCount == 0) {
                this.loading = true;
            }
        }
        if (loading && (totalItemCount > previousTotalItemCount)) {
            loading = false;
            previousTotalItemCount = totalItemCount;
        }
        if (!loading && (lastVisibleItemPosition + visibleThreshold) > totalItemCount) {
            currentPage++;
            onLoadMore(currentPage, totalItemCount, view);
            loading = true;
        }
    }
cs


이렇게 한 후엔 스크롤이 반복적으로 reset될 state를 설정하면 됩니다.


    public void resetState() {
        this.currentPage = this.startingPageIndex;
        this.previousTotalItemCount = 0;
        this.loading = true;
    }
 
cs


그 다음에 마무리로 더 불러오기를 구현합니다. 여러가지 처리를 한 끝에 자동적으로 스크롤할 콘텐츠를 불러오게 됩니다. 사용자는 끊임없이 스크롤되는 것처럼 느끼게 됩니다.


    public abstract void onLoadMore(int page, int totalItemsCount, RecyclerView view);
cs


이렇게 끝맺을 수 있습니다.

+ Recent posts