步骤1.使用Navigation Drawer模板创建一个新应用。
步骤2.添加自定义按钮并覆盖onMeasure方法。
@CoordinatorLayout.DefaultBehavior(MyButton.Behavior.class)
public class MyButton extends android.support.v7.widget.AppCompatButton {
private ViewTreeObserver.OnPreDrawListener mPreDrawListener;
public MyButton(Context context) {
super(context);
}
public MyButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (mPreDrawListener == null) {
mPreDrawListener = new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
offsetTopAndBottom(50);
return true;
}
};
ViewParent p = getParent();
if (p instanceof View) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
((View)p).getViewTreeObserver().addOnPreDrawListener(mPreDrawListener);
}
}
}
}
public static class Behavior extends CoordinatorLayout.Behavior<MyButton> {
@Override
public boolean onLayoutChild(CoordinatorLayout parent, MyButton child, int layoutDirection) {
final List<View> dependencies = parent.getDependencies(child);
return super.onLayoutChild(parent, child, layoutDirection);
}
@Override
public void onAttachedToLayoutParams(@NonNull CoordinatorLayout.LayoutParams lp) {
if (lp.dodgeInsetEdges == Gravity.NO_GRAVITY) {
// If the developer hasn't set dodgeInsetEdges, lets set it to BOTTOM so that
// we dodge any Snackbars
lp.dodgeInsetEdges = Gravity.BOTTOM;
}
}
}
}
步骤3.在app_bar_main布局中使用
MyButton
。步骤4.在onPreDraw中设置一个断点,然后我可以看到它将被无限执行。如果我评论
offsetTopAndBottom(50)
,一切都会很好。我还跟踪源代码,发现应用程序一次又一次接收到vsync信号,这导致Choreographer.java中的
onVsync
函数无限运行。为什么会这样?更新资料
如果我按如下所示设置断点并注释
onPreDraw
,则最终将无法达到该断点,否则始终可以到达。最佳答案
在绘制每帧之前,将调用回调onPreDraw()
。由于您通常会保持绘制帧(〜60fps),因此通常将其称为“无限”。
为了避免这种行为,通常的模式是将侦听器作为onPreDraw()
中的第一条语句删除:
view.getViewTreeObserver().removeOnPreDrawListener(this);
其中
view
是您的情况下被the弃的父母。您可以在this video中查看示例代码。工程师是Android Framework团队的成员。