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

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

บทนำ

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

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

สร้างโปรเจกต์ใหม่ใน Android Studio

ขั้นตอนที่ 2: Layout (activity_main.xml)

เพิ่มโค้ดใน 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/buttonBack"
            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/buttonForward"
            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: MainActivity.kt

เพิ่มโค้ดใน src/MainActivity.kt:

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.TextUtils
import android.text.style.ForegroundColorSpan
import android.text.style.RelativeSizeSpan
import android.text.style.StyleSpan
import android.view.ViewTreeObserver
import android.widget.Button
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {
    lateinit var buttonBack: Button
    lateinit var buttonForward: Button
    private lateinit var textView: TextView
    private var pagination: Pagination? = null
    private lateinit var charSequence: CharSequence
    private var currentIndex = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        title = "KotlinApp"

        buttonBack = findViewById(R.id.buttonBack)
        buttonForward = findViewById(R.id.buttonForward)
        textView = findViewById(R.id.tv)

        val htmlString = Html.fromHtml(getString(R.string.html_string))
        val spanString = SpannableString(getString(R.string.long_string))

        spanString.setSpan(ForegroundColorSpan(Color.BLUE), 0, 24, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
        spanString.setSpan(RelativeSizeSpan(2f), 0, 24, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
        spanString.setSpan(StyleSpan(Typeface.MONOSPACE.style), 0, 24, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
        spanString.setSpan(ForegroundColorSpan(Color.BLUE), 536, spanString.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
        spanString.setSpan(RelativeSizeSpan(2f), 536, spanString.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
        spanString.setSpan(StyleSpan(Typeface.MONOSPACE.style), 536, spanString.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)

        charSequence = TextUtils.concat(htmlString, spanString)

        textView.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
            override fun onGlobalLayout() {
                textView.viewTreeObserver.removeOnGlobalLayoutListener(this)
                pagination = Pagination(
                    charSequence, textView.width,
                    textView.height, textView.paint,
                    textView.lineSpacingMultiplier,
                    textView.lineSpacingExtra,
                    textView.includeFontPadding
                )
                update()
            }
        })

        buttonBack.setOnClickListener {
            currentIndex = if (currentIndex > 0) currentIndex - 1 else 0
            update()
        }

        buttonForward.setOnClickListener {
            currentIndex = if (currentIndex < pagination!!.size() - 1) currentIndex + 1 else pagination!!.size() - 1
            update()
        }
    }

    private fun update() {
        val text = pagination!![currentIndex]
        if (text != null) textView.text = text
    }
}

ขั้นตอนที่ 4: คลาส Pagination (Pagination.kt)

สร้างไฟล์ Kotlin ใหม่ชื่อ Pagination.kt และเพิ่มโค้ดคำนวณการแบ่งหน้า (โค้ดต้นฉบับซ้ำกับ MainActivity จึงตัดออก ให้สร้างคลาสแยกต่างหาก)

import android.graphics.Paint
import android.text.Layout
import android.text.Spannable
import android.text.TextUtils

class Pagination(
    private val text: CharSequence,
    private val width: Int,
    private val height: Int,
    private val paint: Paint,
    private val lineSpacingMultiplier: Float,
    private val lineSpacingExtra: Float,
    private val includeFontPadding: Boolean
) {
    private val pages = mutableListOf<CharSequence>()

    init {
        calculatePages()
    }

    private fun calculatePages() {
        // ใช้ StaticLayout วัดข้อความและแบ่งหน้าตามขนาด View
        val layout = android.text.StaticLayout.Builder.obtain(text, 0, text.length, paint, width)
            .setLineSpacing(lineSpacingExtra, lineSpacingMultiplier)
            .setIncludePad(includeFontPadding)
            .setBreakStrategy(Layout.BREAK_STRATEGY_HIGH_QUALITY)
            .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
            .build()

        var start = 0
        for (i in 0 until layout.lineCount) {
            val lineTop = layout.getLineTop(i)
            val lineBottom = layout.getLineBottom(i)
            if (lineBottom > height) {
                val end = layout.getLineEnd(i - 1)
                pages.add(text.subSequence(start, end))
                start = end
            }
        }
        if (start < text.length) {
            pages.add(text.subSequence(start, text.length))
        }
    }

    operator fun get(index: Int): CharSequence? = pages.getOrNull(index)
    fun size() = pages.size
}

ขั้นตอนที่ 5: Strings.xml

เพิ่มสตริงใน res/values/strings.xml:

<resources>
    <string name="html_string"><b>Header</b></string>
    <string name="long_string">Lorem ipsum dolor sit amet, consectetur adipiscing elit. ...</string>
</resources>

ขั้นตอนที่ 6: AndroidManifest.xml

ตรวจสอบการประกาศ Activity

การทดสอบ

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

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