Android 仿新版微信的小程序下拉栏

上周微信更新到了 6.6.1 版本,加入了微信小游戏。朋友圈都在玩跳一跳。而且现在微信把最近用过的小程序放到了首页顶部,轻轻下拉就可以快速访问了。可以看下效果,如果还没升级的朋友可要抓紧了。

自己作为一个安卓程序员,虽然不会写小程序,但也要紧跟热潮(蹭热点)啊。于是乎就干脆仿写下这个下拉控件吧。第七宇宙惯例,先上效果图:

上图的主界面是我上一篇文章《撸一款全手势操作浏览器》写的 demo。写完这个控件,发现正好可以作为它的下拉菜单栏,就直接用上了。好了,废话不多说,开始介绍下实现流程。

流程分析

整个下拉过程分为四个阶段:阶段一:出现一个原点,半径随下拉距离变大而变大。位置始终在中间

阶段二:原点两边出现两个原点,半径较小。距离随下拉距离变大而变大,中间原点半径不断变小。位置始终在中间

阶段三:从顶部出现内容列表,位置随手指下拉快速往下移动,同时三个原点位置不断下移并逐渐消失

阶段四:只剩下内容列表,手指可以继续往下滑动,但阻尼变大。内容列表始终在中间。

上滑分两种情况:如果开始上滑的时候内容列表已展开,则平移上滑(原点不会出现)

反之,就是下拉的逆过程了(原点会出现)。

具体实现

熟悉下拉刷新控件的同学可以看出来,上述滑动的流程和下拉刷新很相似,所以为了避免重复造轮子(偷懒),我将下拉刷新控件作了改动,所以主要的实现还是在头部那块。

初始布局位置

将头部放到屏幕外层的方法有很多。我采用了设置负数 padding 的方法。外层布局继承了 LinearLayout,方向竖直。然后为其设置 padding:headerHeight=(null!=mHeaderLayout)?mHeaderLayout.getMeasuredHeight():0;

intpLeft=getPaddingLeft();

intpTop=-headerHeight;

intpRight=getPaddingRight();

intpBottom=-footerHeight;

setPadding(pLeft,pTop,pRight,pBottom);

paddingTop 的值等于负的 HeaderLayout 的高度,这样正好将头部布局顶到屏幕外面。

处理触摸事件

这块主要内容就是复写booleanonInterceptTouchEvent(MotionEventevent)和booleanonTouchEvent(MotionEventev)@Override

public

final

boolean

onInterceptTouchEvent

(MotionEventevent)

{

finalintaction=event.getAction();

//不拦截

if(action==MotionEvent.ACTION_CANCEL||action==MotionEvent.ACTION_UP){

mIsHandledTouchEvent=false;

returnfalse;

}

//如果不是重新开始触摸且已经判断需要拦截,就一直拦截整套触摸事件

if(action!=MotionEvent.ACTION_DOWN&&mIsHandledTouchEvent){

returntrue;

}

switch(action){

caseMotionEvent.ACTION_DOWN:

mLastMotionY=event.getY();

mIsHandledTouchEvent=false;

break;

caseMotionEvent.ACTION_MOVE:

finalfloatdeltaY=event.getY()-mLastMotionY;

finalfloatabsDiff=Math.abs(deltaY);

// 位移差大于mTouchSlop,这是为了防止快速拖动引发刷新

if((absDiff>mTouchSlop)){

mLastMotionY=event.getY();

// 第一个显示出来,Header已经显示或拉下

if(isPullRefreshEnabled()&&isReadyForPullDown()){

// 1,Math.abs(getScrollY()) > 0:表示当前滑动的偏移量的绝对值大于0,表示当前HeaderView滑出来了或完全

// 不可见,存在这样一种case,当正在刷新时并且RefreshableView已经滑到顶部,向上滑动,那么我们期望的结果是

// 依然能向上滑动,直到HeaderView完全不可见

// 2,deltaY > 0.5f:表示下拉的值大于0.5f

mIsHandledTouchEvent=(Math.abs(getScrollYValue())>0||deltaY>0.5f);

}

}

break;

default:

break;

}

returnmIsHandledTouchEvent;//true:拦截,false不拦截

}

