欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android使用ImageView 制作透明圆弧实例代码

程序员文章站 2024-03-02 17:18:16
这几天因为项目需求,需要在imageview上面叠加一层透明圆弧,并且在沿着圆弧的方向显示相应的文字,效果如下图所示:   拿到这个需求,首先想到的是自定义一...

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

Android使用ImageView 制作透明圆弧实例代码

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

1.自定义imageview:

package com.chunk.customviewsdemo.views.arcimageview;
import android.content.context;
import android.content.res.typedarray;
import android.graphics.canvas;
import android.graphics.paint;
import android.graphics.path;
import android.graphics.rectf;
import android.util.attributeset;
import android.widget.imageview;
import com.chunk.customviewsdemo.r;
/**
* description:a custom imageview with circular arc and text
* author: xiaoyu
* date: // :
*/
public class arcimageview extends imageview {
/**
* the default text size.
*/
private final float default_text_size = ;
/**
* the default scale value which decides the width of arc.
*/
private final float default_scale = .f;
/**
* the default transparency of arc.
*/
private final int default_arc_alpha =;
/**
* the default width of arc.
*/
private final int default_arc_width =;
/**
* the default angle that the arc starts with.
*/
private final int default_start_angle = ;
/**
* the default angle that the arc.
*/
private final int default_sweep_angle = ;
/**
* the default distance along the path to add to the text's starting position.
*/
private final int default_h_offset = ;
/**
* the default distance above(-) or below(+) the path to position the text.
*/
private final int default_v_offset = ;
private context mcontext;
/**
* the text displayed on imageview along arc.
*/
private string mdrawstr;
/**
* the font size of text.
*/
private float mtextsize = default_text_size;
/**
* the scale value which decides the width of arc.
*/
private float mscale = default_scale;
/**
* the transparency of arc.
*/
private int marcalpha = default_arc_alpha;
/**
* the width of arc.
*/
private int marcwidth = default_arc_width;
/**
* the start angle of angle.
*/
private int mstartangle = default_start_angle;
/**
* the swept angle of angle.
*/
private int msweepangle = default_sweep_angle;
/**
* the default distance along the path to add to the text's starting position.
*/
private float mhoffset = default_h_offset;
/**
* the default distance above(-) or below(+) the path to position the text.
*/
private float mvoffset = default_v_offset;
/**
* the style of arc, all styles includes left_top, left_bottom, right_top, right_bottom, center。
* of course, you can add your own style according to your demands.
*/
private int mdrawstyle;
/**
* the color of arc.
*/
private int marccolor;
/**
* the color of text.
*/
private int mtextcolor;
public arcimageview(context context) {
super(context);
this.mcontext = context;
}
public arcimageview(context context, attributeset attrs) {
super(context, attrs);
this.mcontext = context;
obtainattributes(attrs);
}
public arcimageview(context context, attributeset attrs, int defstyleattr) {
super(context, attrs, defstyleattr);
this.mcontext = context;
obtainattributes(attrs);
}
/**
* set the text that will be drawn on arc.
* @param drawstr the text content.
*/
public void setdrawstr(string drawstr) {
this.mdrawstr = drawstr;
//refresh this view
invalidate();
}
/**
* set the transparency of arc.
* @param marcalpha the value of transparency.
*/
public void setarcalpha(int marcalpha) {
this.marcalpha = marcalpha;
//refresh this view
invalidate();
}
@override
protected void ondraw(canvas canvas) {
super.ondraw(canvas);
//draw arc
paint arcpaint = new paint();
arcpaint.setstrokewidth(marcwidth);
arcpaint.setstyle(paint.style.stroke);
arcpaint.setcolor(marccolor);
arcpaint.setalpha(marcalpha);
int width = getwidth();
int height = getheight();
float radius;
if (width > height) {
radius = mscale * height;
} else {
radius = mscale * width;
}
rectf oval = new rectf();
int center_x = width;
int center_y = height;
switch (mdrawstyle) {
case :
center_x = ;
center_y = ;
mstartangle = ;
msweepangle = -;
break;
case :
center_x = ;
center_y = height;
mstartangle = ;
msweepangle = ;
break;
case :
center_x = width;
center_y = ;
mstartangle = ;
msweepangle = -;
break;
case :
center_x = width;
center_y = height;
mstartangle = ;
msweepangle = ;
break;
case :
center_x = width / ;
center_y = height / ;
mstartangle = ;
msweepangle = ;
break;
}
float left = center_x - radius;
float top = center_y - radius;
float right = center_x + radius;
float bottom = center_y + radius;
oval.set(left, top, right, bottom);
canvas.drawarc(oval, mstartangle, msweepangle, false, arcpaint);
//draw text
paint textpaint = new paint();
textpaint.settextsize(mtextsize);
textpaint.setstyle(paint.style.fill);
textpaint.setcolor(mtextcolor);
path path = new path();
path.addarc(oval, mstartangle, msweepangle);
canvas.drawtextonpath(mdrawstr, path, mhoffset, mvoffset, textpaint);
}
/**
* obtain custom attributes that been defined in attrs.xml.
* @param attrs a collection of attributes.
*/
private void obtainattributes(attributeset attrs) {
typedarray ta = mcontext.obtainstyledattributes(attrs, r.styleable.arcimageview);
mdrawstr = ta.getstring(r.styleable.arcimageview_drawstr);
mtextsize = ta.getdimension(r.styleable.arcimageview_textsize, default_text_size);
marcalpha = ta.getinteger(r.styleable.arcimageview_arcalpha, default_arc_alpha);
marcwidth = ta.getinteger(r.styleable.arcimageview_arcwidth, default_arc_width);
mstartangle = ta.getinteger(r.styleable.arcimageview_startangle, default_start_angle);
msweepangle = ta.getinteger(r.styleable.arcimageview_startangle, default_sweep_angle);
mhoffset = ta.getinteger(r.styleable.arcimageview_hoffset, default_h_offset);
mvoffset = ta.getinteger(r.styleable.arcimageview_voffset, default_v_offset);
marccolor = ta.getcolor(r.styleable.arcimageview_arccolor, xcccccc);
mtextcolor = ta.getcolor(r.styleable.arcimageview_textcolor, xffffff);
mdrawstyle = ta.getint(r.styleable.arcimageview_drawstyle, );
ta.recycle();
}
}

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

