OnGlobalLayoutListener:弃用和兼容性


75

我必须使用一个OnGlobalLayoutListener对象,然后删除侦听器,我对以下方法解决的不赞成使用的方法有问题。

protected void onCreate(Bundle savedInstanceState) {
    final LinearLayout llTotal = (LinearLayout) findViewById(R.id.mmc_ll);
    ViewTreeObserver vto = llTotal.getViewTreeObserver();
    if(vto.isAlive()){
        vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                //
                // mycode
                //
                if (Build.VERSION.SDK_INT<16) {
                    removeLayoutListenerPre16(llTotal.getViewTreeObserver(),this);
                } else {
                    removeLayoutListenerPost16(llTotal.getViewTreeObserver(), this);
                }
            } 
        });
    }
    super.onCreate(savedInstanceState);
}

@SuppressWarnings("deprecation")
private void removeLayoutListenerPre16(ViewTreeObserver observer, OnGlobalLayoutListener listener){
    observer.removeGlobalOnLayoutListener(listener);
}

@TargetApi(16)
private void removeLayoutListenerPost16(ViewTreeObserver observer, OnGlobalLayoutListener listener){
    observer.removeOnGlobalLayoutListener(listener);
}

这是对的吗?有更好的处理兼容性的方法吗?

使用API​​ 10在模拟器中运行代码我在LogCat中收到以下警告

04-24 09:30:12.565: I/dalvikvm(471): Could not find method android.view.ViewTreeObserver.removeOnGlobalLayoutListener, referenced from method com.my.project.ActivityHome.removeLayoutListenerPost16
04-24 09:30:12.565: W/dalvikvm(471): VFY: unable to resolve virtual method 2950: Landroid/view/ViewTreeObserver;.removeOnGlobalLayoutListener (Landroid/view/ViewTreeObserver$OnGlobalLayoutListener;)V

我是否可以忽略它们,因为我必须以某种方式进行修复?

Answers:


142

我在我的项目中使用它:

@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public static void removeOnGlobalLayoutListener(View v, ViewTreeObserver.OnGlobalLayoutListener listener){
    if (Build.VERSION.SDK_INT < 16) {
        v.getViewTreeObserver().removeGlobalOnLayoutListener(listener);
    } else {
        v.getViewTreeObserver().removeOnGlobalLayoutListener(listener);
    }
}

看起来和你相似。在不同的设备(4.2.2和2.3.3)上进行了测试,并且运行完美。似乎这是唯一的方法。...如果您发现其他任何信息,我想知道。祝好运

2020编辑 这种方法已经非常过时了。希望您将代码移至Kotlin。现在,当使用ktx库时,可以使用doOnPreDraw函数。 https://developer.android.com/reference/kotlin/androidx/core/view/package-summary#(android.view.View).doOnPreDraw(kotlin.Function1)


在开始时,我使用了您的代码,但给出了错误(调用要求API级别16(当前最小值为8):android.view.ViewTreeObserver#removeOnGlobalLayoutListener)和警告(来自ViewTreeObserver类型的方法removeGlobalOnLayoutListener(ViewTreeObserver.OnGlobalLayoutListener)是不推荐使用)。我的代码解决了这些问题,但发出LogCat警告
crbin1 2013年

警告很好。这是因为您使用的是某些sdk版本的jar,且设备<sdk已弃用。因此您仍然可以使用它。
Udi Oshi

9
@ crbin1您可以在函数声明之前添加@TargetApi(Build.VERSION_CODES.JELLY_BEAN),如果希望避免看到此警告/错误。
android开发人员

7
Google,这太可怕了。
奥利弗·迪克森

39

我认为正确的方法是使用Build.VERSION.SDK_INTand Build.VERSION_CODES

public static void removeOnGlobalLayoutListener(View v, ViewTreeObserver.OnGlobalLayoutListener listener){
        if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
                v.getViewTreeObserver().removeGlobalOnLayoutListener(listener);
            } else {
                v.getViewTreeObserver().removeOnGlobalLayoutListener(listener);
            }
}

1
我认为您想传递听众removeGlobalLayoutListener而不是this
Sergio Serra 2015年

10
    mView.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                mView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            } else {
                //noinspection deprecation
                mView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            }
            //
            // mycode
            //
        } 
    });

9

当然,检查Android版本并调用正确的方法更为谨慎,但是如果您查看Android源代码,您会发现一些有趣的东西:

 @Deprecated
    public void removeGlobalOnLayoutListener(OnGlobalLayoutListener victim) {
        removeOnGlobalLayoutListener(victim);
    }

该代码已从API 18中删除


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.