【BYM】Android 仿百度搜索列表滑动效果

public void setTranslationY(float translationY) {
if (translationY != getTranslationY()) {//判断设置的与当前位置是否相同
invalidateViewProperty(true, false);
//RenderNode包含View的属性属性
mRenderNode.setTranslationY(translationY);
invalidateViewProperty(false, true);

invalidateParentIfNeededAndWasQuickRejected();
notifySubtreeAccessibilityStateChangedIfNeeded();
}
}

/**

  • 视图属性更改(alpha、translationXY等)的快速失效。
  • 我们不想设置任何标志或处理默认失效方法处理的所有情况>
  • 相反,我们只想在ViewRootImpl中用适当的dirty rect安排一次遍历。
  • 此方法调用ViewGroup中的快速失效方法,这些方法在层次结构中遍历,并根据需要转换dirty rect。
  • 如果此视图中未使用显示列表属性,则该方法还处理正常的无效逻辑。
  • 该备份方法使用invalidateParent和forceRedraw标志来处理各种属性设置方法中使用的这些情
  • @param invalidateParent 如果此视图中未使用显示列表属性,
  • 则强制调用invalidateParentCaches()
  • @param forceRedraw 如果此视图中未使用显示列表属性,请将视图标记为“已绘制”以强制传播无效
    */
    @UnsupportedAppUsage
    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
    if (!isHardwareAccelerated()//是否支持硬件加速
    || !mRenderNode.hasDisplayList()//是否有需要绘制的缓冲数据
    || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {//view是否正在绘制
    if (invalidateParent) {//是否刷新父控件
    invalidateParentCaches();清楚parent view的缓存,不调用父控件的invalidate方法
    }
    if (forceRedraw) {
    mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
    }
    invalidate(false);//invalidate(boolean invalidateCache) 重绘(是否清除绘图缓存)
    } else {
    damageInParent();//告诉父视图破坏此View的边界。

}
}

  • Display List 是一个缓存绘制命令的 Buffer,Display List 的本质是一个缓冲区,它里面记录了即将要执行的绘制命令序列。

  • Display List 是视图的基本绘制元素,包含元素原始属性(位置、尺寸、角度、透明度等),对应 Canvas 的 drawXxx()方法。

  • 视图信息传递流程:Canvas(Java API) —> OpenGL(C/C++ Lib) —> 驱动程序 —> GPU

c. getY()和getRawY()

  • getRawX()、getRawY()返回的是触摸点相对于屏幕的位置,
  • getX()、getY()返回的则是触摸点相对于View的位置。

3. 思路

  • 弯路1: 想着设置layoutparams.marginTop来改变位置,但是视图刷新效果不行
  • 弯路2: 使用ValueAnimation来修改translateY,但发现有deraution。
  • 瞎猫碰到死耗子: 直接使用setTranslateY方法,改变view的位置,在down的时候记录按下的点位,move的时候判断是否移除位置超过上限和下限,up的时候判断手势方向,并自动setTranslateY到指定的下一个位置。

4. 源码

/**

  • @authoer create by markfrain
  • @github https://github.com/furuiCQ
  • 高怀见物理 和气得天真
  • 时间: 5/8/21
  • 描述: BaiduRecyclView
    */
    public class BaiduRecycleView extends RecyclerView {
    float lastY;
    float translateY;
    float lastDiff = 0f;
    float minVerticalY = 20;
    int topTranslateY = 10, centerTranslateY = 300, bottomTranslateY = 540;

public BaiduRecycleView(@NonNull Context context) {
super(context);
init();
}

public BaiduRecycleView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}

public BaiduRecycleView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}

private void init() {
translateY = DpUtils.dp2px(getContext(), centerTranslateY);
}

@Override
public boolean onTouchEvent(MotionEvent e) {
switch (e.getAction()) {
case MotionEvent.ACTION_DOWN:
lastY = e.getRawY();
return true;
case MotionEvent.ACTION_UP:
float rawY = lastY - e.getRawY();
if (translateY < DpUtils.dp2px(getContext(), centerTranslateY)) {
translateY = DpUtils.dp2px(getContext(), rawY > 0 ? topTranslateY : centerTranslateY);
setTranslationY(translateY);
} else if (translateY < DpUtils.dp2px(getContext(), bottomTranslateY)) {
translateY = DpUtils.dp2px(getContext(), rawY > 0 ? centerTranslateY : bottomTranslateY);
setTranslationY(translateY);
}
return true;
case MotionEvent.ACTION_MOVE:
rawY = lastY - e.getRawY();
float distance = lastDiff == 0f ? lastDiff : rawY - lastDiff;
lastDiff = rawY;
if (rawY > minVerticalY || rawY < -minVerticalY) {
if (translateY - distance < DpUtils.dp2px(getContext(), topTranslateY)) {
translateY = DpUtils.dp2px(getContext(), topTranslateY);
setTranslationY(DpUtils.dp2px(getContext(), topTranslateY));
} else if (translateY - distance > DpUtils.dp2px(getContext(), bottomTranslateY)) {
translateY = DpUtils.dp2px(getContext(), bottomTranslateY);
setTranslationY(DpUtils.dp2px(getContext(), bottomTranslateY));
} else {
translateY -= distance;
setTranslationY(translateY);
}
}
return false;
}
return super.onTouchEvent(e);
}

}
5. 效果展示

4mn1i-c64n1.gif
6. AnyWay

如果你还有更好,更酷炫,更精简的实现代码,也欢迎你没事的时候实现一下,相信你也能收获一点自己的知识。不止做一个高级的Copy工程师~o( ̄▽ ̄)ゞ,觉得文章有blow your mind,欢迎点赞,收藏,评论,欢迎指出我的问题,感谢感谢Thanks♪(・ω・)ノ。

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
img

面试复习笔记:

这份资料我从春招开始,就会将各博客、论坛。网站上等优质的Android开发中高级面试题收集起来,然后全网寻找最优的解答方案。每一道面试题都是百分百的大厂面经真题+最优解答。包知识脉络 + 诸多细节。
节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

《960页Android开发笔记》

《1307页Android开发面试宝典》

包含了腾讯、百度、小米、阿里、乐视、美团、58、猎豹、360、新浪、搜狐等一线互联网公司面试被问到的题目。熟悉本文中列出的知识点会大大增加通过前两轮技术面试的几率。

《507页Android开发相关源码解析》

只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。

真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
img
能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-gEwRpzEa-1712879608334)]

  • 20
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值