
最近看到了好多高端、大气、上档次的动画效果,如果给你的项目中加上这些动画,相信你的app一定很优秀,今天给大家分析一下来自Yalantis的一个超好看的下拉刷新动画。
首先我们看一下效果如何:
怎么样?是不是很高大上?接下来我们看一下代码:
一、首先我们需要自定义刷新的动态RefreshVIEw(也就是下拉时候的头)
1.初始化头所占用的Dimens
private voID initiateDimens() { mScreenWIDth = mContext.getResources().getdisplayMetrics().wIDthPixels; mJettopOffset = mParent.getTotalDragdistance() * 0.5f; mtop = -mParent.getTotalDragdistance(); } 2.为头填充图片,设置图片的大小
分别为左边的云彩,右边的云彩,中间的云彩还有中间的飞机,飞机是带有动画的,下面会介绍飞机的动画
private voID createBitmaps() { mleftClouds = BitmapFactory.decodeResource(mContext.getResources(),R.drawable.clouds_left); mRightClouds = BitmapFactory.decodeResource(mContext.getResources(),R.drawable.clouds_right); mFrontClouds = BitmapFactory.decodeResource(mContext.getResources(),R.drawable.clouds_center); mJet = BitmapFactory.decodeResource(mContext.getResources(),R.drawable.airplane); mJetWIDthCenter = mJet.getWIDth() / 2; mJetHeightCenter = mJet.getHeight() / 2; mFrontClouDWIDthCenter = mFrontClouds.getWIDth() / 2; mFrontCloudHeightCenter = mFrontClouds.getHeight() / 2; mRightCloudsWIDthCenter = mRightClouds.getWIDth() / 2; mRightCloudsHeightCenter = mRightClouds.getHeight() / 2; mleftCloudsWIDthCenter = mleftClouds.getWIDth() / 2; mleftCloudsHeightCenter = mleftClouds.getHeight() / 2; } 3.然后我们来画这个头
public voID draw(@NonNull Canvas canvas) { final int saveCount = canvas.save(); // DRAW BACKGROUND. canvas.drawcolor(mContext.getResources().getcolor(R.color.sky_background)); if (isRefreshing) { // Set up new set of wind while (mWinds.size() < WIND_SET_AMOUNT) { float y = (float) (mParent.getTotalDragdistance() / (Math.random() * RANDOM_Y_COEFFICIENT)); float x = random(MIN_WIND_X_OFFSET,MAX_WIND_X_OFFSET); // Magic with checking interval between winds if (mWinds.size() > 1) { y = 0; while (y == 0) { float tmp = (float) (mParent.getTotalDragdistance() / (Math.random() * RANDOM_Y_COEFFICIENT)); for (Map.Entry<float,float> wind : mWinds.entrySet()) { // We want that interval will be greater than fifth part of draggable distance if (Math.abs(wind.getKey() - tmp) > mParent.getTotalDragdistance() / RANDOM_Y_COEFFICIENT) { y = tmp; } else { y = 0; break; } } } } mWinds.put(y,x); drawWind(canvas,y,x); } // Draw current set of wind if (mWinds.size() >= WIND_SET_AMOUNT) { for (Map.Entry<float,float> wind : mWinds.entrySet()) { drawWind(canvas,wind.getKey(),wind.getValue()); } } // We should to create new set of winds if (mInverseDirection && mNewWindSet) { mWinds.clear(); mNewWindSet = false; mWindlinewidth = random(MIN_WIND_liNE_WIDTH,MAX_WIND_liNE_WIDTH); } // needed for checking direction mLastAnimationTime = mloadingAnimationTime; } drawJet(canvas); drawSIDeClouds(canvas); drawCenterClouds(canvas); canvas.restoretoCount(saveCount); } /** * Draw wind on loading animation * * @param canvas - area where we will draw * @param y - y position fot one of lines * @param xOffset - x offset for on of lines */ private voID drawWind(Canvas canvas,float y,float xOffset) { /* We should multiply current animation time with this coefficIEnt for taking all screen wIDth in time Removing slowing of animation with divIDing on {@link #SLOW_DOWN_ANIMATION_COEFFICIENT} And we should don't forget about distance that should "fly" line that depend on screen of device and x offset */ float cof = (mScreenWIDth + xOffset) / (LOADING_ANIMATION_COEFFICIENT / SLOW_DOWN_ANIMATION_COEFFICIENT); float time = mloadingAnimationTime; // HORRIBLE Hack FOR REVERS ANIMATION THAT SHOulD WORK liKE RESTART ANIMATION if (mLastAnimationTime - mloadingAnimationTime > 0) { mInverseDirection = true; // take time from 0 to end of animation time time = (LOADING_ANIMATION_COEFFICIENT / SLOW_DOWN_ANIMATION_COEFFICIENT) - mloadingAnimationTime; } else { mNewWindSet = true; mInverseDirection = false; } // Taking current x position of drawing wind // For fully disappearing of line we should subtract wind line wIDth float x = (mScreenWIDth - (time * cof)) + xOffset - mWindlinewidth; float xEnd = x + mWindlinewidth; canvas.drawline(x,xEnd,mWindPaint); } private voID drawSIDeClouds(Canvas canvas) { Matrix matrixleftClouds = mMatrix; Matrix matrixRightClouds = mAdditionalMatrix; matrixleftClouds.reset(); matrixRightClouds.reset(); // Drag percent will newer get more then 1 here float dragPercent = Math.min(1f,Math.abs(mPercent)); boolean overdrag = false; // But we check here for overdrag if (mPercent > 1.0f) { overdrag = true; } float scale; float scalePercentDelta = dragPercent - SCALE_START_PERCENT; if (scalePercentDelta > 0) { float scalePercent = scalePercentDelta / (1.0f - SCALE_START_PERCENT); scale = SIDE_CLOUDS_INITIAL_SCALE + (SIDE_CLOUDS_FINAL_SCALE - SIDE_CLOUDS_INITIAL_SCALE) * scalePercent; } else { scale = SIDE_CLOUDS_INITIAL_SCALE; } // Current y position of clouds float dragYOffset = mParent.getTotalDragdistance() * (1.0f - dragPercent); // position where clouds fully visible on screen and we should drag them with content of ListVIEw int cloudsVisibleposition = mParent.getTotalDragdistance() / 2 - mleftCloudsHeightCenter; boolean needMoveCloudsWithContent = false; if (dragYOffset < cloudsVisibleposition) { needMoveCloudsWithContent = true; } float offsetRightX = mScreenWIDth - mRightClouds.getWIDth(); float offsetRightY = (needMoveCloudsWithContent ? mParent.getTotalDragdistance() * dragPercent - mleftClouds.getHeight() : dragYOffset) + (overdrag ? mtop : 0); float offsetleftX = 0; float offsetleftY = (needMoveCloudsWithContent ? mParent.getTotalDragdistance() * dragPercent - mleftClouds.getHeight() : dragYOffset) + (overdrag ? mtop : 0); // Magic with animation on loading process if (isRefreshing) { if (checkCurrentAnimationPart(AnimationPart.FirsT)) { offsetleftY += getAnimationPartValue(AnimationPart.FirsT) / Y_SIDE_CLOUDS_SLOW_DOWN_COF; offsetRightX -= getAnimationPartValue(AnimationPart.FirsT) / X_SIDE_CLOUDS_SLOW_DOWN_COF; } else if (checkCurrentAnimationPart(AnimationPart.SECOND)) { offsetleftY += getAnimationPartValue(AnimationPart.SECOND) / Y_SIDE_CLOUDS_SLOW_DOWN_COF; offsetRightX -= getAnimationPartValue(AnimationPart.SECOND) / X_SIDE_CLOUDS_SLOW_DOWN_COF; } else if (checkCurrentAnimationPart(AnimationPart.THIRD)) { offsetleftY -= getAnimationPartValue(AnimationPart.THIRD) / Y_SIDE_CLOUDS_SLOW_DOWN_COF; offsetRightX += getAnimationPartValue(AnimationPart.THIRD) / X_SIDE_CLOUDS_SLOW_DOWN_COF; } else if (checkCurrentAnimationPart(AnimationPart.FOURTH)) { offsetleftY -= getAnimationPartValue(AnimationPart.FOURTH) / X_SIDE_CLOUDS_SLOW_DOWN_COF; offsetRightX += getAnimationPartValue(AnimationPart.FOURTH) / Y_SIDE_CLOUDS_SLOW_DOWN_COF; } } matrixRightClouds.postscale(scale,scale,mRightCloudsWIDthCenter,mRightCloudsHeightCenter); matrixRightClouds.postTranslate(offsetRightX,offsetRightY); matrixleftClouds.postscale(scale,mleftCloudsWIDthCenter,mleftCloudsHeightCenter); matrixleftClouds.postTranslate(offsetleftX,offsetleftY); canvas.drawBitmap(mleftClouds,matrixleftClouds,null); canvas.drawBitmap(mRightClouds,matrixRightClouds,null); } private voID drawCenterClouds(Canvas canvas) { Matrix matrix = mMatrix; matrix.reset(); float dragPercent = Math.min(1f,Math.abs(mPercent)); float scale; float overdragPercent = 0; boolean overdrag = false; if (mPercent > 1.0f) { overdrag = true; // Here we want kNow about how mach percent of over drag we done overdragPercent = Math.abs(1.0f - mPercent); } float scalePercentDelta = dragPercent - SCALE_START_PERCENT; if (scalePercentDelta > 0) { float scalePercent = scalePercentDelta / (1.0f - SCALE_START_PERCENT); scale = CENTER_CLOUDS_INITIAL_SCALE + (CENTER_CLOUDS_FINAL_SCALE - CENTER_CLOUDS_INITIAL_SCALE) * scalePercent; } else { scale = CENTER_CLOUDS_INITIAL_SCALE; } float parallaxPercent = 0; boolean parallax = false; // Current y position of clouds float dragYOffset = mParent.getTotalDragdistance() * dragPercent; // position when should start parallax scrolling int startParallaxHeight = mParent.getTotalDragdistance() - mFrontCloudHeightCenter; if (dragYOffset > startParallaxHeight) { parallax = true; parallaxPercent = dragYOffset - startParallaxHeight; } float offsetX = (mScreenWIDth / 2) - mFrontClouDWIDthCenter; float offsetY = dragYOffset - (parallax ? mFrontCloudHeightCenter + parallaxPercent : mFrontCloudHeightCenter) + (overdrag ? mtop : 0); float sx = overdrag ? scale + overdragPercent / 4 : scale; float sy = overdrag ? scale + overdragPercent / 2 : scale; if (isRefreshing && !overdrag) { if (checkCurrentAnimationPart(AnimationPart.FirsT)) { sx = scale - (getAnimationPartValue(AnimationPart.FirsT) / LOADING_ANIMATION_COEFFICIENT) / 8; } else if (checkCurrentAnimationPart(AnimationPart.SECOND)) { sx = scale - (getAnimationPartValue(AnimationPart.SECOND) / LOADING_ANIMATION_COEFFICIENT) / 8; } else if (checkCurrentAnimationPart(AnimationPart.THIRD)) { sx = scale + (getAnimationPartValue(AnimationPart.THIRD) / LOADING_ANIMATION_COEFFICIENT) / 6; } else if (checkCurrentAnimationPart(AnimationPart.FOURTH)) { sx = scale + (getAnimationPartValue(AnimationPart.FOURTH) / LOADING_ANIMATION_COEFFICIENT) / 6; } sy = sx; } matrix.postscale(sx,sy,mFrontClouDWIDthCenter,mFrontCloudHeightCenter); matrix.postTranslate(offsetX,offsetY); canvas.drawBitmap(mFrontClouds,matrix,null); } private voID drawJet(Canvas canvas) { Matrix matrix = mMatrix; matrix.reset(); float dragPercent = mPercent; float rotateAngle = 0; // Check overdrag if (dragPercent > 1.0f && !mEndOfRefreshing) { rotateAngle = (dragPercent % 1) * 10; dragPercent = 1.0f; } float offsetX = ((mScreenWIDth * dragPercent) / 2) - mJetWIDthCenter; float offsetY = mJettopOffset + (mParent.getTotalDragdistance() / 2) * (1.0f - dragPercent) - mJetHeightCenter; if (isRefreshing) { if (checkCurrentAnimationPart(AnimationPart.FirsT)) { offsetY -= getAnimationPartValue(AnimationPart.FirsT); } else if (checkCurrentAnimationPart(AnimationPart.SECOND)) { offsetY -= getAnimationPartValue(AnimationPart.SECOND); } else if (checkCurrentAnimationPart(AnimationPart.THIRD)) { offsetY += getAnimationPartValue(AnimationPart.THIRD); } else if (checkCurrentAnimationPart(AnimationPart.FOURTH)) { offsetY += getAnimationPartValue(AnimationPart.FOURTH); } } matrix.setTranslate(offsetX,offsetY); if (dragPercent == 1.0f) { matrix.preRotate(rotateAngle,mJetWIDthCenter,mJetHeightCenter); } canvas.drawBitmap(mJet,null); } 动画效果已经画好了,下面我们来看看怎么结合下拉刷新来调用吧?
二、我们还需要自定义一个PullToRefreshVIEw(下拉刷新)
1.我们的PullToRefreshVIEw这里需要继承VIEwGroup
我们先把刚才定义的刷新时的动画加进来
private RefreshVIEw mRefreshVIEw; <pre name="code" >private ImageVIEw mRefreshImageVIEw; <pre name="code" >mRefreshImageVIEw = new ImageVIEw(context); mRefreshVIEw = new RefreshVIEw(getContext(),this); mRefreshImageVIEw.setimageDrawable(mRefreshVIEw); addVIEw(mRefreshImageVIEw);
2.然后我们设置OntouchEvent()事件
@OverrIDe public boolean ontouchEvent(@NonNull MotionEvent ev) { if (!mIsBeingDragged) { return super.ontouchEvent(ev); } final int action = MotionEventCompat.getActionMasked(ev); switch (action) { case MotionEvent.ACTION_MOVE: { final int pointerIndex = MotionEventCompat.findPointerIndex(ev,mActivePointerID); if (pointerIndex < 0) { return false; } final float y = MotionEventCompat.getY(ev,pointerIndex); final float yDiff = y - mInitialMotionY; final float scrolltop = yDiff * DRAG_RATE; mCurrentDragPercent = scrolltop / mTotalDragdistance; if (mCurrentDragPercent < 0) { return false; } float boundedDragPercent = Math.min(1f,Math.abs(mCurrentDragPercent)); float extraOS = Math.abs(scrolltop) - mTotalDragdistance; float slingshotdist = mTotalDragdistance; float tensionSlingshotPercent = Math.max(0,Math.min(extraOS,slingshotdist * 2) / slingshotdist); float tensionPercent = (float) ((tensionSlingshotPercent / 4) - Math.pow( (tensionSlingshotPercent / 4),2)) * 2f; float extraMove = (slingshotdist) * tensionPercent / 2; int targetY = (int) ((slingshotdist * boundedDragPercent) + extraMove); mRefreshVIEw.setPercent(mCurrentDragPercent); setTargetoffsettop(targetY - mCurrentOffsettop,true); break; } case MotionEventCompat.ACTION_POINTER_DOWN: final int index = MotionEventCompat.getActionIndex(ev); mActivePointerID = MotionEventCompat.getPointerID(ev,index); break; case MotionEventCompat.ACTION_POINTER_UP: onSecondaryPointerUp(ev); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: { if (mActivePointerID == INVALID_POINTER) { return false; } final int pointerIndex = MotionEventCompat.findPointerIndex(ev,mActivePointerID); final float y = MotionEventCompat.getY(ev,pointerIndex); final float overScrolltop = (y - mInitialMotionY) * DRAG_RATE; mIsBeingDragged = false; if (overScrolltop > mTotalDragdistance) { setRefreshing(true,true); } else { mRefreshing = false; animateOffsetToposition(mAnimatetoStartposition); } mActivePointerID = INVALID_POINTER; return false; } } return true; } 三、最后我们看怎样在Activity中使用这个下拉刷新控件
1.先看一下布局文件
这里是我们的下拉刷新空间嵌套着我们的ListVIEw,然后我们再给ListVIEw填充数据即可
<relativeLayout xmlns:androID="http://schemas.androID.com/apk/res/androID" xmlns:tools="http://schemas.androID.com/tools" androID:layout_wIDth="match_parent" androID:layout_height="match_parent" tools:context=".PullToRefreshActivity"> <com.hankkin.AnimationPullToRefreshDemo.PullToRefreshVIEw androID:ID="@+ID/pull_to_refresh" androID:layout_wIDth="match_parent" androID:layout_height="match_parent"> <ListVIEw androID:ID="@+ID/List_vIEw" androID:divIDer="@null" androID:divIDerHeight="0dp" androID:fadingEdge="none" androID:layout_wIDth="match_parent" androID:layout_height="match_parent" /> </com.hankkin.AnimationPullToRefreshDemo.PullToRefreshVIEw> </relativeLayout>
2.为ListVIEw填充数据
为了我们的效果比较好看,这里我们给ListVIEw的每一个item填充不同的颜色,看起来会比较高大上。
Map<String,Integer> map; List<Map<String,Integer>> sampleList = new ArrayList<Map<String,Integer>>(); int[] colors = { R.color.saffron,R.color.eggplant,R.color.sIEnna}; int[] tripnames = { R.string.trip_to_india,R.string.trip_to_italy,R.string.trip_to_indonesia}; for (int i = 0; i < tripnames.length; i++) { map = new HashMap<String,Integer>(); map.put(SampleAdapter.KEY_name,tripnames[i]); map.put(SampleAdapter.KEY_color,colors[i]); sampleList.add(map); } ListVIEw ListVIEw = (ListVIEw) findVIEwByID(R.ID.List_vIEw); ListVIEw.setAdapter(new SampleAdapter(this,R.layout.List_item,sampleList)); 3.最后,我们再设置一下下拉刷新的监听事件就OK了
mpullToRefreshVIEw = (PullToRefreshVIEw) findVIEwByID(R.ID.pull_to_refresh); mpullToRefreshVIEw.setonRefreshListener(new PullToRefreshVIEw.OnRefreshListener() { @OverrIDe public voID onRefresh() { mpullToRefreshVIEw.postDelayed(new Runnable() { @OverrIDe public voID run() { mpullToRefreshVIEw.setRefreshing(false); } },REFRESH_DELAY); } }); 怎么样?有没有很高大上啊?
大家可以动手实践一下,希望对大家的学习有所帮助。
总结以上是内存溢出为你收集整理的超好看的下拉刷新动画Android代码实现全部内容,希望文章能够帮你解决超好看的下拉刷新动画Android代码实现所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)