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

这几天因为项目需求,需要在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"。

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

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

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

(0)

相关推荐

  • Android自定义View弧线进度控件

    这个是一个以弧线为依托的进度控件,主要包括了两个圆弧.一个圆.一个文本. 当我们点击开始按钮的时候,会出现一个动画,逐渐的出现进度,好了,下面开始我们的编码. 新建一个类,继承自View,实现三个构造方法,接着定义变量,初始化变量的数据.代码如下: private Paint mArcPaint, mCirclePaint, mTextPaint, mPaint; private float length; private float mRadius; private float mCircle

  • Android 圆角 ImageView类可设置弧度(代码简单)

    废话不多说了,直接给大家贴代码了,具体代码如下所示: public class RoundImageView extends ImageView { private Paint paint; private int roundWidth = 50; private int roundHeight = 50; private Paint paint2; public RoundImageView(Context context, AttributeSet attrs, int defStyle)

  • android自定义进度条渐变色View的实例代码

    最近在公司,项目不是很忙了,偶尔看见一个兄台在CSDN求助,帮忙要一个自定义的渐变色进度条,我当时看了一下进度条,感觉挺漂亮的,就尝试的去自定义view实现了一个,废话不说,先上图吧! 这个自定义的view,完全脱离了android自带的ProgressView,并且没使用一张图片,这样就能更好的降低程序代码上的耦合性! 下面我贴出代码  ,大概讲解一下实现思路吧! 复制代码 代码如下: package com.spring.progressview; import android.conten

  • Android动画之渐变动画(Tween Animation)详解 (渐变、缩放、位移、旋转)

    本文实例讲述了Android动画之渐变动画(Tween Animation).分享给大家供大家参考,具体如下: Android 平台提供了两类动画. 一类是Tween动画,就是对场景里的对象不断的进行图像变化来产生动画效果(旋转.平移.放缩和渐变). 第二类就是 Frame动画,即顺序的播放事先做好的图像,与gif图片原理类似. 下面就讲一下Tweene Animations. 主要类: Animation                  动画 AlphaAnimation          

  • Android实现渐变色的圆弧虚线效果

    首先来看看效果图: 1,SweepGradient(梯度渲染) public SweepGradient (float cx, float cy, int[] colors, float[] positions) 扫描渲染,就是以某个点位中心旋转一周所形成的效果!参数依次是: cx:扫描的中心x坐标 cy:扫描的中心y坐标 colors:梯度渐变的颜色数组 positions:指定颜色数组的相对位置 public static final int[] SWEEP_GRADIENT_COLORS

  • Android开发之图形图像与动画(二)Animation实现图像的渐变/缩放/位移/旋转

    Android 平台提供了两类动画. 一类是Tween动画,就是对场景里的对象不断的进行图像变化来产生动画效果(旋转.平移.放缩和渐变). 下面就讲一下Tweene Animations. 主要类: Animation 动画 AlphaAnimation 渐变透明度 RotateAnimation 画面旋转 ScaleAnimation 渐变尺寸缩放 TranslateAnimation 位置移动 AnimationSet 动画集 一.AlphaAnimation 其中AlphaAnimatio

  • Android编程之canvas绘制各种图形(点,直线,弧,圆,椭圆,文字,矩形,多边形,曲线,圆角矩形)

    本文实例讲述了Android编程之canvas绘制各种图形的方法.分享给大家供大家参考,具体如下: 1.首先说一下canvas类: Class Overview The Canvas class holds the "draw" calls. To draw something, you need 4 basic components: A Bitmap to hold the pixels, a Canvas to host the draw calls (writing into

  • Android实现自定义的卫星式菜单(弧形菜单)详解

    一.前言 Android 实现卫星式菜单也叫弧形菜单,主要要做的工作如下: 1.动画的处理 2.自定义ViewGroup来实现卫星式菜单View (1)自定义属性 a. 在attrs.xml中定义属性 b. 在布局中使用自定义属性 c. 在自定义View中读取布局文件中的自定义属性 (2)onMeasure 测量 child 即测量主按钮以及菜单项 (3)onLayout 布局 child 即布局主按钮以及菜单项 (4)设置主按钮的选择动画 a.为菜单项menuItem添加平移动画和旋转动画 b

  • android自定义进度条渐变圆形

    在安全卫生上,经常看到有圆形的进度条在转动,效果非常好看,于是就尝试去实现一下,具体实现过程不多说了,直接上效果图,先炫耀下. 效果图: 分析:比较常见于扫描结果.进度条等场景 利用canvas.drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)绘制圆弧 Paint的一些属性定义粗细.颜色.样式等 LinearGradient实现颜色的线型渐变 同样的道理,可以画出长条进度

  • android中实现背景图片颜色渐变方法

    常用,记录一下. 效果图: 首先新建xml文件  bg_gradient.xml 复制代码 代码如下: <?xml version="1.0" encoding="utf-8"?>  <shape xmlns:android="http://schemas.android.com/apk/res/android" >        <gradient          android:startColor="

随机推荐