Android打造带透明圆弧的ImageView

摘要:
同时因为要保证圆弧的位置可以任意摆放,圆弧的颜色、透明度以及文字大小、颜色等都是可控的,所以增加了一些自定义属性。

这几天因为项目需求,需要在ImageView上面叠加一层透明圆弧,并且在沿着圆弧的方向显示相应的文字,效果如下图所示:

Android打造带透明圆弧的ImageView第1张

拿到这个需求,首先想到的是自定义一个ImageView来实现此功能,即在onDraw()中绘制圆弧和文字。同时因为要保证圆弧的位置可以任意摆放,圆弧的颜色、透明度以及文字大小、颜色等都是可控的,所以增加了一些自定义属性。实现代码非常简单,如下:

1.自定义ImageView:

1 packagecom.chunk.customviewsdemo.views.ArcImageView;
2 
3 importandroid.content.Context;
4 importandroid.content.res.TypedArray;
5 importandroid.graphics.Canvas;
6 importandroid.graphics.Paint;
7 importandroid.graphics.Path;
8 importandroid.graphics.RectF;
9 importandroid.util.AttributeSet;
10 importandroid.widget.ImageView;
11 
12 importcom.chunk.customviewsdemo.R;
13 
14 /**
15 * Description:A custom ImageView with circular arc and text
16 * Author: XiaoYu
17 * Date: 2016/5/10 13:55
18  */
19 public class ArcImageView extendsImageView {
20     /**
21 * The default text size.
22      */
23     private final float DEFAULT_TEXT_SIZE = 20;
24     /**
25 * The default scale value which decides the width of arc.
26      */
27     private final float DEFAULT_SCALE = 0.5f;
28     /**
29 * The default transparency of arc.
30      */
31     private final int DEFAULT_ARC_ALPHA =100;
32     /**
33 * The default width of arc.
34      */
35     private final int DEFAULT_ARC_WIDTH =160;
36     /**
37 * The default angle that the arc starts with.
38      */
39     private final int DEFAULT_START_ANGLE = 180;
40     /**
41 * The default angle that the arc.
42      */
43     private final int DEFAULT_SWEEP_ANGLE = 90;
44     /**
45 * The default distance along the path to add to the text's starting position.
46      */
47     private final int DEFAULT_H_OFFSET = 100;
48     /**
49 * The default distance above(-) or below(+) the path to position the text.
50      */
51     private final int DEFAULT_V_OFFSET = 20;
52     privateContext mContext;
53     /**
54 * The text displayed on ImageView along arc.
55      */
56     privateString mDrawStr;
57     /**
58 * The font size of text.
59      */
60     private float mTextSize =DEFAULT_TEXT_SIZE;
61     /**
62 * The scale value which decides the width of arc.
63      */
64     private float mScale =DEFAULT_SCALE;
65     /**
66 * The transparency of arc.
67      */
68     private int mArcAlpha =DEFAULT_ARC_ALPHA;
69     /**
70 * The width of arc.
71      */
72     private int mArcWidth =DEFAULT_ARC_WIDTH;
73     /**
74 * The start angle of angle.
75      */
76     private int mStartAngle =DEFAULT_START_ANGLE;
77     /**
78 * The swept angle of angle.
79      */
80     private int mSweepAngle =DEFAULT_SWEEP_ANGLE;
81     /**
82 * The default distance along the path to add to the text's starting position.
83      */
84     private float mHOffset =DEFAULT_H_OFFSET;
85     /**
86 * The default distance above(-) or below(+) the path to position the text.
87      */
88     private float mVOffset =DEFAULT_V_OFFSET;
89     /**
90 * The style of arc, all styles includes LEFT_TOP, LEFT_BOTTOM, RIGHT_TOP, RIGHT_BOTTOM, CENTER。
91 * of course, you can add your own style according to your demands.
92      */
93     private intmDrawStyle;
94     /**
95 * The color of arc.
96      */
97     private intmArcColor;
98     /**
99 * The color of text.
100      */
101     private intmTextColor;
102 
103     publicArcImageView(Context context) {
104         super(context);
105         this.mContext =context;
106 }
107 
108     publicArcImageView(Context context, AttributeSet attrs) {
109         super(context, attrs);
110         this.mContext =context;
111 obtainAttributes(attrs);
112 }
113 
114     public ArcImageView(Context context, AttributeSet attrs, intdefStyleAttr) {
115         super(context, attrs, defStyleAttr);
116         this.mContext =context;
117 obtainAttributes(attrs);
118 }
119 
120     /**
121 * Set the text that will be drawn on arc.
122 * @paramdrawStr the text content.
123      */
124     public voidsetDrawStr(String drawStr) {
125         this.mDrawStr =drawStr;
126         //refresh this view
127 invalidate();
128 }
129 
130     /**
131 * Set the transparency of arc.
132 * @parammArcAlpha the value of transparency.
133      */
134     public void setArcAlpha(intmArcAlpha) {
135         this.mArcAlpha =mArcAlpha;
136         //refresh this view
137 invalidate();
138 }
139 
140 @Override
141     protected voidonDraw(Canvas canvas) {
142         super.onDraw(canvas);
143         //draw arc
144         Paint arcPaint = newPaint();
145 arcPaint.setStrokeWidth(mArcWidth);
146 arcPaint.setStyle(Paint.Style.STROKE);
147 arcPaint.setColor(mArcColor);
148 arcPaint.setAlpha(mArcAlpha);
149         int width =getWidth();
150         int height =getHeight();
151         floatradius;
152         if (width >height) {
153             radius = mScale *height;
154         } else{
155             radius = mScale *width;
156 }
157         RectF oval = newRectF();
158 
159         int center_x =width;
160         int center_y =height;
161 
162         switch(mDrawStyle) {
163             case 0:
164                 center_x = 0;
165                 center_y = 0;
166                 mStartAngle = 90;
167                 mSweepAngle = -90;
168                 break;
169             case 1:
170                 center_x = 0;
171                 center_y =height;
172                 mStartAngle = 270;
173                 mSweepAngle = 90;
174                 break;
175             case 2:
176                 center_x =width;
177                 center_y = 0;
178                 mStartAngle = 180;
179                 mSweepAngle = -90;
180                 break;
181             case 3:
182                 center_x =width;
183                 center_y =height;
184                 mStartAngle = 180;
185                 mSweepAngle = 90;
186                 break;
187             case 4:
188                 center_x = width / 2;
189                 center_y = height / 2;
190                 mStartAngle = 270;
191                 mSweepAngle = 90;
192                 break;
193 }
194         float left = center_x -radius;
195         float top = center_y -radius;
196         float right = center_x +radius;
197         float bottom = center_y +radius;
198 oval.set(left, top, right, bottom);
199         canvas.drawArc(oval, mStartAngle, mSweepAngle, false, arcPaint);
200 
201         //draw text
202         Paint textPaint = newPaint();
203 textPaint.setTextSize(mTextSize);
204 textPaint.setStyle(Paint.Style.FILL);
205 textPaint.setColor(mTextColor);
206         Path path = newPath();
207 path.addArc(oval, mStartAngle, mSweepAngle);
208 canvas.drawTextOnPath(mDrawStr, path, mHOffset, mVOffset, textPaint);
209 }
210 
211     /**
212 * Obtain custom attributes that been defined in attrs.xml.
213 * @paramattrs A collection of attributes.
214      */
215     private voidobtainAttributes(AttributeSet attrs) {
216         TypedArray ta =mContext.obtainStyledAttributes(attrs, R.styleable.ArcImageView);
217         mDrawStr =ta.getString(R.styleable.ArcImageView_drawStr);
218         mTextSize =ta.getDimension(R.styleable.ArcImageView_textSize, DEFAULT_TEXT_SIZE);
219         mArcAlpha =ta.getInteger(R.styleable.ArcImageView_arcAlpha, DEFAULT_ARC_ALPHA);
220         mArcWidth =ta.getInteger(R.styleable.ArcImageView_arcWidth, DEFAULT_ARC_WIDTH);
221         mStartAngle =ta.getInteger(R.styleable.ArcImageView_startAngle, DEFAULT_START_ANGLE);
222         mSweepAngle =ta.getInteger(R.styleable.ArcImageView_startAngle, DEFAULT_SWEEP_ANGLE);
223         mHOffset =ta.getInteger(R.styleable.ArcImageView_hOffset, DEFAULT_H_OFFSET);
224         mVOffset =ta.getInteger(R.styleable.ArcImageView_vOffset, DEFAULT_V_OFFSET);
225         mArcColor = ta.getColor(R.styleable.ArcImageView_arcColor, 0XCCCCCC);
226         mTextColor = ta.getColor(R.styleable.ArcImageView_textColor, 0XFFFFFF);
227         mDrawStyle = ta.getInt(R.styleable.ArcImageView_drawStyle, 0);
228 ta.recycle();
229 }
230 }

