0

I want to create a custom view based on com.google.android.material.slider.RangeSlider. It works on a physical device, but fails in the XML preview from Android Studio. I've tried rebuilding, clearing the cache, and restarting the IDE.

enter image description here

Exception

java.lang.NullPointerException: Missing required view with ID: com.example.appname:id/sliding_pane_detail_container at com.example.appname.databinding.ViewRangeSliderBinding.bind(ViewRangeSliderBinding.java:78) at com.example.appname.databinding.ViewRangeSliderBinding.inflate(ViewRangeSliderBinding.java:54) at com.example.appname.core.view.RangeSliderView.<init>(RangeSliderView.kt:20) at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499) at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480) at com.android.tools.rendering.ViewLoader.createNewInstance(ViewLoader.java:293) at com.android.tools.rendering.ViewLoader.loadClass(ViewLoader.java:156) at com.android.tools.rendering.ViewLoader.loadView(ViewLoader.java:117) at com.android.tools.rendering.LayoutlibCallbackImpl.loadView(LayoutlibCallbackImpl.java:281) at android.view.BridgeInflater.loadCustomView(BridgeInflater.java:429) at android.view.BridgeInflater.loadCustomView(BridgeInflater.java:440) at android.view.BridgeInflater.createViewFromTag(BridgeInflater.java:344) at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:973) at android.view.LayoutInflater.rInflate_Original(LayoutInflater.java:1135) at android.view.LayoutInflater_Delegate.rInflate(LayoutInflater_Delegate.java:72) at android.view.LayoutInflater.rInflate(LayoutInflater.java:1109) at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1096) at android.view.LayoutInflater.rInflate_Original(LayoutInflater.java:1138) at android.view.LayoutInflater_Delegate.rInflate(LayoutInflater_Delegate.java:72) at android.view.LayoutInflater.rInflate(LayoutInflater.java:1109) at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1096) at android.view.LayoutInflater.rInflate_Original(LayoutInflater.java:1138) at android.view.LayoutInflater_Delegate.rInflate(LayoutInflater_Delegate.java:72) at android.view.LayoutInflater.rInflate(LayoutInflater.java:1109) at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1096) at android.view.LayoutInflater.inflate(LayoutInflater.java:694) at android.view.LayoutInflater.inflate(LayoutInflater.java:505) at com.android.layoutlib.bridge.impl.RenderSessionImpl.inflate(RenderSessionImpl.java:365) at com.android.layoutlib.bridge.Bridge.createSession(Bridge.java:454) at com.android.tools.idea.layoutlib.LayoutLibrary.createSession(LayoutLibrary.java:120) at com.android.tools.rendering.RenderTask.createRenderSession(RenderTask.java:784) at com.android.tools.rendering.RenderTask.lambda$inflate$6(RenderTask.java:934) at com.android.tools.rendering.RenderExecutor$runAsyncActionWithTimeout$3.run(RenderExecutor.kt:202) at com.android.tools.rendering.RenderExecutor$PriorityRunnable.run(RenderExecutor.kt:316) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) at java.base/java.lang.Thread.run(Thread.java:840) 

Code

<?xml version="1.0" encoding="utf-8"?> <resources> <attr name="title" format="string" /> <attr name="stepSize" format="float" /> <attr name="valueFrom" format="float" /> <attr name="valueTo" format="float" /> <declare-styleable name="RangeSliderView"> <attr name="title" /> <attr name="stepSize" /> <attr name="valueFrom" /> <attr name="valueTo" /> <attr name="values" format="reference" /> <attr name="labelBehavior" /> </declare-styleable> </resources> 
<?xml version="1.0" encoding="utf-8"?> <LinearLayout 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:orientation="vertical"> <TextView android:id="@+id/title_text_view" style="@style/TextAppearance.Material3.BodyLarge" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" tools:text="Title" /> <com.google.android.material.slider.RangeSlider android:id="@+id/slider" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> 
class RangeSliderView(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) { private val binging: ViewRangeSliderBinding private val isDiscrete: Boolean val rangeValue get() = with(binging.slider.values) { listOf(this[0], this[1]) } init { val inflater = LayoutInflater.from(context) binging = ViewRangeSliderBinding.inflate(inflater, this, true) with(binging) { context.theme.obtainStyledAttributes(attrs, R.styleable.RangeSliderView, 0, 0).apply { try { titleTextView.text = getString(R.styleable.RangeSliderView_title) with (slider) { stepSize = getFloat(R.styleable.RangeSliderView_stepSize, 0.0F) isDiscrete = stepSize % 1 == 0F valueFrom = getFloat(R.styleable.RangeSliderView_valueFrom, 0.0F) valueTo = getFloat(R.styleable.RangeSliderView_valueTo, 100.0F) labelBehavior = getInt(R.styleable.RangeSliderView_labelBehavior, 0) if (hasValue(com.google.android.material.R.styleable.RangeSlider_values)) { val valuesId: Int = getResourceId(R.styleable.RangeSliderView_values, 0) val values: TypedArray = getResources().obtainTypedArray(valuesId) this.values = convertToFloat(values) } } } finally { recycle() } } } } fun setValues(values: List<Float>) { binging.slider.values = values } private fun convertToFloat(values: TypedArray): List<Float?> { val ret: MutableList<Float?> = ArrayList() for (i in 0 until values.length()) { ret.add(values.getFloat(i, -1.0f)) } return ret } } 
0

2 Answers 2

0

You'll need to override all constructors of the LinearLayout.

class RangeSliderView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0, ) : LinearLayout(context, attrs, defStyleAttr) { ... 

Most likely, the error happens because Android Studio Preview tries to inflate the view programmatically using different constructors.

Sign up to request clarification or add additional context in comments.

Comments

0

I think you should not use

val inflater = LayoutInflater.from(context) 

This can be throwing error. Try like this and also update constructor

class RangeSliderView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : LinearLayout(context, attrs, defStyleAttr) { private val binding: ViewRangeSliderBinding init { val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater binding = ViewRangeSliderBinding.inflate(inflater, this, true) // Ensure the view with the ID sliding_pane_detail_container is present if (binding.slidingPaneDetailContainer == null) { throw NullPointerException("Missing required view with ID: com.example.appname:id/sliding_pane_detail_container") } } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.