Android从零开始(第五篇)手把手教撸一个仿饿了么LoadingView(一)

前言

过年放假前最后一天班,就想着做个简单又有趣的小东西。于是决定来写个自定义的LoadingView作为这个App框架的加载效果吧

走过路过点歌Start O(∩_∩)O Github项目地址

这篇文章叫你如何搭建手写LoadingView,看完这篇文章你能学会:

  1. 属性动画使用
  2. 自定义View

--------------------------------关门,上分割线------------------------------------------------ 先看看效果:

有点像饿了么那种风格。 最重要的,在看到这个效果之前脑中想到的实现思路:

1.创建item_loading_view.xml布局,把样式先写出来
2.自定义View,加载这个自定义布局
3.自定义View内做动画处理
复制代码

1.布局:item_loading_view.xml

"1.0" encoding="utf-8"?>
"http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:padding="24dp"
    android:layout_height="148dp">

    "@+id/iv_loading"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:layout_above="@+id/tv_loading"
        android:src="@drawable/ic_favorites" />
    "@+id/tv_loading"
        android:layout_width="wrap_content"
        android:text="加载中..."
        android:layout_marginTop="12dp"
        android:layout_centerHorizontal="true"
        android:layout_alignParentBottom="true"
        android:layout_height="wrap_content" />


复制代码

2.自定义View

public class LoadingView extends FrameLayout {

    public LoadingView(Context context) {
        this(context,null);
    }

    public LoadingView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public LoadingView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        // 加载布局
        LayoutInflater.from(mContext).inflate(R.layout.item_loading_view, this);
    }

复制代码

这个时候在Activity的布局中引用的话,能看到这个loadingView的静态效果了。最后最关键的一步 3.动画效果实现: 这里面涉及到两个动画效果,一个是那个爱心上下跳动,以及底下一个阴影缩放 爱心上下跳动效果:

 private void logic() {
        ValueAnimator animator = ValueAnimator.ofInt(0,mJumpHeightPx,0);
        animator.setDuration(800);
        animator.setRepeatMode(ValueAnimator.RESTART);
        animator.setRepeatCount(ValueAnimator.INFINITE);
        animator.setInterpolator(new AccelerateDecelerateInterpolator());
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int value = (int) animation.getAnimatedValue();
                mIv.setTranslationY(-value);
                // 为了画shadow
                mMovePercent = value / 100f;
                postInvalidate();
            }
        });
        animator.start();
    }
复制代码

LoaingView构造函数中调用该方法(详细见githun项目源码) 实现思路:利用属性动画移动 关于属性动画作用的原理可以去百度几篇文章,一句话概括就是,属性动画提供的是:使用某种变化规则去得到一个不断变化值,然后自己利用这个值去设置控件的属性以达到动画的效果。

shadow缩放效果:

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 阴影宽高的一半   最大不超过16 / 8
        float shadowHalfWidth = Math.max(16f,(mIvRight - mIvLeft) / 2 );
        float shadowHalfHeight = Math.max(8f,(mIvBottom - mIvTop) / 2 );
        // 阴影区域中线位置(决定阴影所在位置) yCenter:垂直中线的纵坐标 xCenter:水平中线的横坐标
        float yCenter = mIvLeft + shadowHalfWidth;
        float xCenter = mIvTop + shadowHalfHeight * 2;
        // 缩放的变化量(决定阴影变化大小)
        float horizontalDiff = Math.max(2,(1f - mMovePercent) * shadowHalfWidth * mShadowFlatX);
        float verticalDiff = Math.max(2,(1f - mMovePercent) * shadowHalfHeight * mShadowFlatY);
        Log.d("bigname", "onDraw: " + yCenter + "-----" + xCenter + "------" + horizontalDiff + "--------" + verticalDiff + "-------" + mMovePercent);
        mShadowRectF.set(
                yCenter - horizontalDiff,
                xCenter - verticalDiff,
                yCenter + horizontalDiff,
                xCenter + verticalDiff
        );
        canvas.drawOval(mShadowRectF, mShadowPaint);
    }
复制代码

shadow利用画布去实现: 首先在使用属性动画的时候将变化的值赋给全局变量mMovePercent;并且变化的时候调用postInvalidate()重绘,这样的话在onDraw()方法中接口和mMovePercent就能知道当前动画进行的进度。依此来控制shadow缩放。

这个自定义LoadingView效果就已经实现了,接下来会对这个控件做些优化,增加更炫的动画效果,然后做好封装。

源码在上面的github链接

敬请期待---

你可能感兴趣的:(Android从零开始(第五篇)手把手教撸一个仿饿了么LoadingView(一))