Search code examples
androidkotlinkotlin-extension

Kotlin Recursive Extension Function to Walk Android View Hierarchy


I am attempting to create a generic extension function that can walk an Android view hierarchy and return the first occurence of a view of a specific type.

The idea would be to invoke the extension as follows (to find the first occurence of a Toolbar inside of parentView):

val someView = parentView.findFirstChildRecursive<Toolbar>()

Unfortunately the code below doesn't compile. I guess Kotlin is not happy about having recursive inline functions, but I can't use a reified type without inlining the function.

inline fun <reified T> View.findFirstChildRecursive(): T? {
  when (this) {
    is T -> return this
    is ViewGroup -> {
      for (i in 0 until childCount) {
        getChildAt(i).findFirstChildRecursive<T>()?.let { return it }
      }
    }
  }
  return null
}

I'm a little bit of a Kotlin newbie, so I was hoping someone could explain why or propose a good solution?


Solution

  • I'm gonna add a little bit to Victor Rendina's answer.

    You can have two functions: one with the clazz: Class<T> parameter and the other one inline with reified generic:

    inline fun <reified T : View> View.findFirstChildRecursive(): T? {
        return findFirstChildRecursive(T::class.java)
    }
    
    fun <T: View> View.findFirstChildRecursive(clazz: Class<T>): T? {
        if (this::class.java == clazz) {
            @Suppress("UNCHECKED_CAST")
            return this as T
        } else if (this is ViewGroup) {
            for (i in 0 until childCount) {
                getChildAt(i).findFirstChildRecursive(clazz)?.let { return it }
            }
        }
        return null
    }