mg4377娱乐娱城官网_mg4377娱乐手机版_www.mg4377.com

自定义控件之圆形控件,Android自定义控件之圆形

时间:2019-09-08 07:48来源:mg4377娱乐手机版
在广大地方,大家兴许会用到本质图片控件,不过安卓又没有提供这么的控件,大家只能和煦写三个,每回都手动写非常的麻烦,这里平素封装二个本质图片控件,在要求的时候一贯调

在广大地方,大家兴许会用到本质图片控件,不过安卓又没有提供这么的控件,大家只能和煦写三个,每回都手动写非常的麻烦,这里平素封装二个本质图片控件,在要求的时候一贯调用就行啊。创造一个CircleImageView类,代码如下:

自定义控件 - 圈圈

Android L; Android Studio
功用:能够自定义圆圈半径和岗位;设定点击效果;更换背景颜色

下面是demo图
点击前: mg4377娱乐手机版 1 点击后: mg4377娱乐手机版 2
自定义控件一般要继续View;写出构造方法,并设定属性;复写onDrawmg4377娱乐手机版,方法
并在xml中配备一下
例子:OptionCircle.java CirclesActivity.java activity_circle_choose.xml
以那一件事例未有选取attrs.xml

自定义控件之圆形控件,Android自定义控件之圆形石英钟。宣示:原创文章,转发请注解出处

前面运用过,今后做下记录

package com.***.*****.view;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Bitmap;import android.graphics.BitmapShader;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Matrix;import android.graphics.Paint;import android.graphics.RectF;import android.graphics.Shader;import android.graphics.drawable.BitmapDrawable;import android.graphics.drawable.ColorDrawable;import android.graphics.drawable.Drawable;import android.net.Uri;import android.util.AttributeSet;import com.***.*****.R;/** * 圆形图片 */public class CircleImageView extends android.support.v7.widget.AppCompatImageView { private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP; private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888; private static final int COLORDRAWABLE_DIMENSION = 1; private static final int DEFAULT_BORDER_WIDTH = 2; private static final int DEFAULT_BORDER_COLOR = Color.WHITE; private final RectF mDrawableRect = new RectF(); private final RectF mBorderRect = new RectF(); private final Matrix mShaderMatrix = new Matrix(); private final Paint mBitmapPaint = new Paint(); private final Paint mBorderPaint = new Paint(); private int mBorderColor = DEFAULT_BORDER_COLOR; private int mBorderWidth = DEFAULT_BORDER_WIDTH; private Bitmap mBitmap; private BitmapShader mBitmapShader; private int mBitmapWidth; private int mBitmapHeight; private float mDrawableRadius; private float mBorderRadius; private boolean mReady; private boolean mSetupPending; public CircleImageView(Context context) { super; init(); } public CircleImageView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CircleImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyle, 0); mBorderWidth = a.getDimensionPixelSize( R.styleable.CircleImageView_border_width_new, DEFAULT_BORDER_WIDTH); mBorderColor = a.getColor(R.styleable.CircleImageView_border_color_new, DEFAULT_BORDER_COLOR); a.recycle; } private void init() { super.setScaleType(SCALE_TYPE); mReady = true; if (mSetupPending) { setup(); mSetupPending = false; } } @Override public ScaleType getScaleType() { return SCALE_TYPE; } @Override public void setScaleType(ScaleType scaleType) { if (scaleType != SCALE_TYPE) { throw new IllegalArgumentException(String.format( "ScaleType %s not supported.", scaleType)); } } public boolean isCirclel = true; @Override protected void onDraw(Canvas canvas) { if (getDrawable() == null) { return; } if (isCirclel) { canvas.drawCircle(getWidth() / 2, getHeight() / 2, mDrawableRadius, mBitmapPaint); if (mBorderWidth != 0) { canvas.drawCircle(getWidth() / 2, getHeight() / 2, mBorderRadius, mBorderPaint); } } } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); setup(); } public int getBorderColor() { return mBorderColor; } public void setBorderColor(int borderColor) { if (borderColor == mBorderColor) { return; } mBorderColor = borderColor; mBorderPaint.setColor(mBorderColor); invalidate(); } public int getBorderWidth() { return mBorderWidth; } public void setBorderWidth(int borderWidth) { if (borderWidth == mBorderWidth) { return; } mBorderWidth = borderWidth; setup(); } @Override public void setImageBitmap(Bitmap bm) { super.setImageBitmap; mBitmap = bm; setup(); } @Override public void setImageDrawable(Drawable drawable) { super.setImageDrawable; mBitmap = getBitmapFromDrawable; setup(); } @Override public void setImageResource(int resId) { super.setImageResource; mBitmap = getBitmapFromDrawable(getDrawable; setup(); } @Override public void setImageURI { super.setImageURI; mBitmap = getBitmapFromDrawable(getDrawable; setup(); } private Bitmap getBitmapFromDrawable(Drawable drawable) { if (drawable == null) { return null; } if (drawable instanceof BitmapDrawable) { return ((BitmapDrawable) drawable).getBitmap(); } try { Bitmap bitmap; if (drawable instanceof ColorDrawable) { bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG); } else { bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), BITMAP_CONFIG); } Canvas canvas = new Canvas; drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight; drawable.draw; return bitmap; } catch (OutOfMemoryError e) { return null; } } private void setup() { if  { mSetupPending = true; return; } if (mBitmap == null) { return; } mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); mBitmapPaint.setAntiAlias; mBitmapPaint.setShader(mBitmapShader); mBorderPaint.setStyle(Paint.Style.STROKE); mBorderPaint.setAntiAlias; mBorderPaint.setColor(mBorderColor); mBorderPaint.setStrokeWidth(mBorderWidth); mBitmapHeight = mBitmap.getHeight(); mBitmapWidth = mBitmap.getWidth(); mBorderRect.set(0, 0, getWidth(), getHeight; mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2, (mBorderRect.width() - mBorderWidth) / 2); mDrawableRect.set(mBorderWidth, mBorderWidth, mBorderRect.width() - mBorderWidth, mBorderRect.height() - mBorderWidth); mDrawableRadius = Math.min(mDrawableRect.height() / 2, mDrawableRect.width; updateShaderMatrix(); invalidate(); } private void updateShaderMatrix() { float scale; float dx = 0; float dy = 0; mShaderMatrix.set; if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() * mBitmapHeight) { scale = mDrawableRect.height() / mBitmapHeight; dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f; } else { scale = mDrawableRect.width() / mBitmapWidth; dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f; } mShaderMatrix.setScale(scale, scale); mShaderMatrix.postTranslate (dx   0.5f)   mBorderWidth,  (dy   0.5f)   mBorderWidth); mBitmapShader.setLocalMatrix(mShaderMatrix); }}