2.在values文件夹下的attrs.xml中自定义属性:

1 <?xml version="1.0" encoding="utf-8"?>
2 <resources>
3     <declare-styleable name="ArcImageView">
4         <attr name="drawStr"format="string" />
5         <attr name="textSize"format="dimension" />
6         <attr name="arcAlpha"format="integer" />
7         <attr name="arcWidth"format="integer" />
8         <attr name="startAngle"format="integer" />
9         <attr name="sweepAngle"format="integer" />
10         <attr name="scale"format="float" />
11         <attr name="hOffset"format="float" />
12         <attr name="vOffset"format="float" />
13         <attr name="drawStyle"format="enum">
14             <enum name="LEFT_TOP"value="0" />
15             <enum name="LEFT_BOTTOM"value="1" />
16             <enum name="RIGHT_TOP"value="2" />
17             <enum name="RIGHT_BOTTOM"value="3" />
18             <enum name="CENTER"value="4" />
19         </attr>
20         <attr name="arcColor"format="color" />
21         <attr name="textColor"format="color" />
22     </declare-styleable>
23 </resources>

3.在MainActivity调用ArcImageView,实现代码如下:

1 packagecom.chunk.customviewsdemo;
2 
3 importandroid.os.Bundle;
4 importandroid.support.v7.app.AppCompatActivity;
5 importandroid.view.View;
6 importandroid.widget.Button;
7 
8 importcom.chunk.customviewsdemo.views.ArcImageView.ArcImageView;
9 
10 public class MainActivity extends AppCompatActivity implementsView.OnClickListener {
11     privateArcImageView aiv_one;
12     privateArcImageView aiv_two;
13     privateArcImageView aiv_three;
14     privateArcImageView aiv_four;
15     privateButton btn_another_one;
16     private int mGroup = 1;
17 
18 @Override
19     protected voidonCreate(Bundle savedInstanceState) {
20         super.onCreate(savedInstanceState);
21 setContentView(R.layout.activity_main);
22         aiv_one =(ArcImageView) findViewById(R.id.aiv_one);
23         aiv_one.setArcAlpha(180);
24         aiv_two =(ArcImageView) findViewById(R.id.aiv_two);
25         aiv_two.setArcAlpha(180);
26         aiv_three =(ArcImageView) findViewById(R.id.aiv_three);
27         aiv_three.setArcAlpha(180);
28         aiv_four =(ArcImageView) findViewById(R.id.aiv_four);
29         aiv_four.setArcAlpha(180);
30         btn_another_one =(Button) findViewById(R.id.btn_another_one);
31         btn_another_one.setOnClickListener(this);
32 }
33 
34 @Override
35     public voidonClick(View v) {
36         switch(v.getId()) {
37             caseR.id.btn_another_one:
38                 if (mGroup == 1) {
39                     aiv_one.setDrawStr("苹果");
40 aiv_one.setBackgroundResource(R.drawable.apple);
41                     aiv_two.setDrawStr("柚子");
42 aiv_two.setBackgroundResource(R.drawable.pineapple);
43                     aiv_three.setDrawStr("香蕉");
44 aiv_three.setBackgroundResource(R.drawable.banana);
45                     aiv_four.setDrawStr("菠萝");
46 aiv_four.setBackgroundResource(R.drawable.pineapple);
47                     mGroup = 2;
48                 } else{
49                     aiv_one.setDrawStr("牛排");
50 aiv_one.setBackgroundResource(R.drawable.steak);
51                     aiv_two.setDrawStr("海鲜");
52 aiv_two.setBackgroundResource(R.drawable.seafood);
53                     aiv_three.setDrawStr("奶酪");
54 aiv_three.setBackgroundResource(R.drawable.cheese);
55                     aiv_four.setDrawStr("烧烤");
56 aiv_four.setBackgroundResource(R.drawable.barbecue);
57                     mGroup = 1;
58 }
59                 break;
60 }
61 }
62 }

