How to reference a lambda from inside it?

后端 未结 3 2033
温柔的废话
温柔的废话 2020-12-30 00:44

I am trying to get height of a view in onCreate method but I couldn\'t find any way to remove OnGlobalLayoutListener.

In Java (working):

containerLay         


        
相关标签:
3条回答
  • 2020-12-30 01:14

    What's about extension like this?

    import android.annotation.SuppressLint
    import android.os.Build
    import android.view.View
    import android.view.ViewTreeObserver
    
    inline fun View.doOnGlobalLayout(crossinline action: (view: View) -> Unit) {
        val vto = viewTreeObserver
        vto.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
            @SuppressLint("ObsoleteSdkInt")
            @Suppress("DEPRECATION")
            override fun onGlobalLayout() {
                action(this@doOnGlobalLayout)
                when {
                    vto.isAlive -> {
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                            vto.removeOnGlobalLayoutListener(this)
                        } else {
                            vto.removeGlobalOnLayoutListener(this)
                        }
                    }
                    else -> {
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                            viewTreeObserver.removeOnGlobalLayoutListener(this)
                        } else {
                            viewTreeObserver.removeGlobalOnLayoutListener(this)
                        }
                    }
                }
            }
        })
    }
    

    Finally, you can call OnGlobalLayoutListener from View directly

    val view: View = ...
    view.doOnGlobalLayout {
      val width = view?.measuredWidth
      val height = view?.measuredHeight
    }
    
    0 讨论(0)
  • 2020-12-30 01:14

    Another solution is to implement and use self-reference:

    class SelfReference<T>(val initializer: SelfReference<T>.() -> T) {
        val self: T by lazy {
            inner ?: throw IllegalStateException()
        }
    
        private val inner = initializer()
    }
    
    fun <T> selfReference(initializer: SelfReference<T>.() -> T): T {
        return SelfReference(initializer).self
    }
    

    Then the usage would be

    containerLayout.viewTreeObserver.addOnGlobalLayoutListener(selfReference { 
        OnGlobalLayoutListener {
            containerLayout.viewTreeObserver.removeOnGlobalLayoutListener(self)
            // ...
        }
    }
    

    Instead of this, self property is used.

    0 讨论(0)
  • 2020-12-30 01:15

    Referencing a lambda from inside it is not supported.

    As a workaround, you might use anonymous object instead of lambda SAM-converted to Java functional interface OnGlobalLayoutListener:

    containerLayout.viewTreeObserver.addOnGlobalLayoutListener(object: OnGlobalLayoutListener {
        override fun onGlobalLayout() {
            // your code here. `this` should work
        }
    })
    
    0 讨论(0)
提交回复
热议问题