控件 OptionCircle

此地继续的是ImageView;设定了多个属性,有半径,圆心地点,背景颜色和字体颜色等等
本着这么些属性,开放set方法;方便设置属性;能够转移这么些属性来做出一些卡通效果
构造方法中预设多少个属性,设置画笔,背景颜色和圆形的半径
onDraw办法中开端绘制控件;先画圆形,在圈子为主画上文字;文字为主定位供给特意总括一下

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;

public class OptionCircle extends ImageView {

    private final Paint paint;
    private final Context context;
    boolean clicked = false;// 是否被点击
    boolean addBackground = false;
    int radius = -1;      // 半径值初始化为-1
    int centerOffsetX = 0;// 圆圈原点的偏移量x
    int centerOffsetY = 0;// 偏移量y
    int colorCircle;      // 圆圈颜色
    int colorBackground;  // 背景填充颜色
    int colorText;        // 文字颜色
    String textCircle = "";

    public OptionCircle(Context context) {
        this(context, null);
    }

    public OptionCircle(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        this.paint = new Paint();
        this.paint.setAntiAlias(true);
        this.paint.setStyle(Paint.Style.STROKE);
        colorCircle = Color.argb(205, 245, 2, 51);// 默认颜色
        colorText = colorCircle;      // 字体颜色默认与圈圈颜色保持一致
        colorBackground = colorCircle;// 设定默认参数
    }
    // 属性设置方法
    public void setRadius(int r) {
        this.radius = r;
    }

    public void setCenterOffset(int x, int y) {
        this.centerOffsetX = x;
        this.centerOffsetY = y;
    }

    public void setColorCircle(int c) {
        this.colorCircle = c;
    }

    public void setColorText(int c) {
        this.colorText = c;
    }

    public void setColorBackground(int c) {
        this.colorBackground = c;
    }

    public void setText(String s) {
        this.textCircle = s;
    }

    public void setClicked(boolean clicked) {
        this.clicked = clicked;
    }

