Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

Cách tạo văn bản phân trang (pagination) trong Android

Giới thiệu

Hướng dẫn này trình bày cách triển khai tính năng phân trang văn bản (text pagination) trong Android, cho phép chia nội dung dài thành nhiều trang để hiển thị dễ đọc hơn.

Các bước thực hiện

Bước 1: Tạo dự án mới

Mở Android Studio, chọn File → New Project và điền thông tin cần thiết.

Bước 2: Thiết kế giao diện (res/layout/activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="16dp"
    android:paddingTop="16dp"
    android:paddingRight="16dp"
    android:paddingBottom="16dp">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <Button
            android:id="@+id/btn_back"
            style="?android:attr/buttonBarButtonStyle"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="@android:color/transparent" />
        <Button
            android:id="@+id/btn_forward"
            style="?android:attr/buttonBarButtonStyle"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="@android:color/transparent" />
    </LinearLayout>
    <TextView
        android:id="@+id/tv"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</RelativeLayout>

Bước 3: Logic chính (src/MainActivity.java)

package app.com.sample;

import android.graphics.Color;
import android.graphics.Typeface;
import android.os.Bundle;
import android.text.Html;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import android.text.style.RelativeSizeSpan;
import android.text.style.StyleSpan;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {
    private TextView mTextView;
    private Pagination mPagination;
    private CharSequence mText;
    private int mCurrentIndex = 0;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        mTextView = findViewById(R.id.tv);
        
        // Chuẩn bị nội dung văn bản có định dạng
        Spanned htmlString = Html.fromHtml(getString(R.string.html_string));
        Spannable spanString = new SpannableString(getString(R.string.long_string));
        
        // Áp dụng style cho đoạn đầu
        spanString.setSpan(new ForegroundColorSpan(Color.BLUE), 0, 24, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        spanString.setSpan(new RelativeSizeSpan(2f), 0, 24, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        spanString.setSpan(new StyleSpan(Typeface.MONOSPACE.getStyle()), 0, 24, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        
        // Áp dụng style cho đoạn cuối
        spanString.setSpan(new ForegroundColorSpan(Color.BLUE), 700, spanString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        spanString.setSpan(new RelativeSizeSpan(2f), 700, spanString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        spanString.setSpan(new StyleSpan(Typeface.MONOSPACE.getStyle()), 700, spanString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        
        mText = TextUtils.concat(htmlString, spanString);
        
        // Khởi tạo phân trang sau khi layout hoàn tất
        mTextView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                mTextView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                mPagination = new Pagination(
                    mText, 
                    mTextView.getWidth(),
                    mTextView.getHeight(),
                    mTextView.getPaint(),
                    mTextView.getLineSpacingMultiplier(),
                    mTextView.getLineSpacingExtra(),
                    mTextView.getIncludeFontPadding()
                );
                update();
            }
        });
        
        // Nút quay lại trang trước
        findViewById(R.id.btn_back).setOnClickListener(v -> {
            mCurrentIndex = (mCurrentIndex > 0) ? mCurrentIndex - 1 : 0;
            update();
        });
        
        // Nút chuyển trang tiếp theo
        findViewById(R.id.btn_forward).setOnClickListener(v -> {
            mCurrentIndex = (mCurrentIndex < mPagination.size() - 1) ? mCurrentIndex + 1 : mPagination.size() - 1;
            update();
        });
    }
    
    private void update() {
        final CharSequence text = mPagination.get(mCurrentIndex);
        if (text != null) mTextView.setText(text);
    }
}

Bước 4: Lớp phân trang (src/Pagination.java)

package app.com.sample;

import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import java.util.ArrayList;
import java.util.List;

class Pagination {
    private final boolean mIncludePad;
    private final int mWidth;
    private final int mHeight;
    private final float mSpacingMult;
    private final float mSpacingAdd;
    private final CharSequence mText;
    private final TextPaint mPaint;
    private final List<CharSequence> mPages;
    
    Pagination(CharSequence text, int pageW, int pageH, TextPaint paint, 
               float spacingMult, float spacingAdd, boolean inclidePad) {
        this.mText = text;
        this.mWidth = pageW;
        this.mHeight = pageH;
        this.mPaint = paint;
        this.mSpacingMult = spacingMult;
        this.mSpacingAdd = spacingAdd;
        this.mIncludePad = inclidePad;
        this.mPages = new ArrayList<>();
        layout();
    }
    
    private void layout() {
        final StaticLayout layout = new StaticLayout(
            mText, mPaint, mWidth, Layout.Alignment.ALIGN_NORMAL, 
            mSpacingMult, mSpacingAdd, mIncludePad
        );
        final int lines = layout.getLineCount();
        final CharSequence text = layout.getText();
        int startOffset = 0;
        int height = mHeight;
        
        for (int i = 0; i < lines; i++) {
            if (height < layout.getLineBottom(i)) {
                // Vượt quá chiều cao trang, tạo trang mới
                addPage(text.subSequence(startOffset, layout.getLineStart(i)));
                startOffset = layout.getLineStart(i);
                height = layout.getLineTop(i) + mHeight;
            }
            if (i == lines - 1) {
                // Trang cuối cùng
                addPage(text.subSequence(startOffset, layout.getLineEnd(i)));
                return;
            }
        }
    }
    
    private void addPage(CharSequence text) {
        mPages.add(text);
    }
    
    int size() {
        return mPages.size();
    }
    
    CharSequence get(int index) {
        return (index >= 0 && index < mPages.size()) ? mPages.get(index) : null;
    }
}

Bước 5: Cấu hình Manifest (androidManifest.xml)

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
    package="app.com.sample">
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

Chạy ứng dụng

Kết nối thiết bị Android, nhấn Run trong Android Studio. Sử dụng hai nút transparan bên trái/phải để điều hướng giữa các trang.

Cách tạo văn bản phân trang (pagination) trong Android

Cách tạo văn bản phân trang (pagination) trong Android