<?xml version="." encoding="utf-"?>
<resources>
<declare-styleable name="arcimageview">
<attr name="drawstr" format="string" />
<attr name="textsize" format="dimension" />
<attr name="arcalpha" format="integer" />
<attr name="arcwidth" format="integer" />
<attr name="startangle" format="integer" />
<attr name="sweepangle" format="integer" />
<attr name="scale" format="float" />
<attr name="hoffset" format="float" />
<attr name="voffset" format="float" />
<attr name="drawstyle" format="enum">
<enum name="left_top" value="" />
<enum name="left_bottom" value="" />
<enum name="right_top" value="" />
<enum name="right_bottom" value="" />
<enum name="center" value="" />
</attr>
<attr name="arccolor" format="color" />
<attr name="textcolor" format="color" />
</declare-styleable>
</resources>

3.在mainactivity调用arcimageview,实现代码如下:

package com.chunk.customviewsdemo;
import android.os.bundle;
import android.support.v.app.appcompatactivity;
import android.view.view;
import android.widget.button;
import com.chunk.customviewsdemo.views.arcimageview.arcimageview;
public class mainactivity extends appcompatactivity implements view.onclicklistener {
private arcimageview aiv_one;
private arcimageview aiv_two;
private arcimageview aiv_three;
private arcimageview aiv_four;
private button btn_another_one;
private int mgroup = ;
@override
protected void oncreate(bundle savedinstancestate) {
super.oncreate(savedinstancestate);
setcontentview(r.layout.activity_main);
aiv_one = (arcimageview) findviewbyid(r.id.aiv_one);
aiv_one.setarcalpha();
aiv_two = (arcimageview) findviewbyid(r.id.aiv_two);
aiv_two.setarcalpha();
aiv_three = (arcimageview) findviewbyid(r.id.aiv_three);
aiv_three.setarcalpha();
aiv_four = (arcimageview) findviewbyid(r.id.aiv_four);
aiv_four.setarcalpha();
btn_another_one = (button) findviewbyid(r.id.btn_another_one);
btn_another_one.setonclicklistener(this);
}
@override
public void onclick(view v) {
switch (v.getid()) {
case r.id.btn_another_one:
if (mgroup == ) {
aiv_one.setdrawstr("苹果");
aiv_one.setbackgroundresource(r.drawable.apple);
aiv_two.setdrawstr("柚子");
aiv_two.setbackgroundresource(r.drawable.pineapple);
aiv_three.setdrawstr("香蕉");
aiv_three.setbackgroundresource(r.drawable.banana);
aiv_four.setdrawstr("菠萝");
aiv_four.setbackgroundresource(r.drawable.pineapple);
mgroup = ;
} else {
aiv_one.setdrawstr("牛排");
aiv_one.setbackgroundresource(r.drawable.steak);
aiv_two.setdrawstr("海鲜");
aiv_two.setbackgroundresource(r.drawable.seafood);
aiv_three.setdrawstr("奶酪");
aiv_three.setbackgroundresource(r.drawable.cheese);
aiv_four.setdrawstr("烧烤");
aiv_four.setbackgroundresource(r.drawable.barbecue);
mgroup = ;
}
break;
}
}
}