如果拦截了,我们处理滑动. 其中 offsetRadio 是滑动阻尼值。@OverridepublicfinalbooleanonTouchEvent(MotionEventev){

booleanhandled=false;

switch(ev.getAction()){

caseMotionEvent.ACTION_DOWN:

mLastMotionY=ev.getY();

mIsHandledTouchEvent=false;

break;

caseMotionEvent.ACTION_MOVE:

finalfloatdeltaY=ev.getY()-mLastMotionY;

mLastMotionY=ev.getY();

if(isPullRefreshEnabled()&&isReadyForPullDown()){

pullHeaderLayout(deltaY/offsetRadio);

handled=true;

}else{

mIsHandledTouchEvent=false;

}

break;

caseMotionEvent.ACTION_CANCEL:

caseMotionEvent.ACTION_UP:

if(mIsHandledTouchEvent){

mIsHandledTouchEvent=false;

// 当第一个显示出来时

if(isReadyForPullDown()){

// 调用刷新

if(mPullRefreshEnabled&&(mPullDownState==State.RELEASE_TO_REFRESH)){

startRefreshing();

handled=true;

}

resetHeaderLayout();

}

}

break;

default:

break;

}

returnhandled;

}

最终我们会通过 pullHeaderLayout 调用 View 的 scrollBy(x, y) 方法将布局整体滚动。

遇到的一个问题

我在上面这样写好之后,跑了一遍,发现onInterceptTouchEvent只执行了 ACTION_DOWN,ACTION_MOVE 事件不会执行,也就无法拦截和进行滑动了。百度下原来有这么一个规则:

onInterceptTouchEvent返回 false 表示将 down 事件交由子 View 来处理;若某一层子 View 的 onTouchEvent 返回了 true,后续的 move、up 等事件都将先传递到 ViewGroup 的onInterceptTouchEvent的方法,并继续层层传递下去,交由子 View 处理;若子 View 的 onTouchEvent 都返回了 false,则 down 事件将交由该 ViewGroup 的 onTouchEvent 来处理;如果 ViewGroup 的 onTouchEvent 返回 true,后续事件不再经过该 ViewGroup 的onInterceptTouchEvent方法,直接传递给 onTouchEvent 方法处理。

因为目前的子 View 是 RelativeLayout,它的 onTouchEvent 默认返回了 false(ListView 等其他可滑动的控件不会有这个问题)。解决办法是设置android:clickable="true"。

头部的实现

上面我说过滑动有四个阶段,只要将滑动距离传递给自定义头部,根据距离判断状态,实时改变内容列表的 TranslationY,原点的 TranslationY 和 Alpha 就可以了。实现起来也是比较简单的。详细的代码就不贴了,大家感兴趣的可以去看源码。至于原点动画,也是一个自定义 View,外层只要根据滑动距离换算下动画的百分比传进去,在里面画出需要的图形就行了,百分比是 0.5 的时候出现三个圆 :public

class

ExpendPoint

extends

View

{

floatpercent;

floatmaxRadius=15;

floatmaxDist=60;

PaintmPaint;

publicExpendPoint(Contextcontext,@NullableAttributeSetattrs){

super(context,attrs);

mPaint=newPaint();

mPaint.setAntiAlias(true);

mPaint.setColor(Color.GRAY);

}

public

void

setPercent

(floatpercent)

{

this.percent=percent;

invalidate();

}

@Override

protected

void

onDraw

(Canvascanvas)

{

super.onDraw(canvas);

floatcenterX=getWidth()/2;

floatcenterY=getHeight()/2;

if(percent<=0.5f){只画一个圆

mPaint.setAlpha(255);

floatradius=percent*2*maxRadius;

canvas.drawCircle(centerX,centerY,radius,mPaint);

}else{//画三个个圆

floatafterPercent=(percent-0.5f)/0.5f;

floatradius=maxRadius-maxRadius/2*afterPercent;

canvas.drawCircle(centerX,centerY,radius,mPaint);

canvas.drawCircle(centerX-afterPercent*maxDist,centerY,maxRadius/2,mPaint);

canvas.drawCircle(centerX+afterPercent*maxDist,centerY,maxRadius/2,mPaint);

}

}

}

来源: https://juejin.im/post/5a4c90c15188257c4d1b8d0c

