Regards to all.
I am a beginner in Android Studio. I'm trying to make a simple application that converts long text into multiple pages. I found an old example of the "PageSplitter" project, but the new version of Android Studio reported a lot of errors. I managed to debug it but when I start the project in the emulator it starts to open and then a message appears that the application has been terminated. Can anyone help me find the error. Thanks in advance. Here is the code:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="ru.appheads.pagesplitterapp">
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Pagesplitterapp"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
MainActivity.java
package ru.appheads.pagesplitterapp;
import android.os.Bundle;
import android.text.TextPaint;
import android.view.ViewTreeObserver;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager.widget.ViewPager;
public class MainActivity extends FragmentActivity {
private ViewPager pagesView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pagesView = (ViewPager) findViewById(R.id.pages);
// to get ViewPager width and height we have to wait global layout
pagesView.getViewTreeObserver().addOnGlobalLayoutListener(new
ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
PageSplitter pageSplitter = new PageSplitter(pagesView.getWidth(),
pagesView.getHeight(), 1, 0);
TextPaint textPaint = new TextPaint();
textPaint.setTextSize(getResources().getDimension(R.dimen.text_size));
for (int i = 0; i < 1000; i ) {
pageSplitter.append("Hello, ", textPaint);
textPaint.setFakeBoldText(true);
pageSplitter.append("world", textPaint);
textPaint.setFakeBoldText(false);
pageSplitter.append("! ", textPaint);
if ((i 1) % 100 == 0) {
pageSplitter.append("\n", textPaint);
}
}
pagesView.setAdapter(new TextPagerAdapter(getSupportFragmentManager(),
pageSplitter.getPages()));
pagesView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
}
}
PageFragment.java
package ru.appheads.pagesplitterapp;
import android.os.Bundle;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.fragment.app.Fragment;
public class PageFragment extends Fragment {
private final static String PAGE_TEXT = "PAGE_TEXT";
public static PageFragment newInstance(CharSequence pageText) {
PageFragment frag = new PageFragment();
Bundle args = new Bundle();
args.putCharSequence(PAGE_TEXT, pageText);
frag.setArguments(args);
return frag;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle
savedInstanceState) {
CharSequence text = getArguments().getCharSequence(PAGE_TEXT);
TextView pageView = (TextView) inflater.inflate(R.layout.page, container, false);
pageView.setTextSize(TypedValue.COMPLEX_UNIT_PX,
getResources().getDimension(R.dimen.text_size));
pageView.setText(text);
return pageView;
}
}
PageSpitter.java
package ru.appheads.pagesplitterapp;
import android.graphics.Typeface;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.TextPaint;
import android.text.style.StyleSpan;
import java.util.ArrayList;
import java.util.List;
public class PageSplitter {
private final int pageWidth;
private final int pageHeight;
private final float lineSpacingMultiplier;
private final int lineSpacingExtra;
private final List<CharSequence> pages = new ArrayList<CharSequence>();
private SpannableStringBuilder currentLine = new SpannableStringBuilder();
private SpannableStringBuilder currentPage = new SpannableStringBuilder();
private int currentLineHeight;
private int pageContentHeight;
private int currentLineWidth;
private int textLineHeight;
public PageSplitter(int pageWidth, int pageHeight, float lineSpacingMultiplier, int
lineSpacingExtra) {
this.pageWidth = pageWidth;
this.pageHeight = pageHeight;
this.lineSpacingMultiplier = lineSpacingMultiplier;
this.lineSpacingExtra = lineSpacingExtra;
}
public void append(String text, TextPaint textPaint) {
textLineHeight = (int) Math.ceil(textPaint.getFontMetrics(null) * lineSpacingMultiplier
lineSpacingExtra);
String[] paragraphs = text.split("\n", -1);
int i;
for (i = 0; i < paragraphs.length - 1; i ) {
appendText(paragraphs[i], textPaint);
appendNewLine();
}
appendText(paragraphs[i], textPaint);
}
private void appendText(String text, TextPaint textPaint) {
String[] words = text.split(" ", -1);
int i;
for (i = 0; i < words.length - 1; i ) {
appendWord(words[i] " ", textPaint);
}
appendWord(words[i], textPaint);
}
private void appendNewLine() {
currentLine.append("\n");
checkForPageEnd();
appendLineToPage(textLineHeight);
}
private void checkForPageEnd() {
if (pageContentHeight currentLineHeight > pageHeight) {
pages.add(currentPage);
currentPage = new SpannableStringBuilder();
pageContentHeight = 0;
}
}
private void appendWord(String appendedText, TextPaint textPaint) {
int textWidth = (int) Math.ceil(textPaint.measureText(appendedText));
if (currentLineWidth textWidth >= pageWidth) {
checkForPageEnd();
appendLineToPage(textLineHeight);
}
appendTextToLine(appendedText, textPaint, textWidth);
}
private void appendLineToPage(int textLineHeight) {
currentPage.append(currentLine);
pageContentHeight = currentLineHeight;
currentLine = new SpannableStringBuilder();
currentLineHeight = textLineHeight;
currentLineWidth = 0;
}
private void appendTextToLine(String appendedText, TextPaint textPaint, int textWidth) {
currentLineHeight = Math.max(currentLineHeight, textLineHeight);
currentLine.append(renderToSpannable(appendedText, textPaint));
currentLineWidth = textWidth;
}
public List<CharSequence> getPages() {
List<CharSequence> copyPages = new ArrayList<CharSequence>(pages);
SpannableStringBuilder lastPage = new SpannableStringBuilder(currentPage);
if (pageContentHeight currentLineHeight > pageHeight) {
copyPages.add(lastPage);
lastPage = new SpannableStringBuilder();
}
lastPage.append(currentLine);
copyPages.add(lastPage);
return copyPages;
}
private SpannableString renderToSpannable(String text, TextPaint textPaint) {
SpannableString spannable = new SpannableString(text);
if (textPaint.isFakeBoldText()) {
spannable.setSpan(new StyleSpan(Typeface.BOLD), 0, spannable.length(), 0);
}
return spannable;
}
}
TextAdapter.java
package ru.appheads.pagesplitterapp;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import java.util.List;
public class TextPagerAdapter extends FragmentPagerAdapter {
private final List<CharSequence> pageTexts;
public TextPagerAdapter(FragmentManager fm, List<CharSequence> pageTexts) {
super(fm);
this.pageTexts = pageTexts;
}
@Override
public Fragment getItem(int i) {
return PageFragment.newInstance(pageTexts.get(i));
}
@Override
public int getCount() {
return pageTexts.size();
}
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context="ru.appheads.pagesplitterapp.MainActivity">
<androidx.viewpager2.widget.ViewPager2 xmlns:android="http://schemas.android.com/apk/res
/android"
android:id="@ id/pages"
android:overScrollMode="never"
android:layout_height="match_parent"
android:layout_width="match_parent">
</androidx.viewpager2.widget.ViewPager2>
</RelativeLayout>
Page.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:lineSpacingMultiplier="1"
android:lineSpacingExtra="0sp">
</TextView>
styles.xml
<resources>
<style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
</style>
</resources>
build.gradle.app
plugins {
id 'com.android.application'
}
android {
compileSdk 32
defaultConfig {
applicationId "ru.appheads.pagesplitterapp"
minSdk 21
targetSdk 32
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-
rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.5.0'
implementation 'com.google.android.material:material:1.6.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.viewpager2:viewpager2:1.0.0'
//implementation 'androidx.fragment:fragment-ktx:1.2.0-beta02'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
CodePudding user response:
This is a 1/4 of logcat content.
This is second logcat - after clear logcat.
2022-09-08 23:03:25.664 6760-6760/? I/pagesplitterap: Late-enabling
-Xcheck:jni
2022-09-08 23:03:25.731 6760-6760/? I/pagesplitterap: Unquickening 12
vdex files!
2022-09-08 23:03:25.737 6760-6760/? W/pagesplitterap: Unexpected CPU
variant for X86 using defaults: x86
2022-09-08 23:03:26.651 6760-6760/ru.appheads.pagesplitterapp
D/NetworkSecurityConfig: No Network Security Config specified, using
platform default
2022-09-08 23:03:26.651 6760-6760/ru.appheads.pagesplitterapp
D/NetworkSecurityConfig: No Network Security Config specified, using
platform default
2022-09-08 23:03:26.739 6760-6783/ru.appheads.pagesplitterapp
D/libEGL:
loaded /vendor/lib/egl/libEGL_emulation.so
2022-09-08 23:03:26.743 6760-6783/ru.appheads.pagesplitterapp
D/libEGL:
loaded /vendor/lib/egl/libGLESv1_CM_emulation.so
2022-09-08 23:03:26.753 6760-6783/ru.appheads.pagesplitterapp
D/libEGL:
loaded /vendor/lib/egl/libGLESv2_emulation.so
2022-09-08 23:03:27.182 6760-6760/ru.appheads.pagesplitterapp
D/AndroidRuntime: Shutting down VM
--------- beginning of crash
2022-09-08 23:03:27.184 6760-6760/ru.appheads.pagesplitterapp
E/AndroidRuntime: FATAL EXCEPTION: main
Process: ru.appheads.pagesplitterapp, PID: 6760
java.lang.RuntimeException: Unable to start activity
ComponentInfo {ru.appheads.pagesplitterapp
/ru.appheads.pagesplitterapp.MainActivity}:
java.lang.ClassCastException: androidx.viewpager2.widget.ViewPager2
cannot be cast to androidx.viewpager.widget.ViewPager
at
android.app.ActivityThread.performLaunchActivity
(ActivityThread.java:3449)
at android.app.ActivityThread.handleLaunchActivity
(ActivityThread.java:3601)
at android.app.servertransaction.LaunchActivityItem.execute
(LaunchActivityItem.java:85)
at
android.app.servertransaction.TransactionExecutor.executeCallbacks
(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute
(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage
(ActivityThread.java:2066)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run
(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Caused by: java.lang.ClassCastException:
androidx.viewpager2.widget.ViewPager2 cannot be cast to
androidx.viewpager.widget.ViewPager
at ru.appheads.pagesplitterapp.MainActivity.onCreate
(MainActivity.java:19)
at android.app.Activity.performCreate(Activity.java:7994)
at android.app.Activity.performCreate(Activity.java:7978)
at android.app.Instrumentation.callActivityOnCreate
(Instrumentation.java:1309)
at android.app.ActivityThread.performLaunchActivity
(ActivityThread.java:3422)
at android.app.ActivityThread.handleLaunchActivity
(ActivityThread.java:3601)
at android.app.servertransaction.LaunchActivityItem.execute
(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.
executeCallbacks (TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute
(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage
(ActivityThread.java:2066)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run
(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
2022-09-08 23:03:27.217 6760-6760/ru.appheads.pagesplitterapp
I/Process: Sending signal. PID: 6760 SIG: 9
CodePudding user response:
you are using Viewpager2 in xml and imported and declared Viewpager in MainActivity, that's why you are getting ClassCastException. Both xml and activity viewPager type should be same