4.mainactivity的布局文件如下:

<linearlayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margintop="dp"
android:layout_marginbottom="dp"
android:orientation="vertical" >
<button
android:id="@+id/btn_another_one"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="换一组" />
<linearlayout
android:layout_width="match_parent"
android:layout_height="dp"
android:layout_weight=""
android:orientation="horizontal" >
<relativelayout
android:layout_width="dp"
android:layout_weight=""
android:layout_height="match_parent" >
<com.chunk.customviewsdemo.views.arcimageview.arcimageview
android:id="@+id/aiv_one"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/steak"
custom:drawstyle="right_bottom"
custom:drawstr="牛排"
custom:arcalpha=""
custom:arccolor="@color/gray"
custom:textcolor="@color/black"
custom:textsize="sp" />
</relativelayout>
<relativelayout
android:layout_width="dp"
android:layout_weight=""
android:layout_height="match_parent" >
<com.chunk.customviewsdemo.views.arcimageview.arcimageview
android:id="@+id/aiv_two"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/seafood"
custom:drawstyle="left_bottom"
custom:drawstr="海鲜"
custom:arcalpha=""
custom:arccolor="@color/gray"
custom:textcolor="@color/black"
custom:textsize="sp" />
</relativelayout>
</linearlayout>
<linearlayout
android:layout_width="match_parent"
android:layout_height="dp"
android:layout_weight=""
android:orientation="horizontal" >
<relativelayout
android:layout_width="dp"
android:layout_weight=""
android:layout_height="match_parent" >
<com.chunk.customviewsdemo.views.arcimageview.arcimageview
android:id="@+id/aiv_three"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/cheese"
custom:drawstyle="right_top"
custom:drawstr="奶酪"
custom:arcalpha=""
custom:arccolor="@color/gray"
custom:textcolor="@color/black"
custom:textsize="sp" />
</relativelayout>
<relativelayout
android:layout_width="dp"
android:layout_weight=""
android:layout_height="match_parent" >
<com.chunk.customviewsdemo.views.arcimageview.arcimageview
android:id="@+id/aiv_four"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/barbecue"
custom:drawstyle="left_top"
custom:drawstr="烧烤"
custom:arcalpha=""
custom:arccolor="@color/gray"
custom:textcolor="@color/black"
custom:textsize="sp" />
</relativelayout>
</linearlayout>
</linearlayout>

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

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

Android使用ImageView 制作透明圆弧实例代码

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

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