android微信下拉出现小程序,Android 仿新版微信的小程序下拉栏相关推荐

  1. android微信下拉出现小程序,仿新版微信的小程序下拉栏

    原标题:仿新版微信的小程序下拉栏 本项目会对金融交易软件中存在的各种View进行模仿绘制,提供详细的实现思路,收集整理相关算法.文档以及专业资料. https://github.com/scsfwgy ...

  2. android 自定义Scrollview实现淘宝二层楼效果新版微信小程序下拉效果

    android 自定义Scrollview实现淘宝二层楼效果新版微信小程序下拉效果 由于最近一段时间真的是太忙了,没有顾上即使更新博客,还请粉丝们见谅,最近要实现这样一个效果,这个效果跟淘宝二层楼和新 ...

  3. android布局管理器模仿qq登录效果,Android程序开发仿新版QQ锁屏下弹窗功能

    新版的qq,可以在锁屏下弹窗显示qq消息,正好目前在做的项目也需要这一功能.经过各种试验和资料查找,终于实现,过程不难,但是却有一些地方需要注意. 下面是实现过程. 1.使用Activity,而不是V ...

  4. iOS高仿新版微信扫一扫源码

    iOS版本高仿新版微信V8.0.6扫一扫.支持全屏扫码,支持识别多个二维码,支持选择指定二维码,支持从相册选取二维码,支持光线暗打开手电筒.无需多余的文件,一个Controller即可搞定,可继承,可 ...

  5. 解除微信接收文件只读属性的最新解决方案,新版微信3.9.2.23也能用,适用范围更广,没有微信版本要求,不需要微信降级

    从3.9版本开始,微信PC端默认将接收到的Word.Excel等文件的文件属性设置为只读,这使得大家在打开文件后,对文件的修改只能以另存为新文件的方式进行保存,一时间很多小伙伴还不能接受这种设置. 之 ...

  6. 开启微信悬浮窗权限有什么用_新版微信功能!微信也可以设置主题皮肤了,不再是单调的白色,这也太好看了吧!...

    阅读本文前,请您先点击上面的"蓝色字体",再点击"关注",这样您就可以继续免费收到文章了.每天都会有分享,都是免费订阅,请您放心关注.注:本文转载自网络,不代表 ...

  7. Android仿新版微信的小程序下拉栏

    作者:大头呆 链接:https://juejin.im/post/5a4c90c15188257c4d1b8d0c 本文经作者授权推送. 上周微信更新到了6.6.1版本,加入了微信小游戏.朋友圈都在玩 ...

  8. 仿新版支付宝账单页面滑动时月份栏被下一个月给顶上去

    前段时间支付宝账单出现了新特效,就是下月账单可以推送上月账单的吸顶位置. 不多说上代码: 首先:HTML <div class="list" v-for="item ...

  9. python小游戏毕设 仿八分音符的声控小游戏设计与实现 (源码)

    文章目录 0 项目简介 1 游戏介绍 2 实现效果 3 开发工具 3.1 环境配置 3.2 Pygame介绍 4 具体实现 5 最后 0 项目简介

最新文章

  1. 关于csgo的观看录像fps低_中国CSGO神秘天才欲初登赛场!却因这件事被无数人所质疑!!...
  2. 计算机视觉不可能凉!
  3. poj1655Multiplication Puzzle
  4. mysql 面试知识点笔记(二)查询优化及索引越多越好吗?
  5. Golang 计算MD5值示例
  6. C语言 利用malloc()和realloc()动态分配内存
  7. 【转】执行Import-SPWeb报错Import-SPWeb : Requested value 'PublishingPages' was not found
  8. (八大方法、逐层深入,有你一定没见过的)使用INSERT语句向表中插入数据
  9. android 还可以输入多少个字符
  10. linux下安装rar解压包
  11. 文献阅读 An incremental density-based clustering framework using fuzzy local clustering
  12. 腾讯云对象存储(cos) js jdk上传文件
  13. android axis2 webservice实例,Axis2创建WebService实例.doc
  14. 【愚公系列】2022年04月 微信小程序-Flex布局详解
  15. 三大知名PHP开源多用户商城系统对比
  16. 美通企业日报 | 英特尔20亿美元收购AI芯片制造商;嘉吉投资扩建河北嘉好粮油...
  17. Win7设置开机密码后开机不需要输入密码
  18. iOS 手机号码验证
  19. php独孤九剑,针对浏览器隐藏CSS之独孤九剑_经验交流
  20. WinForm在窗体中嵌入窗体

热门文章

  1. 如何写出完美的PLC程序?
  2. 计算机二级课程论文摘要,摘要、论文格式概念.doc
  3. 视觉设计和平面设计的区别,看完之后你就明白了
  4. 【go】结合一个go开源项目分析谷歌浏览器cookie为什么不安全 附go项目导包失败怎么解决教程
  5. ie 浏览器直接打印与非ie
  6. 最大子列和问题的分治算法
  7. Netconf协议学习笔记
  8. c++性能优化(cpu篇)
  9. 树莓派使用RFID-RC522A读卡器对IC卡进行读写(通过 python)
  10. EA开发系列---回测