Android 那些事 – 欢迎页特效 (上推–推动门效果)
2015-06-18 21:20
253 查看
Android 那些事 – 欢迎页特效 (上推–推动门效果)
项目中开发欢迎页,本来是想做一个带有上推门效果的,后来设计说不要了,用了上下滑动的ViewPager,反正demo写出来了,顺便总结下。在Ata发了,发现csdn也可以用markdown了,顺便粘过来好了,排版都省了。
进入正题
之前在csdn中看到过一个帖子Android特效开发(仿zaker用手向上推动的效果(推动门效果))
帖子中介绍了通过Interpolator来实现弹跳效果。参考之后拿来改造了下,可以实现多个欢迎页的效果。
效果图如下所示【因为之前要求gif不能超过1M,所以删了一些帧,压缩了大小,也没法还原了】:
原文中有一个bug,上推如果距离比较大(不超过半个屏幕),当前的View是会“砸”回到底部,但是如果是慢慢拖动,慢慢放下,就会在底部留下几个像素的空白,就好像设置了MarginBottom一样,如果快速滑动有可能空白更大如下图:
测试发现是在计算Touch坐标时忘记了一个场景,假定手指在(40,50)处向上拨动屏幕,移动的最后位置很有可能按着屏幕(40,20)位置上。也就是mDelY的取值问题,当<0的时候可以正常,也就是说只要回到(40,50)坐标之上就可以正常回到屏幕底部,如果一旦回到(40,50)坐标之下就不行了。理论上触摸滑动向上X个单位,向下回来的时候也应该是X个单位,但是在Log中测试发现不一定,有可能向上滑动X个单位,实际返回时滑动Y个单位【这里我也是不解,感觉是UI线程没有来得及处理吧】,总之是有偏差的。
[code]public boolean onTouchEvent(MotionEvent event) { int action = event.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: mLastDownY = (int) event.getY(); return true; case MotionEvent.ACTION_MOVE: mCurryY = (int) event.getY(); mDelY = mCurryY - mLastDownY; if (mDelY < 0) {//上滑有效,把当前View向上滑动 scrollTo(0, -mDelY); } break;
解决的方法也就一句代码:在处理UP事件时,添加一个分支,即当捕获到UP事件的时候,再执行一下
startBounceAnim(this.getScrollY(), -this.getScrollY(), 450);也就是当松开手指的时候,强制view回到屏幕底部。
然后添加多个页面,同时可以回到上一个页面功能。
在欢迎页面中,手指向下滑动大约1/3时,把上一个页面调出来,修改ACTION_MOVE事件代码:其中
getScrollY()==0目的是为了 保证只有当前View在屏幕底部时向下滑动才会出现上一个页面 。如果刚好先向上滑动,再向下滑动也会触发次操作,为了避免冲突,需要判断此时并没有向上滑动过。
[code]case MotionEvent.ACTION_MOVE: mCurryY = (int) event.getY(); mDelY = mCurryY - mLastDownY; if (mDelY < 0) {//上滑有效,把当前View向上滑动 scrollTo(0, -mDelY); }else{//如果向下画的距离超过了1/3,把上一个页面弄出来 if(this.getScrollY()==0 && mDelY>mScreenHeigh / 3){ mActivity.showView(false); } }
在
computeScroll方法中添加一个关闭当前页面的分支。
[code]public void computeScroll() { if (mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); // 不要忘记更新界面 postInvalidate(); } else { if (mCloseFlag) {//关闭此页面, this.setVisibility(View.GONE); mActivity.showView(true);//进入到新的view } } }
showView(boolean flag)是Activity中的方法,根据flag标记来判断当前应该下一个页面还是上一个页面,因为所有的View都在Activity中管理。其中mCurrentIndex表示当前页面中为第几个View,mWelcomView为类型为PullDoorView的数组。
[code]public void showView(boolean flag) { if (flag) {// 打开下一个页面 if (mCurrentIndex == 0) { ++mCurrentIndex; } if (mCurrentIndex == mViewSize - 1) {// 已经是最后一个或者第一个,则只需要开启动画即可 return; } else {// 先关闭当前动画,然后再开启新页面动画 ++mCurrentIndex; } } else {// 打开上一个页面 if (mCurrentIndex == 0) {// 已经是第一个,不能再回退了 return; }//如果上一页还有view,则显示上一页的内容,把上一页的view“砸”下来 mWelcomView[--mCurrentIndex].setVisibility(View.VISIBLE); mWelcomView[mCurrentIndex].mCloseFlag = false;// 不需要关闭 mWelcomView[mCurrentIndex].startBounceAnim( mWelcomView[mCurrentIndex].getScrollY(), -mWelcomView[mCurrentIndex].getScrollY(), 1000); } }
代码最后贴在了github上。
还是有很多不足,比如说在PullDoorView中调用了Activity中的方法,view做了与自身无关的一些操作,还没想到好的解决方法;当返回上一个页面时,是直接通过执行返回动画,比较生硬;上滑的时候是根据距离计算是否显示下一个页面,如果快速滑动经常无法触发显示下一个页面的动作,应该再加上一个根据滑动的速度来判断等。
相关文章推荐
- Android中蓝牙通信的实现
- Android-样式及主题
- 英语词典
- Android基于TrafficStats实现实时流量统计
- android-custom-tab-with-viewpager
- 【Android】INSTALL_PARSE_FAILED_MANIFEST_MALFORMED错误与Not targeting the latest versions警告
- Android:Fragment笔记
- Android基础教程之Button事件触发AlertDialog简单小窗口的应用
- android之修改系统自带ProgressDialog样式
- android EditText获取光标位置并安插字符删除字符
- Android 常用RGB值及名称
- Android AsyncTask 详解
- 【Android】利用Notification操作设备的通知栏
- Android安卓电话拦截及短信过滤
- Android实战页面内容加载动画
- 【进阶android】ListView源码分析——适配器及观察者模式
- 关于android.view.WindowLeaked异常的解决方案
- Android PinnedSectionListView 收缩
- Android系统中Parcelable和Serializable的区别
- Android getWindow().setFlags(。。。。。。)