Be Developer

[Android] Infinite/Endless Scrolling (무한 스크롤) 본문

Android

[Android] Infinite/Endless Scrolling (무한 스크롤)

yujin_dev 2020. 4. 8. 12:40
반응형

트위터나 페이스북에서 흔히 볼 수 있는 무한 스크롤을 구현해보자.

 

1. RecyclerView를 구현하고

2. Scroll이 끝에 닿았을 경우 NULL 요소를 추가하고 Adapter에 알린다.

3. 새로운 데이터 요소 집합을 가져온 후

4. NULL요소를 제거 한 후 추가하고 Adapter에 알린다.

 

코드

RecyclerViewAdapter.java

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private final int VIEW_TYPE_ITEM = 0;
    private final int VIEW_TYPE_LOADING = 1;

    private List<String> items;

    public RecyclerViewAdapter(List<String> items) {
        this.items = items;
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        if (viewType == VIEW_TYPE_ITEM) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_row, parent, false);
            return new ItemViewHolder(view);
        } else {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_loading, parent, false);
            return new LoadingViewHolder(view);
        }
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        if (holder instanceof ItemViewHolder) {
            populateItemRows((ItemViewHolder) holder, position);
        } else if (holder instanceof LoadingViewHolder) {
            showLoadingView((LoadingViewHolder) holder, position);
        }
    }

    @Override
    public int getItemViewType(int position) {
        return items.get(position) == null ? VIEW_TYPE_LOADING : VIEW_TYPE_ITEM;
    }

    @Override
    public int getItemCount() {
        return items == null ? 0 : items.size();
    }

    private void showLoadingView(LoadingViewHolder holder, int position) {

    }

    private void populateItemRows(ItemViewHolder holder, int position) {
        String item = items.get(position);
        holder.setItem(item);
    }

    private class ItemViewHolder extends RecyclerView.ViewHolder {
        private TextView textView;

        public ItemViewHolder(@NonNull View itemView) {
            super(itemView);
            textView = itemView.findViewById(R.id.textView);
        }

        public void setItem(String item) {
            textView.setText(item);
        }
    }

    private class LoadingViewHolder extends RecyclerView.ViewHolder {
        private ProgressBar progressBar;

        public LoadingViewHolder(@NonNull View itemView) {
            super(itemView);
            progressBar = itemView.findViewById(R.id.progressBar);
        }
    }
}

 

MainActivity.java

public class MainActivity extends AppCompatActivity {
    //..

    private void initScrollListener() {
        recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
            }

            @Override
            public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);

                LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();

                if (!isLoading) {
                    if (layoutManager != null && layoutManager.findLastCompletelyVisibleItemPosition() == items.size() - 1) {
                        //리스트 마지막
                        loadMore();
                        isLoading = true;
                    }
                }
            }
        });
    }

    private void loadMore() {
        items.add(null);
        adapter.notifyItemInserted(items.size() - 1);

        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                items.remove(items.size() - 1);
                int scrollPosition = items.size();
                adapter.notifyItemRemoved(scrollPosition);
                int currentSize = scrollPosition;
                int nextLimit = currentSize + 10;

                while (currentSize - 1 < nextLimit) {
                    items.add("Item " + currentSize);
                    currentSize++;
                }

                adapter.notifyDataSetChanged();
                isLoading = false;
            }
        }, 2000);
    }
}

RecyclerViewAdapter에서 우리는 두 개의 ViewHolder를 사용한다.

1. ItemViewHolder

  • RecyclerView 요소 ViewHolder

2. LoadingViewHolder

  • NULL로 추가된 요소 ViewHolder

RecyclerView의 ScrollListener에서 리스트의 마지막을 감지하고 NULL요소를 추가한다.

Adapter에 알리게 되면 LoadingViewHolder를 통해 로딩 아이템을 볼 수 있다.

그 후, 추가되는 데이터 요소 집합을 가져오고 NULL로 추가되었던 아이템 제거 한 후 추가한다.

Adapter에 알리게 되면 다음 스크롤이 진행된다.

 

 

 

전체 소스는 이 곳에서 볼 수 있다.

https://github.com/yujinK/Endless-RecyclerView.git

 

참고 : https://www.journaldev.com/24041/android-recyclerview-load-more-endless-scrolling

 

반응형
Comments