• Android 用属性动画自定义view的渐变背景


    自定义view渐变背景,同时监听手势自动生成小圆球。

    宿主Activity如下:

    package com.edaixi.tempbak;
    
    import java.util.ArrayList;
    import android.animation.Animator;
    import android.animation.AnimatorListenerAdapter;
    import android.animation.AnimatorSet;
    import android.animation.ArgbEvaluator;
    import android.animation.ObjectAnimator;
    import android.animation.ValueAnimator;
    import android.annotation.SuppressLint;
    import android.app.Activity;
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Paint;
    import android.graphics.RadialGradient;
    import android.graphics.Shader;
    import android.graphics.drawable.ShapeDrawable;
    import android.graphics.drawable.shapes.OvalShape;
    import android.os.Bundle;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.Window;
    import android.view.animation.AccelerateInterpolator;
    import android.view.animation.DecelerateInterpolator;
    import android.widget.LinearLayout;
    
    @SuppressLint("NewApi")
    public class MainActivity extends Activity {
    
    	/** Called when the activity is first created. */
    	@Override
    	public void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		requestWindowFeature(Window.FEATURE_NO_TITLE);
    		setContentView(R.layout.activity_main);
    		LinearLayout container = (LinearLayout) findViewById(R.id.container);
    		container.addView(new MyAnimationView(this));
    	}
    
    	public class MyAnimationView extends View {
    
    		private static final int RED = 0xffFF8080;
    		private static final int BLUE = 0xff8080FF;
    		private static final int CYAN = 0xff80ffff;
    		private static final int GREEN = 0xff80ff80;
    
    		public final ArrayList<ShapeHolder> balls = new ArrayList<ShapeHolder>();
    		AnimatorSet animation = null;
    
    		public MyAnimationView(Context context) {
    			super(context);
    			/**************************************************************************************************
    			 * 
    			 * 设置自定义view的背景,是一个渐变的过程,用ValueAnimator实现,ValueAnimator是Property
    			 * Animation系统 的核心类,它包含了配置Property Animation属性的大部分方法,那要实现一个Property
    			 * Animation,都需要直接 或间接使用ValueAnimator类,使用ValueAnimator的步骤如下:
    			 * 1.调用ValueAnimation类中的ofInt(int...values)、ofFloat(String
    			 * propertyName,float...values)等静态方
    			 * 法实例化ValueAnimator对象,并设置目标属性的属性名、初始值或结束值等值;
    			 * 2.调用addUpdateListener(AnimatorUpdateListener
    			 * mListener)方法为ValueAnimator对象设置属性变化的监听器
    			 * 3.创建自定义的Interpolator,调用setInterpolator(TimeInterpolator
    			 * value)为ValueAniamtor设置自定义的 Interpolator;(可选,不设置默认为缺省值)
    			 * 4.创建自定义的TypeEvaluator,调用setEvaluator(TypeEvaluator
    			 * value)为ValueAnimator设置自定义的 TypeEvaluator;(可选,不设置默认为缺省值)
    			 * 5.在AnimatorUpdateListener 中的实现方法为目标对象的属性设置计算好的属性值。
    			 * 6.设置动画的持续时间、是否重复及重复次数等属性; 7.为ValueAnimator设置目标对象并开始执行动画。
    			 * 
    			 * *****************************************************************
    			 */
    			ValueAnimator colorAnim = ObjectAnimator.ofInt(this,
    					"backgroundColor", RED, BLUE);
    			colorAnim.setDuration(3000);
    			colorAnim.setEvaluator(new ArgbEvaluator());
    			colorAnim.setRepeatCount(ValueAnimator.INFINITE);
    			colorAnim.setRepeatMode(ValueAnimator.REVERSE);
    			colorAnim.start();
    		}
    
    		@SuppressLint("NewApi")
    		@Override
    		public boolean onTouchEvent(MotionEvent event) {
    			if (event.getAction() != MotionEvent.ACTION_DOWN
    					&& event.getAction() != MotionEvent.ACTION_MOVE) {
    				return false;
    			}
    			ShapeHolder newBall = addBall(event.getX(), event.getY());
    
    			/** Bouncing animation with squash and stretch **/
    			float startY = newBall.getY();
    			float endY = getHeight() - 50f;
    			float h = (float) getHeight();
    			float eventY = event.getY();
    			int duration = (int) (500 * ((h - eventY) / h));
    			ValueAnimator bounceAnim = ObjectAnimator.ofFloat(newBall, "y",
    					startY, endY);
    			bounceAnim.setDuration(duration);
    			bounceAnim.setInterpolator(new AccelerateInterpolator());
    			ValueAnimator squashAnim1 = ObjectAnimator.ofFloat(newBall, "x",
    					newBall.getX(), newBall.getX() - 25f);
    			squashAnim1.setDuration(duration / 4);
    			squashAnim1.setRepeatCount(1);
    			squashAnim1.setRepeatMode(ValueAnimator.REVERSE);
    			squashAnim1.setInterpolator(new DecelerateInterpolator());
    			ValueAnimator squashAnim2 = ObjectAnimator.ofFloat(newBall,
    					"width", newBall.getWidth(), newBall.getWidth() + 50);
    			squashAnim2.setDuration(duration / 4);
    			squashAnim2.setRepeatCount(1);
    			squashAnim2.setRepeatMode(ValueAnimator.REVERSE);
    			squashAnim2.setInterpolator(new DecelerateInterpolator());
    			ValueAnimator stretchAnim1 = ObjectAnimator.ofFloat(newBall, "y",
    					endY, endY + 25f);
    			stretchAnim1.setDuration(duration / 4);
    			stretchAnim1.setRepeatCount(1);
    			stretchAnim1.setInterpolator(new DecelerateInterpolator());
    			stretchAnim1.setRepeatMode(ValueAnimator.REVERSE);
    			ValueAnimator stretchAnim2 = ObjectAnimator.ofFloat(newBall,
    					"height", newBall.getHeight(), newBall.getHeight() - 25);
    			stretchAnim2.setDuration(duration / 4);
    			stretchAnim2.setRepeatCount(1);
    			stretchAnim2.setInterpolator(new DecelerateInterpolator());
    			stretchAnim2.setRepeatMode(ValueAnimator.REVERSE);
    			ValueAnimator bounceBackAnim = ObjectAnimator.ofFloat(newBall, "y",
    					endY, startY);
    			bounceBackAnim.setDuration(duration);
    			bounceBackAnim.setInterpolator(new DecelerateInterpolator());
    			// Sequence the down/squash&stretch/up animations
    			AnimatorSet bouncer = new AnimatorSet();
    			bouncer.play(bounceAnim).before(squashAnim1);
    			bouncer.play(squashAnim1).with(squashAnim2);
    			bouncer.play(squashAnim1).with(stretchAnim1);
    			bouncer.play(squashAnim1).with(stretchAnim2);
    			bouncer.play(bounceBackAnim).after(stretchAnim2);
    
    			// Fading animation - remove the ball when the animation is done
    			ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha",
    					1f, 0f);
    			fadeAnim.setDuration(250);
    			fadeAnim.addListener(new AnimatorListenerAdapter() {
    				@Override
    				public void onAnimationEnd(Animator animation) {
    					balls.remove(((ObjectAnimator) animation).getTarget());
    
    				}
    			});
    
    			// Sequence the two animations to play one after the other
    			AnimatorSet animatorSet = new AnimatorSet();
    			animatorSet.play(bouncer).before(fadeAnim);
    
    			// Start the animation
    			animatorSet.start();
    
    			return true;
    		}
    
    		private ShapeHolder addBall(float x, float y) {
    			OvalShape circle = new OvalShape();
    			circle.resize(50f, 50f);
    			ShapeDrawable drawable = new ShapeDrawable(circle);
    			ShapeHolder shapeHolder = new ShapeHolder(drawable);
    			shapeHolder.setX(x - 25f);
    			shapeHolder.setY(y - 25f);
    			int red = (int) (Math.random() * 255);
    			int green = (int) (Math.random() * 255);
    			int blue = (int) (Math.random() * 255);
    			int color = 0xff000000 | red << 16 | green << 8 | blue;
    			Paint paint = drawable.getPaint(); // new
    												// Paint(Paint.ANTI_ALIAS_FLAG);
    			int darkColor = 0xff000000 | red / 4 << 16 | green / 4 << 8 | blue
    					/ 4;
    			RadialGradient gradient = new RadialGradient(37.5f, 12.5f, 50f,
    					color, darkColor, Shader.TileMode.CLAMP);
    			paint.setShader(gradient);
    			shapeHolder.setPaint(paint);
    			balls.add(shapeHolder);
    			return shapeHolder;
    		}
    
    		@Override
    		protected void onDraw(Canvas canvas) {
    			for (int i = 0; i < balls.size(); ++i) {
    				ShapeHolder shapeHolder = balls.get(i);
    				canvas.save();
    				canvas.translate(shapeHolder.getX(), shapeHolder.getY());
    				shapeHolder.getShape().draw(canvas);
    				canvas.restore();
    			}
    		}
    	}
    
    }
    

      

    自定义

    ShapeHolder 

    如下:

    /*
     * Copyright (C) 2010 The Android Open Source Project
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package com.edaixi.tempbak;
    
    import android.graphics.Paint;
    import android.graphics.RadialGradient;
    import android.graphics.drawable.ShapeDrawable;
    import android.graphics.drawable.shapes.Shape;
    
    /**
     * A data structure that holds a Shape and various properties that can be used to define
     * how the shape is drawn.
     */
    public class ShapeHolder {
        private float x = 0, y = 0;
        private ShapeDrawable shape;
        private int color;
        private RadialGradient gradient;
        private float alpha = 1f;
        private Paint paint;
    
        public void setPaint(Paint value) {
            paint = value;
        }
        public Paint getPaint() {
            return paint;
        }
    
        public void setX(float value) {
            x = value;
        }
        public float getX() {
            return x;
        }
        public void setY(float value) {
            y = value;
        }
        public float getY() {
            return y;
        }
        public void setShape(ShapeDrawable value) {
            shape = value;
        }
        public ShapeDrawable getShape() {
            return shape;
        }
        public int getColor() {
            return color;
        }
        public void setColor(int value) {
            shape.getPaint().setColor(value);
            color = value;
        }
        public void setGradient(RadialGradient value) {
            gradient = value;
        }
        public RadialGradient getGradient() {
            return gradient;
        }
    
        public void setAlpha(float alpha) {
            this.alpha = alpha;
            shape.setAlpha((int)((alpha * 255f) + .5f));
        }
    
        public float getWidth() {
            return shape.getShape().getWidth();
        }
        public void setWidth(float width) {
            Shape s = shape.getShape();
            s.resize(width, s.getHeight());
        }
    
        public float getHeight() {
            return shape.getShape().getHeight();
        }
        public void setHeight(float height) {
            Shape s = shape.getShape();
            s.resize(s.getWidth(), height);
        }
    
        public ShapeHolder(ShapeDrawable s) {
            shape = s;
        }
    }
    

      

    自定义Layout布局渐变背景如下:

    package com.edaixi.tempbak;
    
    import android.animation.ArgbEvaluator;
    import android.animation.ObjectAnimator;
    import android.animation.ValueAnimator;
    import android.annotation.SuppressLint;
    import android.content.Context;
    import android.util.AttributeSet;
    import android.widget.RelativeLayout;
    
    @SuppressLint("NewApi")
    public class CustomerRelativeLayout extends RelativeLayout {
    	private static final int RED = 0xffFF8080;
    	private static final int BLUE = 0xff8080FF;
    
    	public CustomerRelativeLayout(Context context) {
    		super(context);
    		setBg();
    	}
    
    	public CustomerRelativeLayout(Context context, AttributeSet attrs,
    			int defStyleAttr, int defStyleRes) {
    		super(context, attrs, defStyleAttr, defStyleRes);
    		setBg();
    	}
    
    	public CustomerRelativeLayout(Context context, AttributeSet attrs,
    			int defStyleAttr) {
    		super(context, attrs, defStyleAttr);
    		setBg();
    	}
    
    	public CustomerRelativeLayout(Context context, AttributeSet attrs) {
    		super(context, attrs);
    		setBg();
    	}
    
    	public void setBg() {
    		ValueAnimator colorAnim = ObjectAnimator.ofInt(this, "backgroundColor",
    				RED, BLUE);
    		colorAnim.setDuration(3000);
    		colorAnim.setEvaluator(new ArgbEvaluator());
    		colorAnim.setRepeatCount(ValueAnimator.INFINITE);
    		colorAnim.setRepeatMode(ValueAnimator.REVERSE);
    		colorAnim.start();
    	}
    }
    

      

    布局中引用即可“

    <?xml version="1.0" encoding="utf-8"?>
    <com.edaixi.tempbak.CustomerRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/rl_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >
    
    </com.edaixi.tempbak.CustomerRelativeLayout>
    

      

  • 相关阅读:
    [C++] Const Summary (mind map)
    [C++] Operator Overload
    [C++] Deep copy ,Shallow copy, copy constructor,"="
    [C++] CONST 2
    [C++] * Basic and Class
    《Javascript权威指南-第6版》
    Bootstrap源码分析系列之初始化和依赖项
    Bootstrap源码分析系列之整体架构
    CSS模糊效果
    韩顺平php从入门到精通
  • 原文地址:https://www.cnblogs.com/spring87/p/4496930.html
Copyright © 2020-2023  润新知