728x90
RecylclerView에 기존 데이터를 담은 아이템과 함께 마지막 아이템을 스크롤 할 때 보여줄 Loading Progress Bar 아이템을 추가해 보겠습니다.
먼저 MainActivity에서 보여줄 레이아웃과 2가지 RecyclerView 아이템 레이아웃을 만듭니다
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recy"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="50dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="28dp"
android:text="목록"
android:textSize="24sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
recy_item.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/number"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:gravity="center"
android:text="TextView"
android:textColor="@color/black"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
progress_item.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
RecyclerView에 사용할 Adapter 클래스를 만들어 줍니다
public class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> {
// 두가지 아이템을 구분하기 위해 ViewType 변수 선언
final int VIEW_TYPE_POSITIVE = 1;
final int VIEW_TYPE_NEGATIVE = 0;
// 표시할 양수 ArrayList
ArrayList<Integer> positiveNumberList;
// Adapter 생성자를 사용해 ArrayList 초기화
public Adapter(ArrayList<Integer> positiveNumbers){
positiveNumberList = positiveNumbers;
}
// ViewHolder 셍성 메소드
@NonNull
@Override
public Adapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = null;
// ViewType을 확인한 뒤 그에 맞는 ViewHolder 생성
if (viewType == VIEW_TYPE_POSITIVE) {
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recy_item, parent, false);
// 양수를 표시할 ViewHolder
return new PositiveNumberViewHolder(view);
} else {
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.progress_item, parent, false);
// Loading Progress bar를 표시할 ViewHolder
return new ProgressViewHolder(view);
}
}
// ViewHolder에 데이터 바인딩 메소드
@Override
public void onBindViewHolder(@NonNull Adapter.ViewHolder holder, int position) {
// 데이터를 바인딩할 ViewHolder가 양수를 표시하는 ViewHolder일 경우
if (holder instanceof PositiveNumberViewHolder){
// 현재 ArrayList에 담겨있는 양수 설정
((PositiveNumberViewHolder) holder).getPositiveNumber().setText(String.valueOf(positiveNumberList.get(position)));
}
}
// ViewType을 결정하는 메소드
@Override
public int getItemViewType(int position) {
if (positiveNumberList.get(position) != -1)
// ArrayList에서 position에 위치한 정수가 -1이 아닐 경우 ViewType을 VIEW_TYPE_POSITIVE로 설정
return VIEW_TYPE_POSITIVE;
else
// ArrayList에서 position에 위치한 정수가 -1이 아닐 경우 ViewType을 VIEW_TYPE_NEGATIVE로 설정
return VIEW_TYPE_NEGATIVE;
}
// 현재 목록에 표시해야할 아이템의 개수를 반환
@Override
public int getItemCount() {
return positiveNumberList.size();
}
// Loading Progress bar를 보여주기 위해 임의로 -1을 ArrayList 마지막에 추가하는 메소드
public void addProgress() {
positiveNumberList.add(-1);
notifyItemInserted(positiveNumberList.size() - 1);
}
// 임의로 보여준 Loading Progress bar를 제거하기 위해 ArrayList에서 마지막 정수를 제거하는 메소드
public void removeProgress() {
positiveNumberList.remove(positiveNumberList.size() - 1);
notifyItemRemoved(positiveNumberList.size());
}
// 목록에 보여줄 데이터를 추가하는 메소드
public void addNumbers(ArrayList<Integer> positiveNumbers){
for(int i = 0; i < positiveNumbers.size(); i++){
positiveNumberList.add(positiveNumbers.get(i));
notifyItemInserted(positiveNumberList.size()-1);
}
}
// 부모 뷰홀더를 상속한 Loading Progress bar 뷰홀더
public class ProgressViewHolder extends ViewHolder{
public ProgressViewHolder(View itemView){
super(itemView);
}
}
// 부모 뷰홀더를 상속한 양수 뷰홀더
public class PositiveNumberViewHolder extends ViewHolder{
// 양수를 표시할 TextView 변수
TextView positiveNumber;
public PositiveNumberViewHolder(View itemView){
super(itemView);
positiveNumber = (TextView) itemView.findViewById(R.id.number);
}
// TextView 반환 메소드
public TextView getPositiveNumber(){
return positiveNumber;
}
}
// 2개의 뷰홀더를 사용하기 위해 부모 뷰홀더를 만듬
public class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(@NonNull View itemView) {
super(itemView);
}
}
}
MainActivity 클래스에 onCreate 안에 코드를 작성해줍니다
public class MainActivity extends AppCompatActivity {
// 마지막으로 추가한 숫자를 저장할 변수
int lastNum;
// 연속 클릭 방지 시간 측정용 변수
private Long mLastClickTime = 0L;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 변수 초기화
lastNum = 0;
// 초기 양수 목록을 만들기 위해 ArrayList 생성
ArrayList<Integer> positiveNumberList = new ArrayList<>();
// ArrayList에 양수 추가
for(int i = 0; i < 20; i++){
lastNum++;
positiveNumberList.add(lastNum);
}
// 리사이클러뷰 초기화
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recy);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(MainActivity.this);
recyclerView.setLayoutManager(linearLayoutManager);
Adapter adapter = new Adapter(positiveNumberList);
recyclerView.setAdapter(adapter);
// 리사이클러뷰를 스크롤에 반응하는 리스너 설정
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
// ScrollState가 변경되었을 때 호출되는 메소드 (SCROLL_STATE_IDLE, SCROLL_STATE_DRAGGING, SCROLL_STATE_SETTLING)
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
// 최상단 또는 최하단에 있는 상태일 경우 실행
if(newState == RecyclerView.SCROLL_STATE_SETTLING){
// 최하단일 경우 실행
if(recyclerView.canScrollVertically(1)){
// 데이터를 추가하는 코드를 실행한지 1초가 지났으면 실행 (Loading Progress Bar를 보여주기 위해 코드 실행을 멈추는 Thread.sleep를 사용해서 임의로 추가)
if(SystemClock.elapsedRealtime() - mLastClickTime > 1000){
mLastClickTime = SystemClock.elapsedRealtime(); // 코드 실행시 현재 시간 저장
// 목록에 Loading progress bar 추가
adapter.addProgress();
// Thread.sleep을 사용하기 Thread 생성 후 시작
new Thread(){
@Override
public void run() {
super.run();
try {
// 0.75초간 해당 스레드 정지
Thread.sleep(750);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
// 목록에 추가할 양수 ArrayList 생성
ArrayList numbers = new ArrayList();
for(int i = 0; i < 20; i++){
lastNum++;
numbers.add(lastNum);
}
runOnUiThread(new Runnable() {
@Override
public void run() {
// 양수 데이터를 추가하기 전 목록에 Loading progress bar 제거
adapter.removeProgress();
// 양수 데이터 추가
adapter.addNumbers(numbers);
}
});
}
}.start();
}
}
}
}
});
}
}
이렇게 만들면 RecyclerView의 최하단 아이템까지 드래그할 경우 Loading Progress Bar를 보여주고 아이템을 추가해줍니다.
'안드로이드 자바' 카테고리의 다른 글
[Android][Java] FadingTextView 사용해서 일정시간마다 글자 바꿔주기 (0) | 2023.04.27 |
---|---|
[Android][Java] 스낵바(Snackbar) 커스텀 하기 (0) | 2023.04.26 |
[Android][Java] 네이버 지도에 현재 위치 표시하기 (0) | 2023.04.22 |
[Android][Java]Intent를 이용해 다른 앱으로 이동하기 (0) | 2023.04.19 |
[Android][Java] Socket.io를 사용해서 서버와 통신하기 (0) | 2023.04.18 |