照着“自定义控件其实很简单”博客来学自定义view(一)

在有了一定的自定义view的基础了后,我现在开始了再一次重新温故和学习自定义view的知识。
From AigeStudio(http://blog.csdn.net/aigestudio/article/details/41212583)Power by Aige
根据这篇文章起,开始重学一遍。
我要做的就是这个:圆圈是会动态变化半径的。

Paste_Image.png

首先的步骤是:
如图:
Paste_Image.png

1、写自定义控件,首先就是继承View或者子类ViewGroup甚至更子类,比如:TextView,Button或者其他的第三方自定义View。
2、继承了View后,就需要重写构造方法。
Paste_Image.png

构造方法有好几个。我们主要可以重写蓝色框的这两个。第二个是用于xml的。什么用呢?
先来看一下我在xml怎么调用这个AnimationCircleView自定义view。

Paste_Image.png

我们在xml文件引用我们的AnimationCircleView自定义view时为其指定了两个android自带的两个属性:layout_width和layout_height,当我们需要使用类似的属性(比如更多的什么id啊、padding啊、margin啊之类)时必须在自定义View的构造方法中添加一个AttributeSet类型的签名来解析这些属性。所以记住,要加重写方法哦!

然后,开始准备画画了。
要画画,首先当然是需要工具了。纸笔桌伺候嘛。
纸即Canvas,俗称画布。笔即Paint,俗称画笔。桌即为初始化准备。
纸是什么纸,白纸一张。所以不用初始化。笔呢,要求当然高了。要能画出花来,5毛钱的笔可不好画。要9.9的才行。所以需要初始化画笔。桌呢,没桌子不好画图耶。
那么开始:
先initView()准备好要画图需要的桌子。

Paste_Image.png

我需要Context 和屏幕的宽、高。
然后我要挑个好一点的笔,沾点墨水。
这么多选择可以挑。
Paste_Image.png

我们挑好了。
Paste_Image.png

开始画画喽,重写onDraw()方法
canvas有很多的画画模具哦,比如:
Paste_Image.png

我们画个圆环。drawCircle表示绘制的是圆形,但是由于我们的画笔样式设置为描边,其绘制出来的就是一个圆环!其中drawCircle的前两个参数表示圆心的XY坐标,这里我们用到了一个工具类获取屏幕尺寸以便将其圆心设置在屏幕中心位置,第三个参数是圆的半径,第四个参数则为我们的画笔!
注意:
在Android中设置数字类型的参数时如果没有特别的说明,参数的单位一般都为px像素。
Paste_Image.png

好了。画完了。现在要让他动起来,怎么动。一种方式就是通过线程去不断的重绘。
线程的话,我们通过自定义view来继承接口Runnable。重写run()方法。


Paste_Image.png

而重绘呢?这时就有2个方法了。invalidate()、postInvalidate()。
invalidate()、postInvalidate(): 调用invalidate()、postInvalidate()会 界面刷新,执行 draw 过程。区别就是Invalidate不能直接在线程中调用,因为他是违背了单线程模型:Android UI操作并不是线程安全的,并且这些操作必须在UI线程中调用。 鉴于此,如果要使用invalidate的刷新,那我们就得配合handler的使用,使异步非ui线程转到ui线程中调用,如果要在非ui线程中直接使用就调用postInvalidate方法即可,这样就省去使用handler的烦恼了。

Paste_Image.png

然后建个activity去调用它,就能实现需要的效果了。

Paste_Image.png

总代码:
xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">

    <Button
        android:id="@+id/start"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="start"/>

    <rcjs.com.customviewdemo.widget.AnimationCircleView
        android:id="@+id/circle"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>

自定义view:

package rcjs.com.customviewdemo.widget;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;

import rcjs.com.customviewdemo.utils.UIHelper;

/**
 * Created by 仁昌居士 on 2017/5/3.
 * Description:
 */

public class AnimationCircleView extends View implements Runnable {
    private Paint mPaint;
    private Context mContext;
    private int mWidth;
    private int mHeight;
    private int radiu;// 圆环半径

    public AnimationCircleView(Context context) {
        this(context, null);

    }

    public AnimationCircleView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);

        // 初始化
        initView(context);
    }

    private void initView(Context context) {
        mContext = context;
        mWidth = UIHelper.getWindowWidthHeight(mContext)[0];
        mHeight = UIHelper.getWindowWidthHeight(mContext)[1];
        // 初始化画笔
        initPaint();
    }


    /**
     * 初始化画笔
     */
    private void initPaint() {
        // 实例化画笔并打开抗锯齿
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

    /*
     * 设置画笔样式为描边,圆环嘛……当然不能填充不然就么意思了
     *
     * 画笔样式分三种:
     * 1.Paint.Style.STROKE:描边
     * 2.Paint.Style.FILL_AND_STROKE:描边并填充
     * 3.Paint.Style.FILL:填充
     */
        mPaint.setStyle(Paint.Style.STROKE);

        // 设置画笔颜色为浅灰色
        mPaint.setColor(Color.LTGRAY);

    /*
     * 设置描边的粗细,单位:像素px
     * 注意:当setStrokeWidth(0)的时候描边宽度并不为0而是只占一个像素
     */
        mPaint.setStrokeWidth(10);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        // 绘制圆环
        canvas.drawCircle(mWidth / 2, mHeight / 2, radiu, mPaint);
    }

    @Override
    public synchronized void run() {
         /*
         * 确保线程不断执行不断刷新界面
         */
        while (true) {
            try {
                /*
                 * 如果半径小于200则自加否则大于200后重置半径值以实现往复
                 */
                if (radiu <= 200) {
                    radiu += 10;

                    // 刷新View
                    postInvalidate();// invalidate();必须在子线程里去调用,postInvalidate();会另开线程调用

                } else {
                    radiu = 0;
                }

                // 每执行一次暂停40毫秒
                Thread.sleep(40);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

Activity:

package rcjs.com.customviewdemo.ui.activity;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import rcjs.com.customviewdemo.R;
import rcjs.com.customviewdemo.widget.AnimationCircleView;

/**
 * Created by 仁昌居士 on 2017/5/3.
 * Description:
 */

public class AnimationCircleActivity extends AppCompatActivity {

    @BindView(R.id.circle)
    AnimationCircleView mAnimationCircleView;
    @BindView(R.id.start)
    Button start;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_animationcircle);
        ButterKnife.bind(this);
    }

    @OnClick(R.id.start)
    public void onClick(View view) {
          /*
         * 开线程
         */
        new Thread(mAnimationCircleView).start();
    }

}

好了,接下来就是看第二篇去了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,045评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,114评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,120评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,902评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,828评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,132评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,590评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,258评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,408评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,335评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,385评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,068评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,660评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,747评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,967评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,406评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,970评论 2 341

推荐阅读更多精彩内容