jQuery鼠标指针特效

属性动画实现-LoadingView

ShapeLoadingView

阴影布局--shadow_view.xml

<?xml version="1.0" encoding="utf-8"?>
<!--底部阴影部分-->
<shape  xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <solid android:color="#11000000"/>
</shape>

阴影布局--loading_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="match_parent">

    <com.android.myapplication.demo7.MulShapeView
        android:id="@+id/shape"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_marginBottom="50dp"
        android:layout_centerInParent="true"
        android:layout_above="@+id/image_shadow"
        />

    <ImageView
        android:id="@+id/image_shadow"
        android:layout_width="50dp"
        android:layout_height="4dp"
        android:layout_centerInParent="true"
        android:layout_margin="15dp"
        android:src="@drawable/shadow_view" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/image_shadow"
        android:layout_centerInParent="true"
        android:layout_marginTop="5dp"
        android:text="loading..." />


</RelativeLayout>

MulShapeView.java--多形状View

package com.android.myapplication.demo7;


import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.View;


import androidx.annotation.Nullable;

public class MulShapeView extends View {
    private int mCurrentShape = ShapeType.CIRCLE;
    private Paint circlePaint, rectPaint, trianglePaint;
    private Path mPath;//画三角形所需

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

    public MulShapeView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MulShapeView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //init
        circlePaint = initPaint(Color.RED);
        rectPaint = initPaint(Color.MAGENTA);
        trianglePaint = initPaint(Color.YELLOW);

    }

    private Paint initPaint(int color) {
        Paint p = new Paint();
        p.setAntiAlias(true);
        p.setDither(true);
        p.setColor(color);
        p.setStyle(Paint.Style.FILL);//默认
        return p;
    }

    public interface ShapeType {
        int CIRCLE = 0;
        int RECT = 1;
        int TRIANGLE = 2;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        setMeasuredDimension(Math.min(width, height), Math.min(width, height));//正方形
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        switch (mCurrentShape) {
            case ShapeType.CIRCLE:
                int center = getWidth() / 2;//半径
                canvas.drawCircle(center, center, center, circlePaint);
                break;
            case ShapeType.RECT:
                int centerX = getWidth();
                int centerY = getHeight();
                canvas.drawRect(0, 0, centerX, centerY, rectPaint);
                break;
            case ShapeType.TRIANGLE:
                // 画三角  Path 画路线
                if (mPath == null) {
                    mPath = new Path();
                    mPath.moveTo(getWidth() >> 1, 0);
                    //勾股定理
                    mPath.lineTo(0, (float) (Math.sqrt(3) * getWidth() / 2));
                    mPath.lineTo(getWidth(), ((float) Math.sqrt(3) * getWidth() / 2));
                    mPath.close();//直接连接到起点
                }
                canvas.drawPath(mPath, trianglePaint);
                break;
        }
    }

    public void exchange(){
        switch (mCurrentShape){
            case ShapeType.CIRCLE:
                mCurrentShape =  ShapeType.RECT;
                break;
            case ShapeType.RECT:
                mCurrentShape = ShapeType.TRIANGLE;
                break;
            case ShapeType.TRIANGLE:
                mCurrentShape = ShapeType.CIRCLE ;
                break;
        }
        //重新绘制形状
        invalidate();
    }

    public int getCurrentShape(){
        return mCurrentShape;
    }
}

ShapeLoadingView.java--loading

package com.android.myapplication.demo7;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.widget.ImageView;
import android.widget.RelativeLayout;

import com.android.myapplication.R;

import androidx.annotation.Nullable;

/**
 * @author
 * https://blog.csdn.net/u011109881/article/details/112167257
 * https://github.com/caihuijian/learn_darren_android
 */

public class ShapeLoadingView extends RelativeLayout {
    private static final int ANIMATOR_TIME = 1000;
    private MulShapeView mMulShapeView;//变形imageView
    private ImageView mShadowView;// 阴影View
    private int mShapeTransactionY;//MulShapeView的margin_bottom (底边距)

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

    public ShapeLoadingView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ShapeLoadingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //inflate(context, R.layout.loading_layout, this);
        //添加布局
        LayoutInflater layoutInflater = LayoutInflater.from(context);
        layoutInflater.inflate(R.layout.loading_layout, this);

        //init
        mMulShapeView = findViewById(R.id.shape);
        mShadowView = findViewById(R.id.image_shadow);
        mShapeTransactionY = ((MarginLayoutParams) mMulShapeView.getLayoutParams()).bottomMargin;