4.MainActivity的布局文件如下:

1 <LinearLayout
2     xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:custom="http://schemas.android.com/apk/res-auto"
4 android:layout_width="match_parent"
5 android:layout_height="match_parent"
6 android:layout_marginTop="100dp"
7 android:layout_marginBottom="100dp"
8 android:orientation="vertical" >
9 
10     <Button
11         android:id="@+id/btn_another_one"
12 android:layout_width="wrap_content"
13 android:layout_height="wrap_content"
14 android:text="换一组" />
15 
16     <LinearLayout
17         android:layout_width="match_parent"
18 android:layout_height="0dp"
19 android:layout_weight="1"
20 android:orientation="horizontal" >
21 
22         <RelativeLayout
23             android:layout_width="0dp"
24 android:layout_weight="1"
25 android:layout_height="match_parent" >
26 
27             <com.chunk.customviewsdemo.views.ArcImageView.ArcImageView
28                 android:id="@+id/aiv_one"
29 android:layout_width="match_parent"
30 android:layout_height="match_parent"
31 android:background="@drawable/steak"
32 custom:drawStyle="RIGHT_BOTTOM"
33 custom:drawStr="牛排"
34 custom:arcAlpha="100"
35 custom:arcColor="@color/gray"
36 custom:textColor="@color/black"
37 custom:textSize="20sp" />
38         </RelativeLayout>
39 
40         <RelativeLayout
41             android:layout_width="0dp"
42 android:layout_weight="1"
43 android:layout_height="match_parent" >
44 
45             <com.chunk.customviewsdemo.views.ArcImageView.ArcImageView
46                 android:id="@+id/aiv_two"
47 android:layout_width="match_parent"
48 android:layout_height="match_parent"
49 android:background="@drawable/seafood"
50 custom:drawStyle="LEFT_BOTTOM"
51 custom:drawStr="海鲜"
52 custom:arcAlpha="100"
53 custom:arcColor="@color/gray"
54 custom:textColor="@color/black"
55 custom:textSize="20sp" />
56 
57         </RelativeLayout>
58     </LinearLayout>
59 
60     <LinearLayout
61         android:layout_width="match_parent"
62 android:layout_height="0dp"
63 android:layout_weight="1"
64 android:orientation="horizontal" >
65 
66         <RelativeLayout
67             android:layout_width="0dp"
68 android:layout_weight="1"
69 android:layout_height="match_parent" >
70 
71             <com.chunk.customviewsdemo.views.ArcImageView.ArcImageView
72                 android:id="@+id/aiv_three"
73 android:layout_width="match_parent"
74 android:layout_height="match_parent"
75 android:background="@drawable/cheese"
76 custom:drawStyle="RIGHT_TOP"
77 custom:drawStr="奶酪"
78 custom:arcAlpha="100"
79 custom:arcColor="@color/gray"
80 custom:textColor="@color/black"
81 custom:textSize="20sp" />
82         </RelativeLayout>
83 
84         <RelativeLayout
85             android:layout_width="0dp"
86 android:layout_weight="1"
87 android:layout_height="match_parent" >
88 
89             <com.chunk.customviewsdemo.views.ArcImageView.ArcImageView
90                 android:id="@+id/aiv_four"
91 android:layout_width="match_parent"
92 android:layout_height="match_parent"
93 android:background="@drawable/barbecue"
94 custom:drawStyle="LEFT_TOP"
95 custom:drawStr="烧烤"
96 custom:arcAlpha="100"
97 custom:arcColor="@color/gray"
98 custom:textColor="@color/black"
99 custom:textSize="20sp" />
100 
101         </RelativeLayout>
102     </LinearLayout>
103 </LinearLayout>

