android自定义view实现公章效果

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

上次去一个公司面试,面试官问了一个题,怎么用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*i/2), 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

目录
相关文章
|
26天前
|
数据可视化 Android开发 开发者
安卓应用开发中的自定义View组件
【10月更文挑战第5天】在安卓应用开发中,自定义View组件是提升用户交互体验的利器。本篇将深入探讨如何从零开始创建自定义View,包括设计理念、实现步骤以及性能优化技巧,帮助开发者打造流畅且富有创意的用户界面。
59 0
|
1天前
|
搜索推荐 前端开发 Android开发
安卓应用开发中的自定义视图实现
【10月更文挑战第30天】在安卓开发的海洋中,自定义视图是那抹不可或缺的亮色,它为应用界面的个性化和交互体验的提升提供了无限可能。本文将深入探讨如何在安卓平台创建自定义视图,并展示如何通过代码实现这一过程。我们将从基础出发,逐步引导你理解自定义视图的核心概念,然后通过一个实际的代码示例,详细讲解如何将理论应用于实践,最终实现一个美观且具有良好用户体验的自定义控件。无论你是想提高自己的开发技能,还是仅仅出于对安卓开发的兴趣,这篇文章都将为你提供价值。
|
3天前
|
Android开发 开发者 UED
安卓开发中自定义View的实现与性能优化
【10月更文挑战第28天】在安卓开发领域,自定义View是提升应用界面独特性和用户体验的重要手段。本文将深入探讨如何高效地创建和管理自定义View,以及如何通过代码和性能调优来确保流畅的交互体验。我们将一起学习自定义View的生命周期、绘图基础和事件处理,进而探索内存和布局优化技巧,最终实现既美观又高效的安卓界面。
14 5
|
10天前
|
缓存 数据处理 Android开发
在 Android 中使用 RxJava 更新 View
【10月更文挑战第20天】使用 RxJava 来更新 View 可以提供更优雅、更高效的解决方案。通过合理地运用操作符和订阅机制,我们能够轻松地处理异步数据并在主线程中进行 View 的更新。在实际应用中,需要根据具体情况进行灵活运用,并注意相关的注意事项和性能优化,以确保应用的稳定性和流畅性。可以通过不断的实践和探索,进一步掌握在 Android 中使用 RxJava 更新 View 的技巧和方法,为开发高质量的 Android 应用提供有力支持。
|
10天前
|
缓存 调度 Android开发
Android 在子线程更新 View
【10月更文挑战第21天】在 Android 开发中,虽然不能直接在子线程更新 View,但通过使用 Handler、AsyncTask 或 RxJava 等方法,可以实现子线程操作并在主线程更新 View 的目的。在实际应用中,需要根据具体情况选择合适的方法,并注意相关的注意事项和性能优化,以确保应用的稳定性和流畅性。可以通过不断的实践和探索,进一步掌握在子线程更新 View 的技巧和方法,为开发高质量的 Android 应用提供支持。
16 2
|
11天前
|
XML 前端开发 Android开发
Android面试高频知识点(3) 详解Android View的绘制流程
Android面试高频知识点(3) 详解Android View的绘制流程
Android面试高频知识点(3) 详解Android View的绘制流程
|
15天前
|
XML 前端开发 Android开发
Android面试高频知识点(3) 详解Android View的绘制流程
Android面试高频知识点(3) 详解Android View的绘制流程
19 2
|
27天前
|
XML 前端开发 Android开发
Android View的绘制流程和原理详细解说
Android View的绘制流程和原理详细解说
32 3
|
3月前
|
XML 前端开发 Android开发
Android面试高频知识点(3) 详解Android View的绘制流程
View的绘制和事件处理是两个重要的主题,上一篇《图解 Android事件分发机制》已经把事件的分发机制讲得比较详细了,这一篇是针对View的绘制,View的绘制如果你有所了解,基本分为measure、layout、draw 过程,其中比较难理解就是measure过程,所以本篇文章大幅笔地分析measure过程,相对讲得比较详细,文章也比较长,如果你对View的绘制还不是很懂,对measure过程掌握得不是很深刻,那么耐心点,看完这篇文章,相信你会有所收获的。
107 3
|
4月前
|
消息中间件 前端开发 Android开发
Android面试题自定义View之Window、ViewRootImpl和View的三大流程
Android开发中,View的三大核心流程包括measure(测量)、layout(布局)和draw(绘制)。MeasureSpec类在测量过程中起到关键作用,它结合尺寸大小和模式(EXACTLY、AT_MOST、UNSPECIFIED)来指定View应如何测量。onMeasure方法用于自定义View的测量,布局阶段,ViewGroup调用onLayout确定子元素位置,而draw阶段按照特定顺序绘制背景、内容、子元素和装饰。整个流程始于ViewRootImpl的performTraversals,该方法触发测量、布局和绘制。
107 0