Android自定义view(一):简单流程

申明

  • 本片文章大主要就是手动写一遍用来加深下印象,真想学技术还是移步下面的资料链接;
  • 参考资料:
    https://www.jianshu.com/p/7bfaf8789e5f 自定义View(一)

自定义view简单流程

  • 流程不复杂,特别如果是效果简单就很快。

流程

  • 尝试写一个自定义view,一个加载动画。
  • 一个加载loading动画的view,一个圆形或者长方形的加载框,边框一开始是完整的,然后顺时针开始消失,到完全消失的时候开始出现框中间是自己定义的加载图片或者文字。

自定义属性声明和使用

  1. 分析确认自己view的属性(长高,颜色,字体,大小)
    /**
     * 圆形的半径
     */
    private int radius = -1;
    /**
     * 加载框的颜色
     */
    private int cheek_color = Color.BLACK;
    /**
     * 加载狂中间的图片
     */
    private long imageResId = R.mipmap.ic_launcher;
    /**
     * 加载框中间的文字
     */
    private String loadingText = "加载中...";
    /**
     * 文字字体大小
     */
    private int textSize = 1;

    private int height;
    private int width;

    /**
     * 圆形图形的进度
     */
    private int progress = 5;
    private int maxProgress = 100;
    private int progressColor = Color.BLACK;
    private int backColor = Color.WHITE;


    private Paint paint = new Paint();
    ;
    private RectF rectF = new RectF();
  1. 在res/values/目录下创建attrs.xml并定义自己view属性
    <declare-styleable name="LoadingView">
        <attr name="text" format="string"/>
        <attr name="textSize" format="dimension"/>
        <attr name="mode" format="enum">
            <enum name="circle" value="0"/>
            <enum name="rectangle" value="1"/>
        </attr>
        <attr name="cheek_color" format="color"/>
        <attr name="imageRes" format="integer"/>
        <attr name="radius" format="dimension"/>
    </declare-styleable>
  1. 在layout文件中使用

    <com.southwind.selfview.view.LoadingView
        android:id="@+id/loading"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:mode="circle"
        app:radius="30dp"
        android:text="加载中..."
        app:textSize="12dp"
        app:cheek_color="@color/black"
        android:layout_width="100dp"
        android:layout_height="80dp"/>
  1. 在view构造方法里面获取
    public LoadingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.LoadingView);
        mode = array.getInteger(R.styleable.LoadingView_mode, 0);
        cheek_color = array.getColor(R.styleable.LoadingView_cheek_color, Color.BLACK);
        textSize = array.getDimensionPixelSize(R.styleable.LoadingView_textSize, (int) dip2px(13));
        imageResId = array.getResourceId(R.styleable.LoadingView_imageRes, -1);
        radius = array.getDimensionPixelSize(R.styleable.LoadingView_radius, (int) dip2px(5));

        backColor = Color.BLACK;
        progressColor = Color.WHITE;
    }

onMeasure确定view的大小尺寸

  • 这里我没做任何调整,也是不熟练,还得看看,以后专门学了在写一篇
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        height = MeasureSpec.getSize(heightMeasureSpec);
        width = MeasureSpec.getSize(widthMeasureSpec);
        setMeasuredDimension(width, height);
    }

onDraw画出你要的效果

    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
//        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
//        canvas.drawPaint(paint);

        //设置画笔属性
        paint.setStyle(Paint.Style.FILL);
        paint.setAntiAlias(true);

        //原始进度
        radius = Math.min(width, height) - 40;
        //画出进度圆形

        paint.setColor(backColor);
        rectF.left = (width - radius) / 2;//左边距:(空间宽度-直径)/2
        rectF.right = radius + (width - radius) / 2;
        rectF.top = (height - radius) / 2;
        rectF.bottom = radius + (width - radius) / 2;
        canvas.drawArc(rectF, 270, 360, false, paint);

        //首先画出当前进度的圆形
        radius = Math.min(width, height) - 38;
        //画出进度圆形
        paint.setColor(progressColor);
        rectF.left = (width - radius) / 2;//左边距:(空间宽度-直径)/2
        rectF.right = radius + (width - radius) / 2;
        rectF.top = (height - radius) / 2;
        rectF.bottom = radius + (width - radius) / 2;

        //计算进度
        float precent = (float) progress / (float) maxProgress;
        float sweepAngle = (float) (360 * precent);
        canvas.drawArc(rectF, 270, sweepAngle, false, paint);

        //画出遮挡圆形
        int radius2 = radius - 10;
        paint.setColor(Color.WHITE);
        rectF.left = (width - radius2) / 2;//左边距:(空间宽度-直径)/2
        rectF.right = radius2 + (width - radius2) / 2;
        rectF.top = (height - radius2) / 2;
        rectF.bottom = radius2 + (width - radius2) / 2;
        canvas.drawArc(rectF, 0, 360, false, paint);
        canvas.drawArc(rectF, 0, 360, false, paint);

        //画出text
        paint.setColor(Color.BLACK);
        paint.setTextSize(22);
        canvas.drawText(loadingText,width/2 - 40,height/2 + 20,paint);
    }

其他处理

  • 这里主要就是做了个循环的东西,必须要在外部开启,说实话内部不确定在哪里开启哈,肯定不能在onDraw中开启,要不然肯定会重复调用
  /**
     * 实时设置当前进度取重绘
     *
     */
    private void setCurrentProgress() {
        invalidate();
    }

    public  void startLoading(){
        CirculateThread runnable = new CirculateThread();
        Thread thread = new Thread(runnable);
        thread.start();
    }

    class CirculateThread implements Runnable {
        @Override
        public void run() {
            while (true) {
                if (progress < 100) {
                    progress += 2;
                } else {
                    progress = 0;
                    int color = progressColor;
                    progressColor = backColor;
                    backColor = color;
                }
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                setCurrentProgress();
            }
        }
    }
  • 使用
 @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        LoadingView view = this.findViewById(R.id.loading);
        view.startLoading();
    }

效果

  • 这个是最简单的流程哈,等我再学习学习搞个更吊的出来。
  • 要查看原图才能看的gif不是好gif


    你这个gif怎么不懂啊?.gif

流程很简单哈

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

推荐阅读更多精彩内容