【达内课程】自定义控件(奔跑的阿狸)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010356768/article/details/89462624

这一节要的效果如图
在这里插入图片描述
新建AnimationView

public class AnimationView extends View {
    Bitmap[] bitmapArray = new Bitmap[4];
    int currentIndex = 0;
    int viewWidth, viewHeight;
    int sleepTime = 1000;
    boolean isRunning = true;
    Thread thread;

    public AnimationView(Context context, AttributeSet attrs) {
        super(context, attrs);
        bitmapArray[0] = BitmapFactory.decodeResource(getResources(), R.mipmap.logo1);
        bitmapArray[1] = BitmapFactory.decodeResource(getResources(), R.mipmap.logo2);
        bitmapArray[2] = BitmapFactory.decodeResource(getResources(), R.mipmap.logo3);
        bitmapArray[3] = BitmapFactory.decodeResource(getResources(), R.mipmap.logo4);

        thread = new Thread(new MyRunnable());
        thread.start();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Rect rect = new Rect(0, 0, viewWidth, viewHeight);
        Paint paint = new Paint();
        paint.setColor(Color.CYAN);
        canvas.drawRect(rect, paint);

        Bitmap bitmap = bitmapArray[currentIndex];
        int imageX = (viewWidth - bitmap.getWidth()) / 2;
        int imageY = (viewHeight - bitmap.getHeight()) / 2;
        canvas.drawBitmap(bitmap, imageX, imageY, paint);
    }

    /////
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        viewWidth = w;
        viewHeight = h;
        super.onSizeChanged(w, h, oldw, oldh);
    }

    class MyRunnable implements Runnable {

        @Override
        public void run() {
            while (isRunning) {
                try {
                    currentIndex++;
                    if (currentIndex > (bitmapArray.length - 1)) {
                        currentIndex = 0;
                    }
                    //只能在主线程中调用invalidate()
                    //工作线程中调onDraw
                    postInvalidate();
                    Thread.currentThread().sleep(sleepTime);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

在布局中使用

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@mipmap/first_bg">

    <com.example.xx.allrun.widget.AnimationView
        android:id="@+id/animationView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

素材图片如下
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
增加自定义属性

res下增加attrs.xml,这里我们定义了2个属性,sleep_time用来控制休眠时间,是个浮点类型;images用来控制图片,是个引用类型

<resources>
    <declare-styleable name="AnimationView">
        <attr name="sleep_time" format="float"/>
        <attr name="images" format="reference"/>
    </declare-styleable>
</resources>

xml使用

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:AnimationView="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.xx.animationview.AnimationView
        android:id="@+id/animationView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        AnimationView:sleep_time="1000"/>

</LinearLayout>

这里用了我们刚才自定义的属性,就行android中自带的属性会有android:前缀,我们自定义的属性要想使用自定义的前缀,需要增加声明。例如,我们使用AnimationView:前缀,我们需要增加xmlns:AnimationView="http://schemas.android.com/apk/res-auto",这行代码

AnimationView的构造方法中可以拿到这些属性

    public AnimationView(Context context, AttributeSet attrs) {
        super(context, attrs);

        //读取自定义属性
        //attrs里放的是属性
        //数组里放的是sleep_time和images属性
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AnimationView);
        sleepTime = (int)typedArray.getFloat(R.styleable.AnimationView_sleep_time,0);

        ......
    }

现在我们来用属性控制图片

res下新建arrays.xml

<resources>
    <string-array name="animationImages">
        <item>@mipmap/logo1</item>
        <item>@mipmap/logo2</item>
        <item>@mipmap/logo3</item>
        <item>@mipmap/logo4</item>
    </string-array>
</resources>

xml中使用

    <com.xx.animationview.AnimationView
        android:id="@+id/animationView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        AnimationView:sleep_time="5000"
        AnimationView:images="@array/animationImages"/>

AnimationView构造方法中读取图片属性,之前存放图片的 Bitmap[] bitmapArray 指定了大小为4,这里去掉这个限制,设置其大小为图片的个数

public class AnimationView extends View {
    Bitmap[] bitmapArray;
    ......

    public AnimationView(Context context, AttributeSet attrs) {
        super(context, attrs);
		......
		
        //读取float和读取数组是不一样的
        Resources resources = context.getResources();
        TypedArray typedArrayImages = resources.obtainTypedArray(R.array.animationImages);

        int length = typedArrayImages.length();
        bitmapArray = new Bitmap[length];
        for(int i=0;i<length;i++){
            //从数组中读取图的Id
            //第二个参数是默认值
            int imageResId = typedArrayImages.getResourceId(i,0);
            //创建Bitmap
            Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),imageResId);
            bitmapArray[i] = bitmap;
        }

        ......
    }
}

设置控件宽高

现在控件是全屏的,现在设置控件大小为最大的图片宽高

扫描二维码关注公众号,回复: 6189712 查看本文章

布局中设置控件宽高为wrap_content

<com.xx.animationview.AnimationView
        android:id="@+id/animationView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        AnimationView:sleep_time="500"
        AnimationView:images="@array/animationImages"/>

AnimationView中定义最大宽高,然后重写onMeasure方法

public class AnimationView extends View {
    ......
    //图片最大宽高
    int imageMaxWidth,imageMaxHeight;

    public AnimationView(Context context, AttributeSet attrs) {
        super(context, attrs);
        ......
        for(int i=0;i<length;i++){
            //从数组中读取图的Id
            //第二个参数是默认值
            int imageResId = typedArrayImages.getResourceId(i,0);
            //创建Bitmap
            Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),imageResId);
            //得图的最大宽高
            if(bitmap.getWidth()>imageMaxWidth){
                imageMaxWidth = bitmap.getWidth();
            }
            if(bitmap.getHeight()>imageMaxHeight){
                imageMaxHeight = bitmap.getHeight();
            }
            bitmapArray[i] = bitmap;
        }

        thread = new Thread(new MyRunnable());
        thread.start();
    }

    //设置控件的大小
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(imageMaxWidth,imageMaxHeight);
    }
    ......
}

下载地址

https://download.csdn.net/download/u010356768/11151293

猜你喜欢

转载自blog.csdn.net/u010356768/article/details/89462624