Android自定义View-圆形印章

前言:

第一次写文章,可能有些地方文字表述得不清楚,见谅。

做这个东西的灵感来源于之前公司发的一份清明节放假通知上的盖章,就有了做个类似这种圆形印章的View的想法。刚好今天也没什么工作,就试着实现出来。

正文:

先看效果:

实现这个View,还是比较简单的,一是圆环,二是文字扇形排列,三是中间的圆形图片。

下面上具体代码:

public class StampView extends View {

    private static final int TEXT_SIZE = 32;  //文字大小
    private static final int OUTSIDE_RING_WIDTH = 10; //圆环宽度
    private static final float TEXT_ANGLE = 120f;  //文字扇形排列的角度
    private static final int RADIUS = 180;  //印章半径
    private static final int SPACING = 36;  //图片与文字间距
    private static final float STAMP_ROTATE = 15f;  //印章旋转角度

    private static final int TEXT_COLOR = 0xFF000000; //文字颜色
    private static final int CIRCLE_COLOR = 0xFFFF0000; //圆环颜色

    private String mText;
    private Bitmap source;

    private final Paint mTextPaint = new Paint();
    private final Paint mCirclePaint = new Paint();

    public StampView(Context context) {
        super(context);
        init();
    }

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

    public StampView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        mTextPaint.setColor(TEXT_COLOR);
        mTextPaint.setTextAlign(Paint.Align.CENTER);

        mCirclePaint.setColor(CIRCLE_COLOR);
        mCirclePaint.setStyle(Paint.Style.STROKE);
        mCirclePaint.setAntiAlias(true);

        source = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        // 获取宽高
        int width = this.getWidth();
        int height = this.getHeight();

        mTextPaint.setTextSize(TEXT_SIZE);

        float textY = height / 2 - RADIUS + OUTSIDE_RING_WIDTH + TEXT_SIZE;
        mText = mText != null ? mText : "";
        // 把文字拆成字符数组
        char[] chs = mText.toCharArray();

        // 画圆环
        mCirclePaint.setStrokeWidth(OUTSIDE_RING_WIDTH);
        canvas.drawCircle(width / 2, height / 2, RADIUS - OUTSIDE_RING_WIDTH / 2, mCirclePaint);

        canvas.save();
        canvas.rotate(STAMP_ROTATE, width / 2, height / 2);

        // 中间圆形位图的半径
        int radius = RADIUS - OUTSIDE_RING_WIDTH - TEXT_SIZE - SPACING;
        Bitmap image = createCircleImage(source, radius * 2);
        canvas.drawBitmap(image, (width - image.getWidth()) / 2, (height - image.getHeight()) / 2,
                mCirclePaint);
        image.recycle();

        canvas.rotate(-TEXT_ANGLE / 2, width / 2, height / 2);
        // 每个文字间的角度间隔
        float spaceAngle = TEXT_ANGLE / (chs.length - 1);
        for(int i = 0; i < chs.length; i++) {
            String s = String.valueOf(chs[i]);
            canvas.drawText(s, width / 2, textY, mTextPaint);
            canvas.rotate(spaceAngle, width / 2, height / 2);
        }
        canvas.restore();
    }

    /**
     * 创建圆形位图
     * @param source 原图片位图
     * @param diameter 圆形位图的直径
     * @return
     */
    private Bitmap createCircleImage(Bitmap source, int diameter) {
        final Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setFilterBitmap(true);

        int width = source.getWidth();
        int height = source.getHeight();
        Bitmap clipBitmap;
        if(width > height) {
            int x = (width - height) / 2;
            int y = 0;
            clipBitmap = Bitmap.createBitmap(source, x, y, height, height);
        } else if(width < height) {
            int x = 0;
            int y = (height - width) / 2;
            clipBitmap = Bitmap.createBitmap(source, x, y, width, width);
        } else {
            clipBitmap = source;
        }

        Bitmap scaledBitmap = Bitmap.createScaledBitmap(clipBitmap, diameter, diameter, true);
        Bitmap outputBitmap = Bitmap.createBitmap(diameter, diameter, Config.ARGB_8888);
        Canvas canvas = new Canvas(outputBitmap);
        canvas.drawCircle(diameter / 2, diameter / 2, diameter / 2, paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(scaledBitmap, 0, 0, paint);
//        source.recycle();
        clipBitmap.recycle();
        scaledBitmap.recycle();
        return outputBitmap;
    }

    public void setText(String text) {
        mText = text;
    }

    public String getText() {
        return mText;
    }

    public void setTextColor(int textColor) {
        mTextPaint.setColor(textColor);
    }

    public void setCircleColor(int circleColor) {
        mCirclePaint.setColor(circleColor);
    }

    public void setBitmap(int id) {
        source = BitmapFactory.decodeResource(getResources(), id);
    }
}
时间: 2024-08-03 08:26:01

