/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */
#content_views .toc,
/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */
#content_views.markdown_views > p:empty:has(+ .toc),
#content_views.markdown_views > .toc + p:empty,
/* 富文本旧版目录标记 */
#content_views.htmledit_views #main-toc,
#content_views.htmledit_views #hr-toc,
#content_views.htmledit_views p[id*=\”-toc\”] {
display: none !important;
}
/* 目录去掉后,紧跟的首个标题不再多出一块上边距 */
#content_views.markdown_views > .toc + h1,
#content_views.markdown_views > .toc + h2,
#content_views.markdown_views > .toc + h3,
#content_views.markdown_views > .toc + h4,
#content_views.markdown_views > .toc + p:empty + h1,
#content_views.markdown_views > .toc + p:empty + h2,
#content_views.markdown_views > .toc + p:empty + h3,
#content_views.markdown_views > .toc + p:empty + h4 {
margin-top: 0 !important;
}
一、先搞清楚:Interpolator 到底在插什么
Interpolator(插值器)只有一个职责:把\”时间进度\”映射成\”动画进度\”。
如果动画的起点是 from、终点是 to、总时长是 D,那么时刻 t(单位秒,0 ≤ t ≤ D)对应的位置是:
位置 = f(t / D) × (to – from) + from
其中 f 就是 Interpolator 的 getInterpolation(float input),输入输出都被归一化到 [0, 1]。
Interpolator 完全不知道距离是多少,也不知道动画持续多久——它只负责\”形状\”。真正的距离和时间由 ValueAnimator 负责:
// ValueAnimator.java 简化后的核心逻辑
private void applyTransformation(float fraction, TransformationInfo info, int pointFlags) {
// ① Interpolator 把线性时间进度变成曲线进度
float interpolatedFraction = mInterpolator.getInterpolation(fraction);
// ② 用曲线进度去插值具体的数值
mCurrentValue = getAnimatedValue(mStartValue, mEndValue, interpolatedFraction);
info.setCurrentValue(mCurrentValue);
}
private float getAnimatedValue(float startValue, float endValue, float fraction) {
return startValue + (endValue – startValue) * fraction;
}
所以理解 Interpolator 的钥匙是速度:
瞬时速度 v(t) = f\'(t) × (总距离 / 总时长)
一条曲线\”先快后慢\”还是\”先慢后快\”,取决于 f\'(t) 是递增还是递减——这才是四个 Interpolator 的真正区别。
二、四个内置 Interpolator 的源码与公式
| LinearInterpolator | 匀速直线 | return input; | f(t) = t | 直线 |
| AccelerateInterpolator | 先慢后快 | return input * input; | f(t) = t² | 开口向上抛物线 |
| DecelerateInterpolator | 先快后慢 | return 1.0f – (1.0f – input) * (1.0f – input); | f(t) = 1 − (1−t)² | 开口向下抛物线 |
| AccelerateDecelerateInterpolator | 慢-快-慢 | return (float) (Math.cos(input * Math.PI) / 2.0 + 0.5); | f(t) = [cos(πt) + 1] / 2 | 半段余弦波 |
AOSP 源码原文:
// frameworks/base/core/java/android/view/animation/LinearInterpolator.java
public class</




