Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Android

วิธีสร้างข้อความแบ่งหน้า (Pagination) ใน Android

การสร้างระบบแบ่งหน้าข้อความ (Text Pagination) ใน Android

ตัวอย่างนี้สาธิตวิธีการแบ่งข้อความยาวเป็นหลายหน้า (Pagination) พร้อมปุ่มนำทางหน้าก่อน/หน้าถัดไป โดยใช้ StaticLayout คำนวณการจัดวางข้อความ

ขั้นตอนที่ 1: สร้างโปรเจกต์ใหม่

เปิด Android Studio เลือก File → New Project และกรอกข้อมูลที่จำเป็น

ขั้นตอนที่ 2: จัดทำ Layout (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>

ขั้นตอนที่ 3: เพิ่มสตริงใน res/values/strings.xml

<resources>
    <string name="long_string">ข้อความยาวสำหรับทดสอบการแบ่งหน้า...</string>
    <string name="html_string"><b>ข้อความ HTML</b> สำหรับทดสอบ</string>
</resources>

ขั้นตอนที่ 4: เขียนโค้ดหลัก (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);
        
        // เตรียมข้อความพร้อมสไตล์
        Spanned htmlString = Html.fromHtml(getString(R.string.html_string));
        Spannable spanString = new SpannableString(getString(R.string.long_string));
        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);
        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);
        
        // รอให้ Layout วาดเสร็จก่อนคำนวณ Pagination
        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();
            }
        });
        
        // ปุ่มหน้าก่อน
        findViewById(R.id.btn_back).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mCurrentIndex = (mCurrentIndex > 0) ? mCurrentIndex - 1 : 0;
                update();
            }
        });
        
        // ปุ่มหน้าถัดไป
        findViewById(R.id.btn_forward).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                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);
    }
}

ขั้นตอนที่ 5: สร้างคลาส Pagination (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)) {
                // เมื่อความสูงเกินกำหนด ให้ตัดหน้า
                addPage(text.subSequence(startOffset, layout.getLineStart(i)));
                startOffset = layout.getLineStart(i);
                height = layout.getLineTop(i) + mHeight;
            }
            if (i == lines - 1) {
                // ใส่ส่วนที่เหลือในหน้าสุดท้าย
                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;
    }
}

ขั้นตอนที่ 6: กำหนดค่าใน 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>

การทดสอบ

รันแอปพลิเคชัน ข้อความยาวจะถูกแบ่งเป็นหลายหน้า กดพื้นที่ซ้าย/ขวาเพื่อนำทาง

วิธีสร้างข้อความแบ่งหน้า (Pagination) ใน Android

วิธีสร้างข้อความแบ่งหน้า (Pagination) ใน Android