Warm tip: This article is reproduced from serverfault.com, please click

findViewById on custom view throws null

发布于 2020-12-24 11:09:26

Before I explain my problem, I want to say that I have already seen all the related questions but none of them worked for me.

I am a beginner in Android. I am using a custom view class, let's say CustomView which looks like:

class CustomView(context: Context?,attributeSet: AttributeSet) : View(context) {

    class CustomView constructor(context: Context?, attributeSet: AttributeSet){

    }
    var number = 1
}

I am inflating this view inside a fragment resource, like:

<com.example.myapp.CustomView
     android:id="@+id/custom_view"
     android:layout_width="match_parent"
     android:layout_height="match_parent"/>

But now whenever I am trying to get the custom view, it is null. All the sibling views work fine.

val root = inflater.inflate(R.layout.fragment_main, container,false)
val customView: CustomView = root.findViewById(R.id.custom_view)

It is throwing an error

java.lang.IllegalStateException: findViewById(R.id.custom_view) must not be null
Questioner
iamsubingyawali
Viewed
0
cactustictacs 2020-12-24 19:28:09

You need to pass that AttributeSet parameter into the View superclass constructor:

To allow Android Studio to interact with your view, at a minimum you must provide a constructor that takes a Context and an AttributeSet object as parameters. This constructor allows the layout editor to create and edit an instance of your view.

(https://developer.android.com/training/custom-views/create-view#subclassview)

So:

class CustomView(context: Context?,attributeSet: AttributeSet) : View(context, attributeSet) {

If you like, this is the standard boilerplate, overloaded custom view constructor (that the IDE will generate for you):

class CustomView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr)

That has some edge case theming compromises but it's usually fine, and handles whichever constructor the system wants to use.

(Also you don't need that nested CustomView class in your code)