注意,在布局文件中引入自定义属性时需要加入一行代码:xmlns:custom="http://schemas.android.com/apk/res-auto"。

好了,需求搞定,剩下的就是搬到实际的项目当中去了。实现效果如下:

Android打造带透明圆弧的ImageView第2张

总结一下,自定义View一般就是通过重写onDraw、onMeasure()、onLayout()等方法来进行测量、绘制,绘制的时候一般会用到Canvas、Paint、Bitmap等类,测量和绘制的过程其实就是对现实生活中绘图工作的抽象和实现,我们利用面向对象的思想将画板、画纸、画笔等工具以及绘画的动作用一行行代码加以描述就OK啦!

由于实现过程比较简单,我就不贴源码了,大家如果对2D绘图还不是很了解,可以去搜一下相关资料或查阅相关书籍!

免责声明:文章转载自《Android打造带透明圆弧的ImageView》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇【07】覆盖物(百度地图覆盖物笔记)转 mysql mysql命令行中执行sql的几种方式总结下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

MongoDB 高级查询_aggregate聚合管道

MongoDB 聚合管道(AggregationPipeline) 使用聚合管道可以对集合中的文档进行变换和组合。实际项目应用主要是表关联查询、数据的统计。 MongoDB 中使用 db.COLLECTION_NAME.aggregate([{<stage>},...]) 方法 来构建和使用聚合管道。下面是官网给的实例,感受一下聚合管道的用法。...

