I am trying to customize SwitchMaterial class in Android, like this
class TipSwitchMaterial @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = android.R.attr.switchStyle
) : SwitchMaterial(context, attrs, defStyleAttr) {
}
I use TipSwitchMaterial in a activity xml like this:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:isScrollContainer="true"
tools:context=".SidActivity">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
...
<com.omnieyes.omnilite.view.TipSwitchMaterial
android:id="@+id/event_record_sort_switch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:text="@string/sort"
android:tooltipText="@string/tooltip_sort"
app:layout_constraintBottom_toBottomOf="@+id/predict_button"
app:layout_constraintEnd_toStartOf="@id/predict_button"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/predict_button" />
...
However a NPE would happen right after getting into that activity:
2023-03-23 15:21:36.630 17706-17706/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.omnieyes.omnilite, PID: 17706
java.lang.NullPointerException: Attempt to invoke interface method 'int java.lang.CharSequence.length()' on a null object reference
at android.text.StaticLayout.<init>(StaticLayout.java:455)
at androidx.appcompat.widget.SwitchCompat.makeLayout(SwitchCompat.java:982)
at androidx.appcompat.widget.SwitchCompat.onMeasure(SwitchCompat.java:905)
at android.view.View.measure(View.java:25466)
at androidx.constraintlayout.widget.ConstraintLayout$Measurer.measure(ConstraintLayout.java:811)
at androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.measure(BasicMeasure.java:466)
at androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.measureChildren(BasicMeasure.java:134)
at androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.solverMeasure(BasicMeasure.java:278)
at androidx.constraintlayout.core.widgets.ConstraintWidgetContainer.measure(ConstraintWidgetContainer.java:120)
at androidx.constraintlayout.widget.ConstraintLayout.resolveSystem(ConstraintLayout.java:1594)
at androidx.constraintlayout.widget.ConstraintLayout.onMeasure(ConstraintLayout.java:1708)
at android.view.View.measure(View.java:25466)
at android.widget.ScrollView.measureChildWithMargins(ScrollView.java:1412)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
at android.widget.ScrollView.onMeasure(ScrollView.java:452)
at android.view.View.measure(View.java:25466)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6957)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
at androidx.appcompat.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:145)
at android.view.View.measure(View.java:25466)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6957)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1552)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:842)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:721)
at android.view.View.measure(View.java:25466)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6957)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
at android.view.View.measure(View.java:25466)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6957)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1552)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:842)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:721)
at android.view.View.measure(View.java:25466)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6957)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
at com.android.internal.policy.DecorView.onMeasure(DecorView.java:747)
at android.view.View.measure(View.java:25466)
at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:3397)
at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:2228)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2486)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1952)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8171)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:972)
at android.view.Choreographer.doCallbacks(Choreographer.java:796)
at android.view.Choreographer.doFrame(Choreographer.java:731)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:957)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
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)
I do this because I want to apply a click-like tooltip with this post, which does perfromLongClick() in a OnClickListener. I'm trying to alter his way a little bit. I planned to do it inside its init{} block like this:
init {
// so we can click and show its tooltip; a long-click still does
setOnClickListener { performLongClick() }
}
Which works with a class that extends TextView. Please help, thanks.
I have listed what I've tried up there. And I can't find any post or tutorial related that extends SwitchMaterial. Maybe there's no need to do this?
Edit: add build.gradle file
My build.gradle file would be like:
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-android-extensions'
}
android {
compileSdk 31
defaultConfig {
applicationId "xxx"
minSdk 26
targetSdk 31
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
ndk {
abiFilters "armeabi", "armeabi-v7a", "x86", "mips"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
packagingOptions {
exclude 'AndroidManifest.xml'
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation project(path: ':opencv')
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'
implementation 'com.google.code.gson:gson:2.10'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation 'androidx.core:core-ktx:1.3.2'
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation group: 'commons-io', name: 'commons-io', version: '2.6'
implementation group: 'org.javatuples', name: 'javatuples', version: '1.2'
implementation('com.squareup.okhttp3:okhttp:4.9.3')
implementation('org.apache.commons:commons-csv:1.5')
implementation files('libs/openCVLibrary330-v1.1-release.aar')
//firebase, choose for kotlin and java or Both.
implementation 'com.google.firebase:firebase-crashlytics-ktx:18.3.0'
implementation 'com.google.firebase:firebase-crashlytics'
}
These types of errors that occur within system/library code can be hard to track down.
I am only able to reproduce your error by either 1) forcing the
defStyleAttrto zero, or, 2) forcing thetextOnattribute in the layout file to null (android:textOn="@null"). This tells me that your are losing the attribute or modifying the style such that thetextOnand, probably,textOffcomes up null. You may be able to satisfy yourself that this is the source of the problem by settingandroid:textOn="On"andandroid:textOff="Off"in the XML layout. (This is not the fix, however.)So, why do I say this? If we take the top program reference lines in the stack trace in reverse order, we can see the code that is involved in the crash.
If we set a breakpoint at line 455 of StaticLayout.java, we can see that
sourceis null and that leads directly to the crash.Tracing back to the source of the
sourcevariable, we see that is comes frommTextOnTransformed(line 905 ofSwitchCompat.java.) The only place wheremTextOnTransformedis set is in the following code:And
textOnis the text to display when the switch is "on" and it is null.I can't tell you specifically how to correct this error, but take a close look at everything you have that touches the switch and its attributes including styles to try to identify what is going wrong.