    public void setAddBackground(boolean add) {
        this.addBackground = add;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        int center = getWidth() / 2;// 当前宽度的一半
        int innerCircle = 86;       // 默认半径为86
        if (radius > 0) {
            innerCircle = dip2px(context, radius); // 如果没有另外设置半径,取半径86
        }

        Drawable drawable = getDrawable();
        if (addBackground) {
        } else {
            // 画圈圈;被点击后会变成实心的圈圈,默认是空心的
            this.paint.setStyle(clicked ? Paint.Style.FILL : Paint.Style.STROKE);
            this.paint.setColor(clicked ? colorBackground : colorCircle);
            this.paint.setStrokeWidth(1.5f);
            canvas.drawCircle(center   centerOffsetX, center   centerOffsetY,
                    innerCircle, this.paint);// 画圆圈时带上偏移量
        }

        // 绘制文字
        this.paint.setStyle(Paint.Style.FILL);
        this.paint.setStrokeWidth(1);
        this.paint.setTextSize(22);
        this.paint.setTypeface(Typeface.MONOSPACE);// 设置一系列文字属性
        this.paint.setColor(clicked ? Color.WHITE : colorText);
        this.paint.setTextAlign(Paint.Align.CENTER);// 文字水平居中
        Paint.FontMetricsInt fontMetrics = paint.getFontMetricsInt();
        canvas.drawText(textCircle, center   centerOffsetX,
                center   centerOffsetY - (fontMetrics.top   fontMetrics.bottom) / 2, this.paint);// 设置文字竖直方向居中
        super.onDraw(canvas);
    }

    /**
     * convert dp to px
     */
    public static int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale   0.5f);
    }
}

新近,Computer蓦然罢工了,搞了自己好长期才弄好。。所以写那篇作品推延了相当长日子。废话比比较少说后马来西亚人给大家带来三个近期协和造的车轱辘——自定义石英钟。对自定义控件风乐趣的心上人能够看看,具体内容小编会尽量讲的事无巨细。先看一下成效图:

  • ### 自定义圆形控件github地址:

在values文件夹下创造三个attrs.xml文件,加多一下代码

配置 activity_circle_choose.xml

控件文件定义实现,在activity_circle_choose.xml中配备一下
定义4个圈圈;center_circle定位在宗旨;circle_0是丁丑革命的;circle_1是黑古铜色的;circle_2是洋朱红的

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

    <TextView
        android:id="@ id/top_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="5dp"
        android:text="@string/circles_top_title"
        android:textSize="26sp" />

    <com.rust.aboutview.view.OptionCircle
        android:id="@ id/center_circle"
        android:layout_width="140dp"
        android:layout_height="140dp"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true" />

    <com.rust.aboutview.view.OptionCircle
        android:id="@ id/circle_0"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_marginStart="130dp"
        android:layout_marginTop="53dp" />

    <com.rust.aboutview.view.OptionCircle
        android:id="@ id/circle_1"
        android:layout_width="210dp"
        android:layout_height="210dp"
        android:layout_below="@ id/circle_0"
        android:layout_toEndOf="@ id/center_circle" />

    <com.rust.aboutview.view.OptionCircle
        android:id="@ id/circle_2"
        android:layout_width="210dp"
        android:layout_height="210dp"
        android:layout_below="@id/center_circle" />

</RelativeLayout>

mg4377娱乐手机版 3mg4377娱乐手机版 4mg4377娱乐手机版 5

https://github.com/hdodenhof/CircleImageView

<declare-styleable name="CircleImageView"> <attr name="border_width_new" format="dimension" /> <attr name="border_color_new" format="color" /> </declare-styleable>

在 CirclesActivity.java 中选择范围

圈圈类OptionCircle.java早就开放了安装属性的点子,大家得以采用那一个措施来调治圈圈的体制,比方半径,颜色,圆心偏移量
center_circle固定在显示器中间不动
circle_0仿造贰个加大降低的意义,改动半径值就可以兑现
circle_1仿制四个变动的效能,改变圆心偏移量来兑现
circle_2克隆抖动效果,也是改动圆心偏移量
那么些层面都得以自定义背景颜色

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;

import com.rust.aboutview.view.OptionCircle;

public class CirclesActivity extends Activity {

    public static final String TAG = "CirclesActivity";
    public static final int circle0_r = 88;

    private static final int SLEEPING_PERIOD = 100; // 刷新UI间隔时间
    private static final int UPDATE_ALL_CIRCLE = 99;
    int circleCenter_r;
    int circle1_r;
    boolean circle0Clicked = false;
    boolean circle1Clicked = false;

    OptionCircle centerCircle;
    OptionCircle circle0;
    OptionCircle circle1;
    OptionCircle circle2;

    CircleHandler handler = new CircleHandler(this);

    /**
     * Handler : 用于更新UI
     */
    static class CircleHandler extends Handler {
        CirclesActivity activity;
        boolean zoomDir = true;
        boolean circle2Shaking = false;
        int r = circle0_r;
        int moveDir = 0;  // 浮动方向
        int circle1_x = 0;// 偏移量的值
        int circle1_y = 0;
        int circle2_x = 0;
        int circle2ShakeTime = 0;
        int circle2Offsets[] = {10, 15, -6, 12, 0};// 抖动偏移量坐标