re库的使用

一、re库的调用 import re 二、正则表达式类型 raw string类型(原生字符串类型,即不包括转义符类型):r'text' string类型,更繁琐。 三、Re库主要功能函数 函数              说明 re.search()        在一个字符串中搜索匹配正则表达式的第一个位置,然后返回match对象 re.match(...

Android之静态和动态加载Fragment

一、fragment的静态加载和动态加载的理解: 我觉得可以把fragment当做为一个自定义的布局,然后去使用这个定义好的布局,对于静态和动态的理解是,静态是讲在主布局文件中放入fragment布局,然后使用,而动态是不需要在主布局文件中去声明fragment的,而是直接在java代码中去添加。 二、通过一个例子来理解: 说明下下面的图:第一个为主界面,...

andoird软件开发之一个记录账号密码的APP--bmob后台

1.app功能:通过注册登录账户,拥有一个账户本,能够将平时自己容易的忘记的账户记录下来,并可以保持到云端,不需要担心数据丢失,只要登录账户,便可获取到自己的账户本。 2.实现的效果图,如下: 以下界面分别为注册界面、登录界面、提交账户内容界面、账户列表界面、长按删除账户信息、具体账户内容信息 3.实现的工程目录如下: 4.实现的具体过程: a.布局...

天气预报APP(2)

之前实现了能够罗列可以罗列出全国所有的省、市、县,然后就是查询全国任意城市的天气信息。查询天气信息使用的是和风天气的api,这个api获得的天气信息是JSON格式的。 使用GSON库解析JSON数据的第一步要先定义用于映照的类。 我对官方实例做了一下删减,然后可以看到这次我想要展示在这次这个项目中的信息: { "HeWeather5": [...

ets学习

http://diaocow.iteye.com/blog/1768647 http://www.cnblogs.com/me-sa/archive/2011/08/11/erlang0007.html ets是什么? ets是Erlang Term Storage的缩写,它是一个基于内存的KV Table,支持大数据量存储以及高效查询. ets有4种类型...