一、需求

- 分頁器需要包含:【上一頁按鈕】、【下一頁按鈕】、【當前頁碼 / 總頁數】、【每頁條數】、【總記錄數】
-
點擊【上一頁按鈕】,渲染上一頁的數據,如果當前頁碼為第一頁,則禁用【上一頁按鈕】
-
點擊【下一頁按鈕】,渲染下一頁的數據,如果當前頁碼為最后一頁,則禁用【下一頁按鈕】
-
點擊【當前頁碼 / 總頁數】,彈出對話框,可以選擇頁碼,選擇頁碼后,渲染該頁碼的數據
二、具體實現
1、Entity
- Student.java
package com.my.paging.model.entity;public class Student {private int id;private String name;private int age;public Student() {}public Student(int id, String name, int age) {this.id = id;this.name = name;this.age = age;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}
- PageResult.java
package com.my.paging.model.entity;import java.util.List;public class PageResult<T> {private int pageNum;private int pageSize;private int pageTotal;private int total;private List<T> data;public PageResult() {}public PageResult(int pageNum, int pageSize, int pageTotal, int total, List<T> data) {this.pageNum = pageNum;this.pageSize = pageSize;this.pageTotal = pageTotal;this.total = total;this.data = data;}public int getPageNum() {return pageNum;}public void setPageNum(int pageNum) {this.pageNum = pageNum;}public int getPageSize() {return pageSize;}public void setPageSize(int pageSize) {this.pageSize = pageSize;}public int getPageTotal() {return pageTotal;}public void setPageTotal(int pageTotal) {this.pageTotal = pageTotal;}public int getTotal() {return total;}public void setTotal(int total) {this.total = total;}public List<T> getData() {return data;}public void setData(List<T> data) {this.data = data;}
}
2、Repository
- StudentRepository.java
package com.my.paging.repository;import com.my.paging.model.entity.PageResult;
import com.my.paging.model.entity.Student;import java.util.ArrayList;
import java.util.List;public class StudentRepository {private List<Student> students;private static final int TOTAL = 100;public StudentRepository() {students = new ArrayList<>();for (int i = 0; i < TOTAL; i++) {int id = i + 1;students.add(new Student(id,"test " + id,20));}}public PageResult<Student> getStudents(int pageNum, int pageSize) {int start = (pageNum - 1) * pageSize;int end = start + pageSize;if (end > TOTAL) {end = TOTAL;}List<Student> data = students.subList(start, end);PageResult<Student> pageResult = new PageResult<>();pageResult.setPageNum(pageNum);pageResult.setPageSize(pageSize);pageResult.setPageTotal((TOTAL + pageSize - 1) / pageSize);pageResult.setTotal(TOTAL);pageResult.setData(data);return pageResult;}
}
3、RecyclerView
(1)Layout
- recycler_view_item_student.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:padding="16dp"><TextViewandroid:id="@+id/tv_id"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textSize="16sp" /><TextViewandroid:id="@+id/tv_name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="4dp"android:textSize="18sp"android:textStyle="bold" /><TextViewandroid:id="@+id/tv_age"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="4dp"android:textSize="16sp" />
</LinearLayout>
(2)Adapter
- StudentRecyclerViewAdapter.java
package com.my.paging.adapter;import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;import com.my.paging.R;
import com.my.paging.model.entity.Student;import java.util.List;public class StudentRecyclerViewAdapter extends RecyclerView.Adapter<StudentRecyclerViewAdapter.StudentRecyclerViewViewHolder> {private List<Student> students;public StudentRecyclerViewAdapter() {}public void setStudents(List<Student> students) {this.students = students;notifyDataSetChanged();}@NonNull@Overridepublic StudentRecyclerViewViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {View view = View.inflate(parent.getContext(), R.layout.recycler_view_item_student, null);return new StudentRecyclerViewViewHolder(view);}@Overridepublic void onBindViewHolder(@NonNull StudentRecyclerViewViewHolder holder, int position) {holder.bind(students.get(position));}@Overridepublic int getItemCount() {if (students == null) return 0;return students.size();}static class StudentRecyclerViewViewHolder extends RecyclerView.ViewHolder {private TextView tvId;private TextView tvName;private TextView tvAge;public StudentRecyclerViewViewHolder(@NonNull View itemView) {super(itemView);tvId = itemView.findViewById(R.id.tv_id);tvName = itemView.findViewById(R.id.tv_name);tvAge = itemView.findViewById(R.id.tv_age);}public void bind(Student student) {tvId.setText(String.valueOf(student.getId()));tvName.setText(student.getName());tvAge.setText(String.valueOf(student.getAge()));}}
}
4、PaginationView
(1)Layout
- pagination_view.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:padding="8dp"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center"android:orientation="horizontal"><Buttonandroid:id="@+id/btn_prev"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginEnd="8dp"android:enabled="false"android:text="上一頁" /><LinearLayoutandroid:id="@+id/ll_page_num_and_page_total"android:layout_width="wrap_content"android:layout_height="wrap_content"android:padding="8dp"><TextViewandroid:id="@+id/tv_page_num"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="1" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="/" /><TextViewandroid:id="@+id/tv_page_total"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="1" /></LinearLayout><Buttonandroid:id="@+id/btn_next"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginStart="8dp"android:text="下一頁" /></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center"android:orientation="horizontal"><LinearLayoutandroid:id="@+id/ll_page_size"android:layout_width="wrap_content"android:layout_height="wrap_content"><TextViewandroid:id="@+id/tv_page_size"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="10"android:textSize="12sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text=" 條/頁"android:textSize="12sp" /></LinearLayout><LinearLayoutandroid:id="@+id/ll_total"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginStart="16dp"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="共 "android:textSize="12sp" /><TextViewandroid:id="@+id/tv_total"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="0"android:textSize="12sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text=" 條"android:textSize="12sp" /></LinearLayout></LinearLayout>
</LinearLayout>
(2)Observer
- OnPageChangeObserver.java
package com.my.paging.customview.observer;public interface OnPageChangeObserver {void onPageChange(int newPageNum);
}
(3)Code
- PaginationView.java
package com.my.paging.customview;import android.app.AlertDialog;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;import androidx.annotation.Nullable;import com.my.paging.R;
import com.my.paging.customview.observer.OnPageChangeObserver;public class PaginationView extends LinearLayout {private Context context;private TextView tvPageNum;private TextView tvPageSize;private TextView tvPageTotal;private TextView tvTotal;private Button btnPrev;private Button btnNext;private LinearLayout llPageNumAndPageTotal;private int pageNum = 1;private int pageSize = 10;private int pageTotal = 0;private int total = 0;private String[] pageItems;private OnPageChangeObserver onPageChangeObserver;public PaginationView(Context context) {super(context);init(context);}public PaginationView(Context context, @Nullable AttributeSet attrs) {super(context, attrs);init(context);}public PaginationView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(context);}public PaginationView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {super(context, attrs, defStyleAttr, defStyleRes);init(context);}private void init(Context context) {this.context = context;LayoutInflater.from(context).inflate(R.layout.pagination_view, this, true);tvPageNum = findViewById(R.id.tv_page_num);tvPageSize = findViewById(R.id.tv_page_size);tvPageTotal = findViewById(R.id.tv_page_total);tvTotal = findViewById(R.id.tv_total);btnPrev = findViewById(R.id.btn_prev);btnNext = findViewById(R.id.btn_next);llPageNumAndPageTotal = findViewById(R.id.ll_page_num_and_page_total);btnPrev.setOnClickListener(v -> {pageNum--;tvPageNum.setText(String.valueOf(pageNum));if (onPageChangeObserver != null) {onPageChangeObserver.onPageChange(pageNum);}});btnNext.setOnClickListener(v -> {pageNum++;tvPageNum.setText(String.valueOf(pageNum));if (onPageChangeObserver != null) {onPageChangeObserver.onPageChange(pageNum);}});llPageNumAndPageTotal.setOnClickListener(view -> {pageItems = new String[pageTotal];for (int i = 0; i < pageTotal; i++) {pageItems[i] = "第 " + (i + 1) + " 頁";}AlertDialog.Builder builder = new AlertDialog.Builder(context);builder.setTitle("選擇頁碼");builder.setSingleChoiceItems(pageItems, -1, (dialog, which) -> {dialog.dismiss();pageNum = which + 1;tvPageNum.setText(String.valueOf(pageNum));if (onPageChangeObserver != null) {onPageChangeObserver.onPageChange(pageNum);}});AlertDialog alertDialog = builder.create();alertDialog.show();});}public void setOnPageChangeObserver(OnPageChangeObserver onPageChangeObserver) {this.onPageChangeObserver = onPageChangeObserver;}public void render(int pageNum, int pageSize, int pageTotal, int total) {this.pageNum = pageNum;this.pageSize = pageSize;this.pageTotal = pageTotal;this.total = total;tvPageNum.setText(String.valueOf(pageNum));tvPageSize.setText(String.valueOf(pageSize));tvPageTotal.setText(String.valueOf(pageTotal));tvTotal.setText(String.valueOf(total));btnPrev.setEnabled(pageNum > 1);btnNext.setEnabled(pageNum < pageTotal);}
}
5、Activity
(1)Layout
- activity_pagination_view_test.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/main"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".PaginationViewTestActivity"><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/rv_student"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1" /><com.my.paging.customview.PaginationViewandroid:id="@+id/pv_student"android:layout_width="match_parent"android:layout_height="wrap_content" />
</LinearLayout>
(2)Code
- PaginationViewTestActivity.java
package com.my.paging;import android.os.Bundle;import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;import com.my.paging.adapter.StudentRecyclerViewAdapter;
import com.my.paging.customview.PaginationView;
import com.my.paging.model.entity.PageResult;
import com.my.paging.model.entity.Student;
import com.my.paging.repository.StudentRepository;import java.util.List;public class PaginationViewTestActivity extends AppCompatActivity {private RecyclerView rvStudent;private PaginationView pvStudent;private int pageNum = 1;private int pageSize = 15;private int pageTotal = 0;private int total = 0;private List<Student> students;private StudentRepository studentRepository;private StudentRecyclerViewAdapter studentRecyclerViewAdapter;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);EdgeToEdge.enable(this);setContentView(R.layout.activity_pagination_view_test);ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);return insets;});rvStudent = findViewById(R.id.rv_student);pvStudent = findViewById(R.id.pv_student);pvStudent.setOnPageChangeObserver(newPageNum -> {pageNum = newPageNum;doRequest();doRender();});studentRepository = new StudentRepository();studentRecyclerViewAdapter = new StudentRecyclerViewAdapter();rvStudent.setAdapter(studentRecyclerViewAdapter);LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);rvStudent.setLayoutManager(linearLayoutManager);DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(this, DividerItemDecoration.VERTICAL);rvStudent.addItemDecoration(dividerItemDecoration);doRequest();doRender();}private void doRequest() {PageResult<Student> pageResult = studentRepository.getStudents(pageNum, pageSize);pageTotal = pageResult.getPageTotal();total = pageResult.getTotal();students = pageResult.getData();}private void doRender() {pvStudent.render(pageNum, pageSize, pageTotal, total);studentRecyclerViewAdapter.setStudents(students);}
}