雅虎过度效果

来源:互联网 发布:台湾大学知乎 编辑:程序博客网 时间:2024/05/22 11:58

这是我以前在做雅虎界面效果的代码,废话不多说,直接上代码:

1、主界面:(没有xml布局,都是通过代码实现):

public class MainActivity extends Activity {    private SplashView mSplashView;    private FrameLayout mMainView;    private Handler mHandler = new Handler();    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        //先放动画加载界面        mMainView = new FrameLayout(getApplicationContext());//帧布局        mSplashView = new SplashView(getApplicationContext());//自定义动画view        mMainView.addView(mSplashView);        setContentView(mMainView);        //模拟后台加载数据        startLoadingData();    }    /** 延迟3s */    private void startLoadingData() {        //开线程        mHandler.postDelayed(                new Runnable() {                    @Override                    public void run() {                        // 加载完毕---                        onLoadingDataEnd();                    }                },                3000);//延迟时间    }    /** 执行其余动画 */    protected void onLoadingDataEnd() {        //开始其他的动画---第二部分的动画        //注意:动画界面已经提前在了,并且动画对象在执行时不会被覆盖掉,只有执行完了才被主界面覆盖        mSplashView.splashAndDisapper();        //再放显示布局界面        ContentView mContentView = new ContentView(this);//ImageView        mMainView.addView(mContentView,0);//位置为0,同动画位置,直接覆盖动画界面    }}

2、 ImageView类(相当于new ImageView(this))

public class ContentView extends ImageView {    public ContentView(Context context) {        super(context);        //设置了一张图片        setImageResource(R.drawable.content);    }}

3、继承View的主要动画实现类

/** * 自定义view *  * @author weica  * 说明:  * 1.先在构造函数中执行第一次旋转动画 * 2.然后再主线程的定时器方法完成后,调用第二个6圆缩放动画, * 以此类推,到中心圆缩放动画,到扩散动画,最后显示主界面 *  */public class SplashView extends View {    /** some adjustable parameters **/    // 大圆(里面包含很多小圆的)的半径    private float mRotationRadius = 90;    // 每一个小圆的半径    private float mCircleRadius = 18;    // 小圆圈的颜色列表,在initialize方法里面初始化    private int[] mCircleColors;    // 大圆和小圆旋转的时间    private long mRotationDuration = 1200; // ms    // 第二部分动画的执行总时间(包括三个动画时间,各占1/3)    private long mSplashDuration = 1200; // ms    // 整体的背景颜色    private int mSplashBgColor = Color.WHITE;    /**     * 参数,保存了一些绘制状态,会被动态地改变*     */    // 空心圆初始半径    private float mHoleRadius = 0F;    // 当前大圆旋转角度(弧度)    private float mCurrentRotationAngle = 0F;    // 当前大圆的半径    private float mCurrentRotationRadius;    // 当前单圆的半径    private float mCurrentSingleCircleRadius;    // 保存当前动画状态--当前在执行哪种动画    private SplashState mState = null;    // 绘制圆的画笔    private Paint mPaint = new Paint();    // 绘制背景的画笔    private Paint mPaintBackground = new Paint();    // 屏幕正中心点坐标    private float mCenterX;    private float mCenterY;    // 屏幕对角线一半    private float mDiagonalDist;    //控件的宽高可以从这个方法中取    @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        mCenterX = w / 2f;        mCenterY = h / 2f;        mDiagonalDist = (float) (Math.sqrt(w * w + h * h) / 2);    }    /**     * 构造方法     *      * @param context     */    public SplashView(Context context) {        super(context);        // 初始化        initialize(context);    }    private void initialize(Context context) {        // 色值数组        mCircleColors = context.getResources().getIntArray(                R.array.splash_circle_colors);        // 给SplashView设置一个默认的背景--透明        // setBackgroundColor(Color.TRANSPARENT);        // 设置画笔        // 消除锯齿        mPaint.setAntiAlias(true);        mPaintBackground.setAntiAlias(true);        // STROKE描边,空心效果        mPaintBackground.setStyle(Paint.Style.STROKE);        // 设置默认背景颜色颜色(背景画笔设置默认设置,Color.WHITE)        mPaintBackground.setColor(mSplashBgColor);    }    /**     * 定义一个抽象类--动画状态类 作用:让几个动画状态类开始执行后都开始绘制各自的界面--invalidate--》onDraw()     * 通过onDraw方法统一控制调用drawstate方法来绘制界面     *      */    private abstract class SplashState {// 接收对象---》mState        public abstract void drawState(Canvas canvas);    }    // 每次界面刷新都会调用的--绘制    @Override    protected void onDraw(Canvas canvas) {        // canvas画布,paint画笔        // super.onDraw(canvas);        if (mState == null) {            // 第一次执行的动画            handleFirstDraw();        }        // 分发到各个动画状态类---绘制各自的图像        mState.drawState(canvas);    }    /** 第一次执行的动画,设置默认执行的动画对象 */    private void handleFirstDraw() {        //默认执行一次第一个旋转动画,给mState赋值        mState = new RotationState();        // 第一次执行动画,需要出示一些默认参数        // 大圆当前旋转角度        mCurrentRotationAngle = 0f;        // 设置默认的空心圆的半径        mHoleRadius = 0f;        // 默认设置当前大圆的半径        mCurrentRotationRadius = mRotationRadius;        // 默认设置当前单圆半径        mCurrentSingleCircleRadius = mCircleRadius;    }    /**     * 定义第一个动画---旋转动画 大圆( 包含了6个小圆) (继承抽象类的子类,其中把drawState方法写好,等待onDraw调用方法)     */    private class RotationState extends SplashState {        private ValueAnimator mAnimator;// 属性动画        /** 构造方法 */        public RotationState() {            // 圆心角弧度变化 0到360            mAnimator = ValueAnimator.ofFloat(0, (float) (Math.PI * 2));            mAnimator.setDuration(mRotationDuration);// 设置默认的旋转时间 1200ms            // 使用线性插值器LinearInterpolator可以让动画平滑地执行            mAnimator.setInterpolator(new LinearInterpolator());            // 设置监听            mAnimator.addUpdateListener(new AnimatorUpdateListener() {                @Override                public void onAnimationUpdate(ValueAnimator animation) {                    // 当前大圆旋转角度(弧度)                    mCurrentRotationAngle = (Float) animation                            .getAnimatedValue();                    // 刷新界面,重新绘制界面--onDraw                    invalidate();                }            });            // 重复次数为无穷            mAnimator.setRepeatCount(ValueAnimator.INFINITE);            // 设置让他不断地旋转 --循环            mAnimator.setRepeatMode(ValueAnimator.RESTART);            // 开始执行            mAnimator.start();        }        @Override        public void drawState(Canvas canvas) {            // 绘制界面--根据旋转情况来绘制界面---坐标!时间!            // 绘制背景            drawBackground(canvas);            // 绘制里面的小圆            drawCircles(canvas);        }        public void cancel() {            mAnimator.cancel();        }    }    /** 绘制大圆背景 */    public void drawBackground(Canvas canvas) {        // 绘制splashview的背景        if (mHoleRadius > 0f) {            /**             * 绘制空心圆的技巧             */            float strokeWidth = mDiagonalDist - mHoleRadius;// 屏幕对角线一半 空心圆初始半径0F            float circleRadius = mHoleRadius + strokeWidth / 2;// 空心圆初始半径                                                                // 屏幕对角线一半的一半            // 绘制边框(width)--里面是空心的            mPaintBackground.setStrokeWidth(strokeWidth);            // 原点:屏幕中心点 半径:屏幕对角线一半的一半 背景画笔:mPaintBackground            canvas.drawCircle(mCenterX, mCenterY, circleRadius,                    mPaintBackground);        } else {            canvas.drawColor(mSplashBgColor);        }    }    /** 绘制里面的小圆 */    public void drawCircles(Canvas canvas) {        // 绘制小圆 --遍历6个小圆        int numCircles = mCircleColors.length;// 色值数组大小        // 小圆之间的间隔角度 360/6就是每个小圆的夹角大小        float rotationAngle = (float) (2 * Math.PI / numCircles);        for (int i = 0; i < numCircles; i++) {            // 得到某个小圆的坐标            // 每一个小圆的弧度 = 当前大圆整体旋转了多少度 + i*小圆之间的间隔角度            double angle = mCurrentRotationAngle + (i * rotationAngle);            // 下面计算小圆在弧度不断改变的情况下,圆心的坐标位置            double circleX = mCenterX + mCurrentRotationRadius                    * Math.cos(angle);            double circleY = mCenterY + mCurrentRotationRadius                    * Math.sin(angle);            // 设置颜色            mPaint.setColor(mCircleColors[i]);            // 根据小圆的坐标点绘制小圆            canvas.drawCircle((float) circleX, (float) circleY, mCircleRadius,                    mPaint);        }    }    /**     * 定义第二个动画---6个小圆聚合动画     */    private class MergingState extends SplashState {        public MergingState() {            // 聚合范围:0~大圆的半径 0~90            ValueAnimator animator = ValueAnimator.ofFloat(0, mRotationRadius);            animator.setDuration(mSplashDuration / 3);// 1200/3            // 设置监听            animator.addUpdateListener(new AnimatorUpdateListener() {                @Override                public void onAnimationUpdate(ValueAnimator animator) {                    // 当前大圆的旋转半径(当前半径对象,可变)                    mCurrentRotationRadius = (Float) animator                            .getAnimatedValue();                    invalidate();                }            });            // 设置监听--            animator.addListener(new AnimatorListenerAdapter() {                @Override                public void onAnimationEnd(Animator animation) {                    super.onAnimationEnd(animation);                    // 动画结束--进入下一个动画 3(中心圆再缩放一下)                    mState = new SingularityState();                    // mState = new ExpandingState();//动画4,扩散动画                }            });            // 插值器(Interpolator)弹射的效果,注意:缩放动画就是因为这个属性会先变大一下再缩小            animator.setInterpolator(new OvershootInterpolator(6f));            // 保持动画执行后的状态            animator.reverse();        }        @Override        public void drawState(Canvas canvas) {            // 绘制界面--根据旋转情况来绘制界面---坐标!时间!            // 背景绘制            drawBackground(canvas);            // 处理小圆            drawCircles(canvas);        }    }    /**     * 定义第三个动画---(为了更加美观,最好处理一下缩放后,中心点的圆再进行缩放) 中心点位置单独的圆的缩放动画效果     */    private class SingularityState extends SplashState {        public SingularityState() {            // 0~单圆的半径 0~18            ValueAnimator animator = ValueAnimator.ofFloat(0, mCircleRadius);            animator.setDuration(mSplashDuration / 3);            animator.setInterpolator(new OvershootInterpolator(6f));            animator.addUpdateListener(new AnimatorUpdateListener() {                @Override                public void onAnimationUpdate(ValueAnimator animation) {                    // 单圆的半径                    mCurrentSingleCircleRadius = (Float) animation                            .getAnimatedValue();                    invalidate();                }            });            // 监听            animator.addListener(new AnimatorListenerAdapter() {                @Override                public void onAnimationEnd(Animator animation) {                    super.onAnimationEnd(animation);                    // 执行下一个动画,动画4,扩散动画                    mState = new ExpandingState();                }            });            animator.reverse();        }        @Override        public void drawState(Canvas canvas) {            // 绘制界面--根据旋转情况来绘制界面---坐标!时间!            drawBackground(canvas);            // 画单圆            drawSingleCircle(canvas);        }    }    /**     * 定义第四个动画--- 空心圆动画     */    private class ExpandingState extends SplashState {        public ExpandingState() {            ValueAnimator animator = ValueAnimator.ofFloat(0, mDiagonalDist);            // 减速效果            animator.setInterpolator(new DecelerateInterpolator());            animator.addUpdateListener(new AnimatorUpdateListener() {                @Override                public void onAnimationUpdate(ValueAnimator animation) {                    mHoleRadius = (Float) animation.getAnimatedValue();                    invalidate();                }            });            animator.start();        }        @Override        public void drawState(Canvas canvas) {            // 绘制界面--根据旋转情况来绘制界面---坐标!时间!            drawBackground(canvas);        }    }    /**     * (暴露的方法,其余动画的入口)     * 执行第二部分的动画然后消失,显示contentview     */    public void splashAndDisapper() {        // mState不为null,并且是第一个动画实例        if (mState != null && mState instanceof RotationState) {            RotationState rs = (RotationState) mState;            rs.cancel();// 停止旋转动画            // 开始下一个动画(聚合动画)            // 开线程放到消息队列里面,为了不影响主UI线程的响应            post(new Runnable() {                @Override                public void run() {                    mState = new MergingState();                }            });        }    }    /** 画单圆 */    public void drawSingleCircle(Canvas canvas) {        mPaint.setColor(mCircleColors[1]);// 中心圆的背景颜色值        canvas.drawCircle(mCenterX, mCenterY, mCurrentSingleCircleRadius,                mPaint);    }}

以上就是全部代码,大家可以自个去试试,有什么问题可以留言。或者在微信公众号“技术帮团队”上找我们。

0 0
原创粉丝点击