Android自定义View-圆形印章的相关文章

Android自定义View——圆形进度条式按钮

介绍 今天上班的时候有个哥们问我怎么去实现一个按钮式的进度条,先来看看他需要实现的效果图. 和普通的圆形进度条类似,只是中间的地方有两个状态表示,未开始,暂停状态.而且他说圆形进度的功能已经实现了.那么我们只需要对中间的两个状态做处理就行了. 先来看看实现的效果图: 上面说了我们只需要处理中间状态的变化就可以了,对于进度的处理直接使用了弘洋文章中实现: http://blog.csdn.net/lmj623565791/article/details/43371299 下面开始具体实现. 具体实

Android 自定义View合集

自定义控件学习 https://github.com/GcsSloop/AndroidNote/tree/master/CustomView 小良自定义控件合集 https://github.com/Mr-XiaoLiang 自定义控件三部曲 http://blog.csdn.net/harvic880925?viewmode=contents Android 从0开始自定义控件之View基础知识与概念 http://blog.csdn.net/airsaid/article/details/5

android自定义View之(六)------高仿华为荣耀3C的圆形刻度比例图(ShowPercentView)

为什么写这篇文章: 显示当前的容量所占的比例,表现当前计划的进度,一般都会采用百分比的方式,而图形显示,以其一目了然的直观性和赏心悦目的美观形成为了我们的当然的首选. 在图形表示百分比的方法中,我们有用画圆的圆形进度条的方法<<android自定义View之(二)------简单进度条显示样例篇>>,也有用画弧形的进度条的方法<<android自定义View之(三)------视频音量调控样例>>,今天看到华为荣耀3C的一个界面: 个人觉得这个表示比例的圆形

Android自定义View学习笔记04

Android自定义View学习笔记04 好长时间没有写相关的博客了,前几周在帮学姐做毕设,所以博客方面有些耽误.过程中写了一个类似wp的磁贴的view,想再写个配套的layout,所以昨天看了一下自定义viewGroup的相关知识-晚上睡觉想了一下可行性不是很高-代码量还不如直接自己在xml上写来得快,速度上也是个问题.今天看了一下张鸿洋老师的Android 自定义View (三) 圆环交替 等待效果这篇博文,再加上前一段时间看到的一幅图,结合之前写的一个圆形imageView的实现博文And

Android自定义View效果目录

1.绚丽的loading动效的实现 2.Android自定义View:进度条+冒泡文本 3.Android雷达图(蜘蛛网图) 4.Android文本闪烁 5.Android绘制圆形进度条 6.重写TextView,实现圆形背景,文本居中显示

Android 自定义View的一些总结

Android 自定义View的一些总结 Paint与Canvas 下面先说下Paint的基本设置函数: paint.setAntiAlias(true);//抗锯齿功能 paint.setColor(Color.RED); //设置画笔颜色 paint.setStyle(Style.FILL);//设置填充样式 paint.setStrokeWidth(30);//设置画笔宽度 paint.setShadowLayer(10, 15, 15, Color.GREEN);//设置阴影 (1)vo

Android自定义View探索(一)—生命周期

Activity代码: public class FiveActivity extends AppCompatActivity { private MyView myView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.e("log", "Activity生命周期:onCreate"); setConte

Android 自定义View视图

创建全新的视图将满足我们独特的UI需求. 本文介绍在指南针开发中会用到的罗盘的界面UI,通过继承View类实现的自定义视图,以此来深刻了解自定义视图. 实现效果图: 源代码: 布局文件activity_main(其中CompassView继承View类): <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.

android自定义View (一)MeasureSpec

A MeasureSpec encapsulates the layout requirements passed from parent to child. Each MeasureSpec represents a requirement for either the width or the height. A MeasureSpec is comprised of a size and a mode. There are three possible modes: UNSPECIFIED

(转)[原] Android 自定义View 密码框 例子

遵从准则 暴露您view中所有影响可见外观的属性或者行为. 通过XML添加和设置样式 通过元素的属性来控制其外观和行为,支持和重要事件交流的事件监听器 详细步骤见:Android 自定义View步骤 样子 支持的样式 可以通过XML定义影响外边和行为的属性如下 边框圆角值,边框颜色,分割线颜色,边框宽度,密码长度,密码大小,密码颜色 <declare-styleable name="PasswordInputView"> <attr name="border