        CircleHandler(CirclesActivity a) {
            activity = a;
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case UPDATE_ALL_CIRCLE: {
                    if (zoomDir) {// 用简单的办法实现半径变化
                        r  ;
                        if (r >= 99) zoomDir = false;
                    } else {
                        r--;
                        if (r <= circle0_r) zoomDir = true;
                    }
                    activity.circle0.invalidate();
                    activity.circle0.setRadius(r);
                    calOffsetX();// 计算圆心偏移量
                    activity.circle1.invalidate();
                    activity.circle1.setCenterOffset(circle1_x, circle1_y);

                    if (circle2Shaking) {
                        if (circle2ShakeTime < circle2Offsets.length - 1) {
                            circle2ShakeTime  ;
                        } else {
                            circle2Shaking = false;
                            circle2ShakeTime = 0;
                        }
                        activity.circle2.invalidate();
                        activity.circle2.setCenterOffset(circle2Offsets[circle2ShakeTime], 0);
                    }
                }
            }
        }
        // 计算circle1圆心偏移量;共有4个浮动方向
        private void calOffsetX() {
            if (moveDir == 0) {
                circle1_x--;
                circle1_y  ;
                if (circle1_x <= -6) moveDir = 1;
            }
            if (moveDir == 1) {
                circle1_x  ;
                circle1_y  ;
                if (circle1_x >= 0) moveDir = 2;
            }
            if (moveDir == 2) {
                circle1_x  ;
                circle1_y--;
                if (circle1_x >= 6) moveDir = 3;
            }
            if (moveDir == 3) {
                circle1_x--;
                circle1_y--;
                if (circle1_x <= 0) moveDir = 0;
            }
        }
    }

    class UpdateCircles implements Runnable {

        @Override
        public void run() {
            while (true) {// 配合Handler,循环刷新UI
                Message message = new Message();
                message.what = UPDATE_ALL_CIRCLE;
                handler.sendEmptyMessage(message.what);
                try {
                    Thread.sleep(SLEEPING_PERIOD); // 暂停
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_circle_choose);
        centerCircle = (OptionCircle) findViewById(R.id.center_circle);
        circle0 = (OptionCircle) findViewById(R.id.circle_0);
        circle1 = (OptionCircle) findViewById(R.id.circle_1);
        circle2 = (OptionCircle) findViewById(R.id.circle_2);

        circleCenter_r = 38;
        circle1_r = 45;
        // 设置圈圈的属性
        centerCircle.setRadius(circleCenter_r);
        centerCircle.setColorText(Color.BLUE);
        centerCircle.setColorCircle(Color.BLUE);
        centerCircle.setText("点击圈圈");

        circle0.setColorText(Color.RED);
        circle0.setRadius(circle0_r);
        circle0.setText("RED");

        circle1.setColorCircle(Color.GREEN);
        circle1.setColorText(Color.GREEN);
        circle1.setText("Green");
        circle1.setRadius(circle1_r);

        circle2.setColorCircle(getResources().getColor(R.color.colorMagenta));
        circle2.setColorText(getResources().getColor(R.color.colorMagenta));
        circle2.setText("Frozen!");

        // 设定点击事件,可在这里改变控件的属性
        circle0.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                circle0Clicked = !circle0Clicked;  // 每次点击都取反
                circle0.setClicked(circle0Clicked);
            }
        });

        circle1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                circle1Clicked = !circle1Clicked;
                circle1.setColorBackground(Color.GREEN);
                circle1.setClicked(circle1Clicked);
            }
        });

        circle2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                handler.circle2Shaking = true;// 颤抖吧!
            }
        });

        Thread t = new Thread(new UpdateCircles());
        t.start();// 开启子线程
    }
}

于今,圈圈demo甘休。通过轻巧的图谋,模拟出浮动,抖动,缩放的作用
如上的代码,复制粘贴进工程里就能够动用。圆心移动的轨道,用三角函数来计算会更加好
此地延续的是ImageView,应该有一些子在圈内动态增进背景Bitmap,效果更加美观

我们在做自定义控件时,能够把本身想像成一名美学家。你在作品本人的艺术品。那么作为一名美学家,你一定得供给至少两样工具:画笔和画布。这两样是画画的底蕴,一个都不可能少。那么Android有这两样东西呢,答案是必然的。在Android中Paint正是大家的画笔,Canvas就是大家的画布。那么这两样东西该怎么去用吗?其实也非常粗大略,Paint提供了成都百货上千主意,我们通过这一个措施能够对那只笔进行设置,比方笔的颜色,画出来线条的粗细等等。而Canvas则承担具体要画的东西,比方点,线,矩形,圆形等等,有关具体的使用细节作者说话会详细疏解。这里您只需求大致领会有那样个东西就足以了。

  • ### 使用方法

