上次去一个公司面试,面试官问了一个题,怎么用android的自定义view实现一个公章的效果,据说这是华为之前的面试题,我想了下,要是公章的效果,最外层是一个圆,里面是一个五角星,但是这文字怎么画呢,比较难搞,后来回来看了下java的api,发现人家的Path里面本来就提供了这么一个方法:

public void addArc(RectF oval, float startAngle, float sweepAngle) {
    addArc(oval.left, oval.top, oval.right, oval.bottom, startAngle, sweepAngle);
}

然后人家解释说了,根据狐线的角度生成相应的路径,所以我们就可以给文字设置一个相应绘制区域,使其绘制的文字都在这个区域内,

path.addArc(oval,-(firstrad-), textPadding);
接下来我们只需要在这个区域内把文字绘制上去就行了。
好的,下面是全部代码:

首先继承自View,我们在构造里面初始化,同样为了方便程序的扩展性,我们用自定义属性,
<declare-styleable name="Seal">
    <attr name="scale_text_size" format="dimension" />
    <attr name="scale_text_color" format="color" />
    <attr name="scale_text" format="string" />
    <attr name="scale_text_padding" format="float" />
    <attr name="circle_stroke_width" format="dimension" />
    <attr name="circle_color" format="color" />
    <attr name="circle_radius" format="dimension" />
</declare-styleable>

然后我们初始化的时候主要初始化文字,文字大小,文字间距,文字颜色等等,
private void initViews(AttributeSet attrs, int defStyle) {
    TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.Seal, defStyle, 0);
    circleText = typedArray.getString(R.styleable.Seal_scale_text);
    textSize = typedArray.getDimension(R.styleable.Seal_scale_text_size, 20);
    scaleTextColor = typedArray.getColor(R.styleable.Seal_scale_text_color, getResources().getColor(R.color.c9));
    textPadding=typedArray.getFloat(R.styleable.Seal_scale_text_padding,50);
    circleStrokeWidth = typedArray.getDimensionPixelSize(R.styleable.Seal_circle_stroke_width, 3);
    circleColor = typedArray.getColor(R.styleable.Seal_circle_color, getResources().getColor(R.color.c9));
    circleRadius = typedArray.getDimensionPixelSize(R.styleable.Seal_circle_radius, 7);
    typedArray.recycle();
}

接下来我们在重写Ondraww(Canvas canvas)

@Override
protected void onDraw(Canvas rootCanvas) {
    super.onDraw(rootCanvas);
    Bitmap image = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(image);
    Paint paint=new Paint();

    drawRing(canvas,paint);
    drawStar(canvas);
    drawText(canvas);
    rootCanvas.drawBitmap(image, 0, 0, null);
}

接下来是对应的三个方法:画圆环(ring),五角星(star),文字(text)
//圆环
private void drawRing(Canvas canvas, Paint paint) {
    centre = canvas.getWidth() / 2; // 获取圆心的x坐标
    radius = (int) (centre - circleStrokeWidth / 2); // 圆环的半径
    paint.setColor(Color.RED); // 设置圆环的颜色
    paint.setStyle(Paint.Style.STROKE); // 设置空心
    paint.setStrokeWidth(circleStrokeWidth); // 设置圆环的宽度
    paint.setAntiAlias(true); // 消除锯齿
    canvas.drawCircle(centre, centre, radius, paint); // 画出圆环
}

//绘制五角星

private void drawStar(Canvas canvas){
    float start_radius = (float) ((radius / 2)*1.1);
    int x = centre, y = centre;
    float x1,y1,x2,y2,x3,y3,x4,y4,x5,y5;
    float r72 = (float) Math.toRadians(72);
    float r36 = (float) Math.toRadians(36);
    //顶点
    x1 = x;
    y1 = y - start_radius;
    //左1
    x2 = (float) (x - start_radius*Math.sin(r72));
    y2 = (float) (y - start_radius*Math.cos(r72));
    //右1
    x3 = (float) (x + start_radius*Math.sin(r72));
    y3 = (float) (y - start_radius*Math.cos(r72));
    //左2
    x4 = (float) (x - start_radius*Math.sin(r36));
    y4 = (float) (y + start_radius*Math.cos(r36));
    //右2
    x5 = (float) (x + start_radius*Math.sin(r36));
    y5 = (float) (y + start_radius*Math.cos(r36));

    //连接各个节点,绘制五角星
    Path path = new Path();
    path.moveTo(x1, y1);
    path.lineTo(x5, y5);
    path.lineTo(x2, y2);
    path.lineTo(x3, y3);
    path.lineTo(x4, y4);
    path.close();

    Paint paint = new Paint();
    paint.setColor(Color.RED);

    canvas.drawPath(path, paint);
}

//文字

private void drawText(Canvas canvas){
    Paint paint = new Paint();
    paint.setColor(Color.RED);
    paint.setTypeface(Typeface.DEFAULT_BOLD);
    paint.setTextAlign(Paint.Align.CENTER);
    paint.setTextSize(radius/5+5);
    //圆弧文字所在矩形范围
    RectF oval=new RectF(0, 0, 2*radius, (float) (2*radius));
    //第一个文字偏移角度,其中padding/2为文字间距
    float firstrad = 90 + textPadding * (circleText.length()) / 4 - textPadding/8;
    for(int i = 0; i < circleText.length(); i++){
        Path path = new Path();
        //根据角度生成弧线路径
        path.addArc(oval,-(firstrad-textPadding*i/2), textPadding);
        canvas.drawTextOnPath(String.valueOf(circleText.charAt(i)), path, -(float) (radius/3),(float) (radius/3), paint);
    }
}

