Android实现带动画效果的自定义View

                

准备工作:

考虑这个自定义view需要什么属性来方便在xml布局里面改。

在values/attrs.xml里面添加自定义属性,分别是尺寸,颜色,变大的倍数。

 
<span style="font-size:14px;"><resources>
    <declare-styleable name="CustomView">
        <attr name="size" format="dimension" />
        <attr name="color" format="color" />
        <attr name="maxValue" format="float"/>
    </declare-styleable>
</resources></span>

format是定义的属性的类型,配置完成后,就可以在xml布局中使用这些属性了。

继承view之后,会有三个构造方法

<span style="font-size:14px;">public class CustomView extends View{

    private int DEFAULT_SIZE = 100;//默认半径
    private int DEFAULT_COLOR = Color.GREEN;//默认颜色
    private float DEFAULT_MAXVALUE = 1.6f;//默认放大倍数

    private int mSize;//半径
    private int mColor;
    private Paint mPaint;
    private int mHeight;
    private int mWidth;
    private Float value = 1f;
    private Float maxValue;//实际放大的倍数

    private ValueAnimator anim;

    public CustomView(Context context) {
        super(context);
    }

    public CustomView(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray typedArray = context.getTheme().obtainStyledAttributes(
                attrs,R.styleable.CustomView,0,0);
        mSize = typedArray.getDimensionPixelSize(R.styleable.CustomView_size,DEFAULT_SIZE);
        mColor = typedArray.getColor(R.styleable.CustomView_color,DEFAULT_COLOR);
        maxValue = typedArray.getFloat(R.styleable.CustomView_maxValue,DEFAULT_MAXVALUE);

        typedArray.recycle();
    }

    public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }</span>
第一个构造方法是在代码中创建view,
<span style="font-size:14px;"> CustomView view = new CustomView(this);</span>
第二个是我们常用的构造方法,给每个自定义属性设置个默认值,可以再布局中配置这些自定义属性。这些属性存放在第二个参数中。

第三个是需要指定style是调用。


然后开始自定义View。。。

主要会涉及三个方法,分别是onDraw(),onLayout(),onMeasure()。

1、onDraw():

      就是把要显示的view画出来,就是一个圆,很简单。

<span style="font-size:14px;">@Override
    protected void onDraw(Canvas canvas) {
        mPaint = new Paint();
        mPaint.setColor(mColor);
        mPaint.setAntiAlias(true);//抗锯齿效果
        //画圆,前两个参数确定圆心,第三个参数是半径
        canvas.drawCircle(mWidth/2,mHeight/2,mSize *value,mPaint);
    }</span>

2,、onLayout():

这个方法主要是确定当前view在父视图中的位置

@Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        // 重设圆半径,防止超出视图大小
        mHeight = getMeasuredHeight();
        mWidth = getMeasuredWidth();
        int maxSize = (int) Math.min(mHeight/(2 * maxValue),mWidth/(2 * maxValue));
        mSize = mSize > maxSize ? maxSize : mSize;
    }
我在这里重写这个方法是为了防止圆变大时,超出屏幕范围。其中maxSize是view可以有的最大半径,要考虑到圆变大时也不能超出屏幕,所以是mHeight / (2 * maxValue)。

其实没必要重写onLayout(),这里只是为了防止半径设置的过大。。

在这里重写onLayout()后,有个弊端,就是当在布局中宽高设置固定大小时,显示的圆的半径是所设置宽高的一半,例如宽高都

设置为20dp,所显示的半径为10dp。设置成wrap_content或者match_parent或者不重写onLayout()就没影响了。


3、onMeasure():

先提一句:onMeasure()方法不是每个自定义view都需要重写的。下面简单的了解一下onMeasure的用法。

在xml布局中,我们会设置wrap_content或者match_parent。

但是系统给我们测量得到的宽度和高度都是match_parent。

当我们用wrap_content时,需要的是实际宽度或高度,而不是系统测量得到的match_parent,就需要我们自己测量,即重写

onMeasure();这里的自定义view就不需要重写onMeasure(),因为这里所需要的宽高就是match_parent,我们只是通

过宽高得到中心点画圆即可。


4.view花完了,开始动画部分,使用ValueAnimator实现的。

public void startAnimation(){
        anim = ValueAnimator.ofFloat(value,maxValue);
        anim.setRepeatCount(ValueAnimator.INFINITE);//设置无限重复
        anim.setRepeatMode(ValueAnimator.REVERSE);//设置重复模式
        anim.setDuration(500);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                value = (Float) animation.getAnimatedValue();
                postInvalidate();
            }
        });

        anim.start();
    }

anim = ValueAnimator.ofFloat(value,maxValue);
得到ValueAnimator对象,其中两个参数代表从value到maxValue平滑变化。

在监听方法中,通过调用getAnimateValue()方法获取动画在播放过程中属性值的变化,也就是上面参数变化过程中的一系列值。

通过postInvalidate()实现刷新,在onDraw()方法中

<span style="font-size:14px;">canvas.drawCircle(mWidth/2,mHeight/2,mSize *value,mPaint);</span>

半径 = mSize * value,半径不断变化,实现了圆放大过程。

想要实现复杂的动画可以了解了解ValueAnimator和ObjectAnimator。


最后在Activity中启动动画和关闭动画

public class MainActivity extends AppCompatActivity {
    private CustomView customView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        customView = (CustomView) findViewById(R.id.custom_view);
        customView.startAnimation();
        
        //customView.endAnimation();
    }
}

Demo下载地址










  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值