一个精神图片控件就定义好了。怎么用吗?在急需的地方,加多自定义控件,代码如下

好了,回到大家的核心上来,画笔和画布都有了,那么难题来了,,,开采机技艺哪家强。。。。。日。。再来二遍,,那么难点来了,若是是您想要在现实生活中画两个石英钟,你感觉都得要画什么吧?笔者想时辰候我们明显皆有在团结手上画石英表的阅历吧。首先,当然得有贰个边框吧,然后是圆心、刻度以及数字,当然还会有最关键的指针,这也是组成机械钟最基本的成分,相信您当时必然画的很美丽貌。那么在Android中毕竟该怎么去画吗。接下来,笔者就带我们一齐走访,那个事物是什么样一步步画在表弟大上的。

<LinearLayout android:layout_width="0dp" android:layout_weight="1" android:gravity="center" android:layout_height="wrap_content"> <com.zydl.citymanagement.view.CircleImageView android: android:src="@mipmap/icon_test_head" android:layout_width="40dp" android:layout_height="40dp" /> </LinearLayout>

首先,大家得自个儿定义叁个类取名称为TimeView,让其后续View,然后创设构造方法,最后大家要覆写onDraw(Canvas canvas)办法,大家现实的图案逻辑就在那些艺术中。具体代码如下:

<de.hdodenhof.circleimageview.CircleImageView 
   xmlns:app="http://schemas.android.com/apk/res-auto" 
   android:id="@ id/profile_image"
   android:layout_width="96dp" 
   android:layout_height="96dp"
   android:src="@drawable/profile"
   app:civ_border_width="2dp" 
   app:civ_border_color="#FF000000"/>

二个本质图片控件就增多好了,在后头设置这些控件的src的时候,图片都会以圆形呈现出来。

