如何从里面引用lambda?

时间:2015-11-24 16:21:44

标签: android kotlin

我试图在onCreate方法中获取视图的高度,但我找不到任何方法来删除OnGlobalLayoutListener。

在Java(工作)中:

containerLayout.getViewTreeObserver.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {  
    @Override  
    public void onGlobalLayout() {  
        containerLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this); 
        int width  = layout.getMeasuredWidth();
        int height = layout.getMeasuredHeight(); 

    }  
});

在Kotlin(不接受“this”):

   containerLayout.viewTreeObserver.addOnGlobalLayoutListener {
            containerLayout.viewTreeObserver.removeOnGlobalLayoutListener(this)
            Toast.makeText(applicationContext, "size is "+ containerLayout.height,Toast.LENGTH_LONG).show()
        }

此问题是否有任何参考或示例?感谢。

4 个答案:

答案 0 :(得分:14)

不支持从内部引用lambda。

作为一种变通方法,您可以使用匿名对象而不是lambda SAM转换为Java功能接口re.sub(r'\bchem\b', r' chemistry ', str)

OnGlobalLayoutListener

答案 1 :(得分:2)

这样的扩展名是什么?

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)
                    }
                }
            }
        }
    })
}

最后,您可以直接从View调用OnGlobalLayoutListener

val view: View = ...
view.doOnGlobalLayout {
  val width = view?.measuredWidth
  val height = view?.measuredHeight
}

答案 2 :(得分:1)

另一个解决方案是implement并使用自引用:

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
}

然后用法

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

使用this属性代替self

答案 3 :(得分:0)

简单/清晰的方法(没有泛型或匿名对象):

您可以提前创建监听器,然后根据需要添加/使用/删除:

private var layoutChangedListener: ViewTreeObserver.OnGlobalLayoutListener? = null

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    // create the listener
    layoutChangedListener = ViewTreeObserver.OnGlobalLayoutListener {

        // do something here

        // remove the listener from your view
        myContainerView.viewTreeObserver.removeOnGlobalLayoutListener(layoutChangedListener)
        layoutChangedListener = null
    }

    // add the listener to your view
    myContainerView.viewTreeObserver.addOnGlobalLayoutListener(layoutChangedListener)
}

用例: 我必须能够移除侦听器,以便调整侦听器本身内部的布局 - 不移除侦听器可能导致死锁