        //post
        post(new Runnable() {
            @Override
            public void run() {
                // onResume 之后View绘制流程执行完毕之后
                fullDownAnimate();
            }
        });
        // onCreate() 方法中执行 ,布局文件解析 反射创建实例

    }

    private void jumpUPAnimate(){
        //垂直上抛
        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mMulShapeView, "translationY", mShapeTransactionY ,0);

        //插值器  减速
        DecelerateInterpolator interpolator = new DecelerateInterpolator();

        //细节
        float rotateAngle = -180;
        switch (mMulShapeView.getCurrentShape()){
            case MulShapeView.ShapeType.RECT:
                rotateAngle = -180;
                break;
            case MulShapeView.ShapeType.TRIANGLE:
                rotateAngle = -270;
                break;
        }

        ObjectAnimator shapeRotateAnimate = ObjectAnimator.ofFloat(mMulShapeView, "rotation", rotateAngle);
        //阴影 从原有宽度从0.3还原
        ObjectAnimator shadowScaleAnimate = ObjectAnimator.ofFloat(mShadowView, "scaleX", 0.3f,1 );

        // 将单个动画做成组合
        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.setDuration(ANIMATOR_TIME);
        animatorSet.setInterpolator(interpolator);
        animatorSet.playTogether(objectAnimator,shapeRotateAnimate,shadowScaleAnimate);//组合动画
        animatorSet.start();

        //监听器
        animatorSet.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                //上抛到最顶点下落
                fullDownAnimate();
            }
        });


    }

    private void fullDownAnimate(){
        //下落
        //mShapeTransactionY  原始位置
        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mMulShapeView, "translationY", 0, mShapeTransactionY);

        //插值器 加速下落
        AccelerateInterpolator interpolator = new AccelerateInterpolator();



        //细节
        float rotateAngle = 0;
        switch (mMulShapeView.getCurrentShape()){
            case MulShapeView.ShapeType.RECT:
                rotateAngle = 180;
                break;
            case MulShapeView.ShapeType.TRIANGLE:
                rotateAngle = 270;
                break;
        }

        ObjectAnimator shapeRotateAnimate = ObjectAnimator.ofFloat(mMulShapeView, "rotation", rotateAngle);
        //阴影 从原有宽度缩短到0.3
        ObjectAnimator shadowScaleAnimate = ObjectAnimator.ofFloat(mShadowView, "scaleX", 1, 0.3f);

        // 将单个动画做成组合
        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.setDuration(ANIMATOR_TIME);
        animatorSet.setInterpolator(interpolator);
        animatorSet.playTogether(objectAnimator,shapeRotateAnimate,shadowScaleAnimate);//组合动画
        animatorSet.start();

        //监听器
        animatorSet.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                //下落中改变图形
                mMulShapeView.exchange();
                //下落完成上抛
                jumpUPAnimate();
            }
        });

    }

    //加载完毕调用 释放动画资源
    public void loadComplete() {
        mMulShapeView.clearAnimation();
        mShadowView.clearAnimation();
        // 把LoadingView从父布局移除
        ViewGroup parent = (ViewGroup) getParent();
        if (parent != null) {
            parent.removeView(this);// 从父布局移除
            removeAllViews();// 移除自己所有的View
        }
    }

    /**
     * 采用代码的方式添加
     *
     * @param parent
     * @return
     */
    public static ShapeLoadingView attach(ViewGroup parent) {
        ShapeLoadingView loadingView = new ShapeLoadingView(parent.getContext());
        loadingView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        parent.addView(loadingView);
        return loadingView;
    }

    /**
     * 优化性能
     * @param visibility 隐藏
     */
    @Override
    public void setVisibility(int visibility) {
        super.setVisibility(View.INVISIBLE);
        ViewGroup parent = (ViewGroup) this.getParent();
        if(parent != null){
            parent.removeView(this);
            mMulShapeView.clearAnimation();
            mShadowView.clearAnimation();
            this.removeAllViews();
        }
    }


    //dip to px
    private int dip2px(int dip) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, getResources().getDisplayMetrics());
    }

}

//使用
 mShapeLoadingView = findViewById(R.id.loading);
        mShapeLoadingView.postDelayed(new Runnable() {
            @Override
            public void run() {
                mShapeLoadingView.loadComplete();
            }
        }, 3000);
posted @ 2022-01-13 20:30  僵小七  阅读(54)  评论(0编辑  收藏  举报