public class TimeView extends View{ private Context mContext; private Paint mPaint; public TimeView(Context context) { super; this.mContext = context; initPaint(); } public TimeView(Context context, AttributeSet attrs) { super(context, attrs); this.mContext = context; initPaint(); } /** * 初始化画笔 */ private void initPaint(){ mPaint = new Paint(); //抗锯齿 mPaint.setAntiAlias; mPaint.setColor(Color.BLACK); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth; } @Override protected void onDraw(Canvas canvas) { //画具体内容 }}
  • ### 自定义控件源码

在此处大家定义了多个构造方法,第二个大家应该都很好明白,关键是第贰个,入参多了个AttributeSet,可能我们对那东西相比较素不相识。大家明白,想要使用一个控件时,有二种情势,第一,大家得以在Java代码中央政府机关接new三个,第三种正是在XML布局文件中宣示。那二种办法也刚好对应以上二种构造方法。如若你不写第两种构造方法,那么您在XML布局文件中一直运用时会报错的。在构造方法中,大家成立了一头画笔。然后给它设置某个性格,个中setAntiAlias的效率是抗锯齿,看名称就会想到其意义借使不安装的话,在图纸边缘会有一对锯齿状的印痕。然后给这只笔设置颜色,以及风格。风格一共有两种:Paint.Style.STROKE,描边效果,譬如你画三个圆,呈现的正是一个圆环;Paint.Style.FILL、填充效果,展现的万事圆;Paint.Style.FILL_AND_STROKE,那么些既有描边,又有填充其实际效果果和FILL大约。如若设置成STROKE,那么您能够用setStrokeWidth()给那条边安装宽度。那样大家的画笔就绸缪好了,画布正是大家onDraw(Canvas canvas)中的canvas现已给大家提供好了。好了,那样大家就早就写好了叁个自定义控件。然后大家就足以在XML布局文件中引用了,注意:控件名前必定要加具体的包名。好了那般我们运营一下发觉怎么都不曾,因为咱们在onDraw方法中还没干任何业务,可是别发急,接下去大家一步步来促成。

<com.example.administrator.timeviewdemo.TimeView android: android:layout_width="300dp" android:layout_height="300dp"/>
/*

* Copyright 2014 - 2016 Henning Dodenhof

*

* Licensed under the Apache License, Version 2.0 (the "License");

* you may not use this file except in compliance with the License.

* You may obtain a copy of the License at

*

*    http://www.apache.org/licenses/LICENSE-2.0

*

* Unless required by applicable law or agreed to in writing, software

* distributed under the License is distributed on an "AS IS" BASIS,

* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

* See the License for the specific language governing permissions and

* limitations under the License.

*/

packagede.hdodenhof.circleimageview;

importandroid.content.Context;

importandroid.content.res.TypedArray;

importandroid.graphics.Bitmap;

importandroid.graphics.BitmapShader;

importandroid.graphics.Canvas;

importandroid.graphics.Color;

importandroid.graphics.ColorFilter;

importandroid.graphics.Matrix;

importandroid.graphics.Paint;

importandroid.graphics.RectF;

importandroid.graphics.Shader;

importandroid.graphics.drawable.BitmapDrawable;

importandroid.graphics.drawable.ColorDrawable;

importandroid.graphics.drawable.Drawable;

importandroid.net.Uri;

importandroid.support.annotation.ColorInt;

importandroid.support.annotation.ColorRes;

importandroid.support.annotation.DrawableRes;

importandroid.util.AttributeSet;

importandroid.widget.ImageView;

publicclassCircleImageViewextendsImageView{

privatestaticfinalScaleTypeSCALE_TYPE=ScaleType.CENTER_CROP;

privatestaticfinalBitmap.ConfigBITMAP_CONFIG=Bitmap.Config.ARGB_8888;

privatestaticfinalintCOLORDRAWABLE_DIMENSION=2;

privatestaticfinalintDEFAULT_BORDER_WIDTH=0;

privatestaticfinalintDEFAULT_BORDER_COLOR=Color.BLACK;

privatestaticfinalintDEFAULT_FILL_COLOR=Color.TRANSPARENT;

privatestaticfinalbooleanDEFAULT_BORDER_OVERLAY=false;

privatefinalRectFmDrawableRect=newRectF();

privatefinalRectFmBorderRect=newRectF();

privatefinalMatrixmShaderMatrix=newMatrix();

privatefinalPaintmBitmapPaint=newPaint();

privatefinalPaintmBorderPaint=newPaint();

privatefinalPaintmFillPaint=newPaint();

privateintmBorderColor=DEFAULT_BORDER_COLOR;

privateintmBorderWidth=DEFAULT_BORDER_WIDTH;

privateintmFillColor=DEFAULT_FILL_COLOR;

privateBitmapmBitmap;

privateBitmapShadermBitmapShader;

privateintmBitmapWidth;

privateintmBitmapHeight;

privatefloatmDrawableRadius;

privatefloatmBorderRadius;

privateColorFiltermColorFilter;

privatebooleanmReady;

privatebooleanmSetupPending;

privatebooleanmBorderOverlay;

privatebooleanmDisableCircularTransformation;

publicCircleImageView(Contextcontext) {

super(context);

init();

}

publicCircleImageView(Contextcontext,AttributeSetattrs) {

this(context, attrs,0);

}

publicCircleImageView(Contextcontext,AttributeSetattrs,intdefStyle) {

super(context, attrs, defStyle);

TypedArraya=context.obtainStyledAttributes(attrs,R.styleable.CircleImageView, defStyle,0);

mBorderWidth=a.getDimensionPixelSize(R.styleable.CircleImageView_civ_border_width,DEFAULT_BORDER_WIDTH);

mBorderColor=a.getColor(R.styleable.CircleImageView_civ_border_color,DEFAULT_BORDER_COLOR);

mBorderOverlay=a.getBoolean(R.styleable.CircleImageView_civ_border_overlay,DEFAULT_BORDER_OVERLAY);

mFillColor=a.getColor(R.styleable.CircleImageView_civ_fill_color,DEFAULT_FILL_COLOR);

a.recycle();

init();

}

privatevoidinit() {

super.setScaleType(SCALE_TYPE);

mReady=true;

if(mSetupPending) {

setup();

mSetupPending=false;

}

}

@Override

publicScaleTypegetScaleType() {

returnSCALE_TYPE;

}

@Override

publicvoidsetScaleType(ScaleTypescaleType) {

if(scaleType!=SCALE_TYPE) {

thrownewIllegalArgumentException(String.format("ScaleType %s not supported.", scaleType));

}

}

@Override

publicvoidsetAdjustViewBounds(booleanadjustViewBounds) {

if(adjustViewBounds) {

thrownewIllegalArgumentException("adjustViewBounds not supported.");

}

}

@Override

protectedvoidonDraw(Canvascanvas) {

if(mDisableCircularTransformation) {

super.onDraw(canvas);

return;

}

if(mBitmap==null) {

return;

}

if(mFillColor!=Color.TRANSPARENT) {

canvas.drawCircle(mDrawableRect.centerX(), mDrawableRect.centerY(), mDrawableRadius, mFillPaint);

}

canvas.drawCircle(mDrawableRect.centerX(), mDrawableRect.centerY(), mDrawableRadius, mBitmapPaint);

if(mBorderWidth>0) {

canvas.drawCircle(mBorderRect.centerX(), mBorderRect.centerY(), mBorderRadius, mBorderPaint);

}

}

@Override

protectedvoidonSizeChanged(intw,inth,intoldw,intoldh) {

super.onSizeChanged(w, h, oldw, oldh);

setup();

}

@Override

publicvoidsetPadding(intleft,inttop,intright,intbottom) {

super.setPadding(left, top, right, bottom);

setup();

}

@Override

publicvoidsetPaddingRelative(intstart,inttop,intend,intbottom) {

super.setPaddingRelative(start, top, end, bottom);

setup();

}

publicintgetBorderColor() {

returnmBorderColor;

}

publicvoidsetBorderColor(@ColorIntintborderColor) {

if(borderColor==mBorderColor) {

return;

}

mBorderColor=borderColor;

mBorderPaint.setColor(mBorderColor);

invalidate();

}

/**

* @deprecated Use {@link #setBorderColor(int)} instead

*/

@Deprecated

publicvoidsetBorderColorResource(@ColorResintborderColorRes) {

setBorderColor(getContext().getResources().getColor(borderColorRes));

}

/**

* Return the color drawn behind the circle-shaped drawable.

*

* @return The color drawn behind the drawable

*

* @deprecated Fill color support is going to be removed in the future

*/

@Deprecated

publicintgetFillColor() {

returnmFillColor;

}

/**

* Set a color to be drawn behind the circle-shaped drawable. Note that

* this has no effect if the drawable is opaque or no drawable is set.

*

* @param fillColor The color to be drawn behind the drawable

*

* @deprecated Fill color support is going to be removed in the future

*/

@Deprecated

publicvoidsetFillColor(@ColorIntintfillColor) {

if(fillColor==mFillColor) {

return;

}

mFillColor=fillColor;

mFillPaint.setColor(fillColor);

invalidate();

}

/**

* Set a color to be drawn behind the circle-shaped drawable. Note that

* this has no effect if the drawable is opaque or no drawable is set.

*

* @param fillColorRes The color resource to be resolved to a color and

*                    drawn behind the drawable

*

* @deprecated Fill color support is going to be removed in the future

*/

@Deprecated

publicvoidsetFillColorResource(@ColorResintfillColorRes) {

setFillColor(getContext().getResources().getColor(fillColorRes));

}

publicintgetBorderWidth() {

returnmBorderWidth;

}

publicvoidsetBorderWidth(intborderWidth) {

if(borderWidth==mBorderWidth) {

return;

}

mBorderWidth=borderWidth;

setup();

}

publicbooleanisBorderOverlay() {

returnmBorderOverlay;

}

publicvoidsetBorderOverlay(booleanborderOverlay) {

if(borderOverlay==mBorderOverlay) {

return;

}

mBorderOverlay=borderOverlay;

setup();

}

publicbooleanisDisableCircularTransformation() {

returnmDisableCircularTransformation;

}

publicvoidsetDisableCircularTransformation(booleandisableCircularTransformation) {

if(mDisableCircularTransformation==disableCircularTransformation) {

return;

}

mDisableCircularTransformation=disableCircularTransformation;

initializeBitmap();

}

@Override

publicvoidsetImageBitmap(Bitmapbm) {

super.setImageBitmap(bm);

initializeBitmap();

}

@Override

publicvoidsetImageDrawable(Drawabledrawable) {

super.setImageDrawable(drawable);

initializeBitmap();

}

@Override

publicvoidsetImageResource(@DrawableResintresId) {

super.setImageResource(resId);

initializeBitmap();

}

@Override

publicvoidsetImageURI(Uriuri) {

super.setImageURI(uri);

initializeBitmap();

}

@Override

publicvoidsetColorFilter(ColorFiltercf) {

if(cf==mColorFilter) {

return;

}

mColorFilter=cf;

applyColorFilter();

invalidate();

}

@Override

publicColorFiltergetColorFilter() {

returnmColorFilter;

}

privatevoidapplyColorFilter() {

if(mBitmapPaint!=null) {

mBitmapPaint.setColorFilter(mColorFilter);

}

}

privateBitmapgetBitmapFromDrawable(Drawabledrawable) {

if(drawable==null) {

returnnull;

}

if(drawableinstanceofBitmapDrawable) {

return((BitmapDrawable) drawable).getBitmap();

}

try{

Bitmapbitmap;

if(drawableinstanceofColorDrawable) {

bitmap=Bitmap.createBitmap(COLORDRAWABLE_DIMENSION,COLORDRAWABLE_DIMENSION,BITMAP_CONFIG);

}else{

bitmap=Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(),BITMAP_CONFIG);

}

Canvascanvas=newCanvas(bitmap);

drawable.setBounds(0,0, canvas.getWidth(), canvas.getHeight());

drawable.draw(canvas);

returnbitmap;

}catch(Exceptione) {

e.printStackTrace();

returnnull;

}

}

privatevoidinitializeBitmap() {

if(mDisableCircularTransformation) {

mBitmap=null;

}else{

mBitmap=getBitmapFromDrawable(getDrawable());

}

setup();

}

privatevoidsetup() {

if(!mReady) {

mSetupPending=true;

return;

}

if(getWidth()==0&&getHeight()==0) {

return;

}

if(mBitmap==null) {

invalidate();

return;

}

mBitmapShader=newBitmapShader(mBitmap,Shader.TileMode.CLAMP,Shader.TileMode.CLAMP);

mBitmapPaint.setAntiAlias(true);

mBitmapPaint.setShader(mBitmapShader);

mBorderPaint.setStyle(Paint.Style.STROKE);

mBorderPaint.setAntiAlias(true);

mBorderPaint.setColor(mBorderColor);

mBorderPaint.setStrokeWidth(mBorderWidth);

mFillPaint.setStyle(Paint.Style.FILL);

mFillPaint.setAntiAlias(true);

mFillPaint.setColor(mFillColor);

mBitmapHeight=mBitmap.getHeight();

mBitmapWidth=mBitmap.getWidth();

mBorderRect.set(calculateBounds());

mBorderRadius=Math.min((mBorderRect.height()-mBorderWidth)/2.0f, (mBorderRect.width()-mBorderWidth)/2.0f);

mDrawableRect.set(mBorderRect);

if(!mBorderOverlay&&mBorderWidth>0) {

mDrawableRect.inset(mBorderWidth-1.0f, mBorderWidth-1.0f);

}

mDrawableRadius=Math.min(mDrawableRect.height()/2.0f, mDrawableRect.width()/2.0f);

applyColorFilter();

updateShaderMatrix();

invalidate();

}

privateRectFcalculateBounds() {

intavailableWidth=getWidth()-getPaddingLeft()-getPaddingRight();

intavailableHeight=getHeight()-getPaddingTop()-getPaddingBottom();

intsideLength=Math.min(availableWidth, availableHeight);

floatleft=getPaddingLeft() (availableWidth-sideLength)/2f;

floattop=getPaddingTop() (availableHeight-sideLength)/2f;

returnnewRectF(left, top, left sideLength, top sideLength);

}

privatevoidupdateShaderMatrix() {

floatscale;

floatdx=0;

floatdy=0;

mShaderMatrix.set(null);

if(mBitmapWidth*mDrawableRect.height()>mDrawableRect.width()*mBitmapHeight) {

scale=mDrawableRect.height()/(float) mBitmapHeight;

dx=(mDrawableRect.width()-mBitmapWidth*scale)*0.5f;

}else{

scale=mDrawableRect.width()/(float) mBitmapWidth;

dy=(mDrawableRect.height()-mBitmapHeight*scale)*0.5f;

}

mShaderMatrix.setScale(scale, scale);

mShaderMatrix.postTranslate((int) (dx 0.5f) mDrawableRect.left, (int) (dy 0.5f) mDrawableRect.top);

mBitmapShader.setLocalMatrix(mShaderMatrix);

}

}

我们的边框就是二个简练的圆:

@Overrideprotected void onDraw(Canvas canvas){ //圆形边框 canvas.drawCircle(getWidth() / 2, getHeight() / 2, getWidth() / 3, mPaint);}

我们能够观察,要想画三个圆,只用调用canvas的drawCircle(float x,float y,float radius,Paint mPaint)方法,它接受多少个参数,在那之中想x、y为圆的圆心。这里作者要说一下Android的坐标系,它的坐标原点暗中认可在荧屏的左上角,向右为为X轴正方向,向下为Y轴正方向

mg4377娱乐手机版 6

此地大家圆心选在控件的为主,即宽高的四分之二。第多个参数是圆的半径,这里大家就取控件宽的三分一,第八个为事先大家创造的画笔。我们来运作看一下功效:

mg4377娱乐手机版 7

编辑:mg4377娱乐手机版 本文来源:自定义控件之圆形控件,Android自定义控件之圆形

关键词: a 自定义 控件 圆形 Android-101