বড় টেক্সটকে পেজে ভাগ করুন (Pagination)
এই উদাহরণটি দেখায় কিভাবে একটি বড় টেক্সট ব্লকে পেজে ভাগ করে একটি বুক-রিডিং অ্যাপের মতো ইন্টারফেস তৈরি করতে হয়। এটি StaticLayout এবং কাস্টম Pagination ক্লাস ব্যবহার করে করা হয়।
ধাপ ১: প্রজেক্ট তৈরি করুন
ধাপ ২: লেআউট ডিজাইন
res/layout/activity_main.xml - এখানে দুইটি অদৃশ্য বাটন (পেছনে/সামনে) এবং একটি TextView আছে:
<?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:padding="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>
ধাপ ৩: MainActivity.java - মূল লজিক
এখানে HTML এবং Spannable স্ট্রিং জোড়া করা হয়েছে, তারপর Pagination ক্লাস ব্যবহার করে পেজে ভাগ করা হয়েছে:
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);
// HTML স্ট্রিং
Spanned htmlString = Html.fromHtml(getString(R.string.html_string));
// Spannable স্ট্রিং স্টাইলিং
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);
// ভিউ রেডি হলে পেজিনেশন শুরু
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(v -> {
mCurrentIndex = (mCurrentIndex > 0) ? mCurrentIndex - 1 : 0;
update();
});
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);
}
}
ধাপ ৪: Pagination.java - কোর ক্লাস
এই ক্লাসটি StaticLayout ব্যবহার করে টেক্সটকে পেজে ভাগ করে:
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 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;
}
}
ধাপ ৫: স্ট্রিং রিসোর্স
res/values/strings.xml এ html_string এবং long_string যোগ করুন।
ব্যবহার
স্ক্রিনের বাম পার্শ্বে ক্লিক করলে পেছনের পেজ, ডান পার্শ্বে ক্লিক করলে আগের পেজ দেখাবে। এটি ই-বুক রিডার অ্যাপ তৈরির ভিত্তি হতে পারে।