求你指教我们怎样数算自己的日子,好叫我们得着智慧的心。—-诗篇90:12
之前写过两篇关于SystemUI的文章:
SystemUI之功能介绍和UI布局实现
SystemUI之呈现流程
本篇分析下SystemUI 拖拽事件处理的过程。
他山之石可以攻玉,通过本篇的分析力求能触摸到Android团队对复杂view的处理技巧,以便今后我们也能在自己的项目里运用上这些技巧。
着重分析下面几个知识点
自定义View的高效布局方式,onMesure,onLayout—onDraw如何实现技巧onTouchEvent—onIntecept—onDispach如何运用,手势监听处理逻辑代码的封装性
开胃小菜—点击事件
如果对SystemUI布局结构不了解,请先参考之前的文章SystemUI之功能介绍和UI布局实现 ,我们先挑个软柿子捏捏,看看下图示意的点击事件是如何处理的。
这里写图片描述
在放上SystemUI的布局图
这里主要分析两块:
点击顶部,如何控制状态栏伸缩
根据SystemUI的布局图,很容易找到点击事件入口是在NotificationPanelView的onClick里。
@Override
public void onClick(View v) {
if (v == mHeader) {
onQsExpansionStarted();
if (mQsExpanded) {
flingSettings(0 /* vel */, false /* expand */, null, true /* isClick */);
} else if (mQsExpansionEnabled) {
EventLogTags.writeSysuiLockscreenGesture(
EventLogConstants.SYSUI_TAP_TO_OPEN_QS,
0, 0);
flingSettings(0 /* vel */, true /* expand */, null, true /* isClick */);
}
}
}
主要的事件处理被封装在了flingSettings方法中,
private void flingSettings(float vel, boolean expand, final Runnable onFinishRunnable,
boolean isClick) {
float target = expand ? mQsMaxExpansionHeight : mQsMinExpansionHeight;
//忽略非主要代码
ValueAnimator animator = ValueAnimator.ofFloat(mQsExpansionHeight, target);
if (isClick) {
animator.setInterpolator(mTouchResponseInterpolator);
animator.setDuration(368);
} else {
mFlingAnimationUtils.apply(animator, mQsExpansionHeight, target, vel);
}
//忽略非主要代码
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
setQsExpansion((Float) animation.getAnimatedValue());
}
});
animator.addListen