Android自定义控件与动画的使用

控件是android开发过程中必不可少的部分,官方本身也给我们提供了许多的控件以供我们使用。但是有的时候已有控件并不能满足我们的需求,所以这个时候就需要我们自己来自定义控件。如果我们要学习自定义控件的话,我们需要去学习view的绘制过程这方面的知识,如果你需要为你的控件加上动画的话,你还需要学习android动画方面的知识,在这个过程中你可能还要学习一下android分发机制。有了这些基本的知识后,你就可以来自定义控件了。
下面我们就来实现一个简单的自定义控件CircleList,效果如下
这里写图片描述

上面控件主要的功能就是点击中间按钮,弹出几个子按钮,再次点击隐藏子按钮,在弹出和隐藏的过程中为子按钮添加旋转动画。
那么现在我们就来实现这个控件。

1.首先分析一下这个控件,它由数个CircleIamgeView组成(CircleImageView控件在网上可以下载,在这里不分析它的实现方式),其实它就好像是一个viewgroup,包含了数个circleImageView子控件,所以这个控件它就继承于viewgroup。

public class CircleList extends ViewGroup
{
   
    //实现它的多个构造函数
    public CircleList(Context context)
    {
        super(context);
    }

    public CircleList(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }

    public CircleList(Context context, AttributeSet attrs, int defStyleAttr)
    {
        super(context, attrs, defStyleAttr);
    }

    public CircleList(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
    {
        super(context, attrs, defStyleAttr, defStyleRes);
    }
    //重写它的layout方法
    @Override
    protected void onLayout(boolean b, int i, int i1, int i2, int i3)
    {

    }
}

上面是继承viewgroup后需要我们重写的一些方法,可以看到,除了四个构造函数外,还有onLayout这个方法需要我们来实现。

如果你了解view的绘制过程你应该知道,第一步我们需要对这个控件进行测量,也就是Measure.。

1.Measure
在自定义控件的时候,我们需要重写onMeasure方法来对控件进行一个测量。

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //从参数中得到高度和宽度的测量规格
        //获取宽度和高度的测量模式
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        //获取宽度和高度的大小
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        int width = widthSize;
        int height = heightSize;
        Log.e("init","ccc");
        switch (widthMode)
        {
            case MeasureSpec.UNSPECIFIED:
                width = widthSize;
                break;
            case MeasureSpec.EXACTLY:
                width = widthSize;
                break;
            case MeasureSpec.AT_MOST:
                //设置一个合适的值作为默认大小
                width = mSize;
                break;
        }
        switch (heightMode)
        {
            case MeasureSpec.UNSPECIFIED:
                height = heightSize;
                break;
            case MeasureSpec.EXACTLY:
                height = heightSize;
                break;
            case MeasureSpec.AT_MOST:
                height = mSize;
                break;
        }
        mWidth=width;
        mHeight=height;
        //设置测量后该控件的大小
        setMeasuredDimension(width,height);
        Log.e("draw",width+","+height+"");
        //因为我们需要一个正方形的布局,所以对高度和宽度进行判断,选择小的作为布局的依据
        MinSize = width > height ? height : width;
        this.pading = MinSize/10;
        //测量子view
        measureChildren(width,height);
    }

由上面代码可以看的,onMeasure这个方法中有widthMeasureSpec,heightMeasureSpec这两个参数,这两个int型参数就是你用来测量当前view的依据。
MeasureSpec参数是一个32位的Int类型数据。最高的两位代表了SpecMode(测量模式),后面的低30位代表了SpecSize(规格大小)。SpecMode有三个值,分别是UNSPECIFIED、EXACTLY、AT_MOST。
UNSPECIFIED:不指定测量模式,子视图可以是任意尺寸。
EXACTLY:精确测量模式。当设置具体数值或match_parent时生效。
AT_MOST:最大值模式,当设置为wrap_content时生效。

所以我们通过MeasureSpec.getMode与MeasureSpec.getSize这两个方法将宽与高的测量模式和规格大小提取出来。对测量模式进行一个判断。如果是AT_MOST(也就是设置了wrap_content)模式的话,则设置一个合适的大小,防止控件不显示。如果为其他两种模式的话就将得到的规格大小作为最终测量的结果。调用setMeasuredDimension(width,height)方法设置好最终了控件大小。因为当前控件继承的是viewgroup所以我们还需要将当前view测量好的规格大小,通过 measureChildren(width,height)传递个给子view,让子view也进行一个测量。

在子view测量之前,你可能会有一个疑问,就是我们并没有给这个viewGroup添加子view啊,其实我们在构造函数中需要进行一个初始化,为当前控件添加它的子view。

private void init(Context context,AttributeSet attr)
    {
        //得到xml中设置的自定义的属性(具体用法,下面会讲)
        TypedArray typedArray = context.obtainStyledAttributes(attr,R.styleable.CircleList);
        //按钮的总个数
        this.mNum = typedArray.getInt(R.styleable.CircleList_button_num,5);
        //是否展开四周的的按钮
        this.Isshow = typedArray.getBoolean(R.styleable.CircleList_is_show,false);
        //初始化所有的按钮
        this.mButtons = new CircleImageView[mNum];
        //初始化坐标点集合,分别代表按钮当前的位置坐标、按钮隐藏时所在坐标、按钮显示时所在坐标。
        this.mPoints = new Point[mNum];
        this.mHidePoints = new Point[mNum];
        this.mShowPoints = new Point[mNum];
        //初始化一个Image数组,用于给按钮添加背景,如果不自己设置背景的话则用下面的Image作为背景,也可以自己设置
        int[] buttonImage=new int[]{R.drawable.img1,R.drawable.img2,R.drawable.img3,R.drawable</
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值