最后在我们需要的视图中引用下就好了

<com.xzh.sealmaster.view.SealView
    android:layout_width="200dp"
    android:layout_height="200dp"
    android:layout_gravity="center"
    app:scale_text_size="16sp"
    app:scale_text_padding="50"
    app:scale_text="华为上海有限公司"
    />

有需要源码的,请到下面地址下载:http://download.csdn.net/detail/xiangzhihong8/9479372

好的,就是这么简单,有任何疑问的请加我们的技术群278792776或者188716429

android自定义view实现公章效果的更多相关文章

  1. Android 自定义View跑马灯效果(一)

    今天通过书籍重新复习了一遍自定义VIew,为了加强自己的学习,我把它写在博客里面,有兴趣的可以看一下,相互学习共同进步: 通过自定义一个跑马灯效果,来诠释一下简单的效果: 一.创建一个类继承View, ...

  2. android 自定义view之侧滑效果

    效果图: 看网上的都是两个view拼接,默认右侧的不显示,水平移动的时候把右侧的view显示出来.但是看最新版QQ上的效果不是这样的,但给人的感觉却很好,所以献丑来一发比较高仿的. 知识点: 1.Vi ...

  3. Android自定义View 画弧形,文字,并增加动画效果

    一个简单的Android自定义View的demo,画弧形,文字,开启一个多线程更新ui界面,在子线程更新ui是不允许的,但是View提供了方法,让我们来了解下吧. 1.封装一个抽象的View类   B ...

  4. Android自定义View(LimitScrollerView-仿天猫广告栏上下滚动效果)

    转载请标明出处: http://blog.csdn.net/xmxkf/article/details/53303872 本文出自:[openXu的博客] 1分析 2定义组合控件布局 3继承最外层控件 ...

  5. Android 自定义View合集

    自定义控件学习 https://github.com/GcsSloop/AndroidNote/tree/master/CustomView 小良自定义控件合集 https://github.com/ ...

  6. Android 自定义 view(三)—— onDraw 方法理解

    前言: 上一篇已经介绍了用自己定义的属性怎么简单定义一个view<Android 自定义view(二) -- attr 使用>,那么接下来我们继续深究自定义view,下一步将要去简单理解自 ...

  7. Android 自定义view(二) —— attr 使用

    前言: attr 在前一篇文章<Android 自定义view -- attr理解>已经简单的进行了介绍和创建,那么这篇文章就来一步步说说attr的简单使用吧 自定义view简单实现步骤 ...

  8. Android 自定义View及其在布局文件中的使用示例(二)

    转载请注明出处 http://www.cnblogs.com/crashmaker/p/3530213.html From crash_coder linguowu linguowu0622@gami ...

  9. Android自定义View

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/24252901 很多的Android入门程序猿来说对于Android自定义View ...

随机推荐

  1. Java HashMap并发死循环

    在淘宝内网里看到同事发了贴说了一个CPU被100%的线上故障,并且这个事发生了很多次,原因是在Java语言在并发情况下使用HashMap造成Race Condition,从而导致死循环.这个事情我4. ...

  2. 6.QT信号和槽

     新建项目SignalAndSlot项目 编写代码如下: mysignal.h #ifndef MYSIGNAL_H #define MYSIGNAL_H   #include <QObje ...

  3. Android View框架总结(六)View布局流程之Draw过程

    请尊重分享成果,转载请注明出处: http://blog.csdn.net/hejjunlin/article/details/52236145 View的Draw时序图 ViewRootImpl.p ...

  4. Jetty 嵌入式启动官方完整教程

    网上太多了,不如直接看官方的这个全面. http://wiki.eclipse.org/Jetty/Tutorial/Embedding_Jetty 入门地址: http://wiki.eclipse ...

  5. Linux系统调用的实现机制分析

    API/POSIX/C库的关系        系统调用的实现 3.1    系统调用处理程序 添加新系统调用 给Linux添加一个新的系统调用是件相对容易的工作.怎样设计和实现一个系统调用是难题所在, ...

  6. shell脚本实现冒泡排序

    手动输入一行字符串,并对其排序. 脚本如下: #!/bin/bash #a test about sort echo "please input a number list" re ...

  7. Linux上程序调试的基石(2)--GDB

    3. GDB的实现 GDB是GNU发布的一个强大的程序调试工具,用以调试C/C++程序.可以使程序员在程序运行的时候观察程序在内存/寄存器中的使用情况.它的实现也是基于ptrace系统调用来完成的.  ...

  8. Ubuntu 12.04: How to enable root login

    1. vi /etc/lightdm/lightdm.conf and add following modifications. greeter-show-manual-login=true allo ...

  9. 《java入门第一季》之HashSet小案例:获取10个1至20的随机数,要求随机数不能重复

    这是基于HashSet集合的唯一性. /*  * 编写一个程序,获取10个1至20的随机数,要求随机数不能重复.  *   * 分析:  * A:创建随机数对象  * B:创建一个HashSet集合 ...

  10. iOS平台添加Google Admob -1/2(Unity3D开发之七)

    猴子原创,欢迎转载.转载请注明: 转载自Cocos2D开发网–Cocos2Dev.com,谢谢! 原文地址: http://www.cocos2dev.com/?p=567 Unity调用iOS还是非 ...