1、概述
1.1 目的 :
在我们的日常开发中,有很多Android UI界面上有一些特殊或者特别的控件与界面,是Android自带的控件所不能满足的,需要我们自己定制一些适合的控件来完成。
1.2 Android自定义View步骤 :
- 自定义属性;
- 选择和设置构造方法;
- 重写onMeasure()方法;
- 重写onDraw()方法;
- 重写onLayout()方法;
- 重写其他事件的方法(滑动监听等)。
2、代码实现
2.1 自定义属性:
我们通常将自定义属性定义在/values/attr.xml文件中(attr.xml文件需要自己创建)。
<declare-styleable name="SaleProgressView">
<attr name="sideColor" format="color" />
<attr name="textColor" format="color" />
<attr name="sideWidth" format="dimension" />
<attr name="overText" format="string" />
<attr name="nearOverText" format="string" />
<attr name="textSize" format="dimension" />
<attr name="isNeedAnim" format="boolean" />
</declare-styleable>
2.2 实现方法含义
1、在OnMeasure()方法中,测量自定义控件的大小,使自定义控件能够自适应布局各种各样的需求。
2、在OnDraw()方法中,利用哼哈二将(Canvas与Paint)来绘制要显示的内容。
3、在OnLayout()方法中来确定控件显示位置。
4、在OnTouchEvent()方法处理控件的触摸事件。、
[图片上传失败...(image-57f412-1538104403176)]
2.3 继承View实现代码
package com.fly.myview.progressbar;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import com.fly.myview.R;
import java.text.DecimalFormat;
/**
* <pre>
* .----.
* _.'__ `.
* .--(Q)(OK)---/$\
* .' @ /$$$\
* : , $$$$$
* `-..__.-' _.-\$$$/
* `;_: `"'
* .'"""""`.
* /, FLY ,\
* // \\
* `-._______.-'
* ___`. | .'___
* (______|______)
* </pre>
* 包 名 : com.fly.myview.processbar
* 作 者 : FLY
* 创建时间 : 2017/9/26
* <p>
* 描述: 仿淘宝抢购进度条
*/
public class SaleProgressView extends View{
//商品总数
private int totalCount;
//当前卖出数
private int currentCount;
//动画需要的
private int progressCount;
//售出比例
private float scale;
//边框颜色
private int sideColor;
//文字颜色
private int textColor;
//边框粗细
private float sideWidth;
//边框所在的矩形
private Paint sidePaint;
//背景矩形
private RectF bgRectF;
private float radius;
private int width;
private int height;
private PorterDuffXfermode mPorterDuffXfermode;
private Paint srcPaint;
private Bitmap fgSrc;
private Bitmap bgSrc;
private String nearOverText;
private String overText;
private float textSize;
private Paint textPaint;
private float nearOverTextWidth;
private float overTextWidth;
private float baseLineY;
private Bitmap bgBitmap;
private boolean isNeedAnim;
public SaleProgressView(Context context) {
this(context,null);
}
public SaleProgressView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initAttrs(context,attrs);
initPaint();
}
private void initAttrs(Context context, AttributeSet attrs) {
//存储资源数组的容器,通过obtaiStyledAttributes()方法创建,调用recycle()方法把它释放
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SaleProgressView);
//获取XML数据,初始化控件
sideColor = ta.getColor(R.styleable.SaleProgressView_sideColor,0xffff3c32);
textColor = ta.getColor(R.styleable.SaleProgressView_textColor,0xffff3c32);
sideWidth = ta.getDimension(R.styleable.SaleProgressView_sideWidth,dp2px(2));
overText = ta.getString(R.styleable.SaleProgressView_overText);
nearOverText = ta.getString(R.styleable.SaleProgressView_nearOverText);
textSize = ta.getDimension(R.styleable.SaleProgressView_textSize,sp2px(16));
isNeedAnim = ta.getBoolean(R.styleable.SaleProgressView_isNeedAnim,true);
ta.recycle();
}
private void initPaint() {
sidePaint = new Paint(Paint.ANTI_ALIAS_FLAG); //消除锯齿
/**
* Paint.Style.FILL:填充内部
* Paint.Style.FILL_AND_STROKE :填充内部和描边
* Paint.Style.STROKE :描边
*/
sidePaint.setStyle(Paint.Style.STROKE);
//画笔样式为空心时,设置空心画笔的宽度
sidePaint.setStrokeWidth(sideWidth);
//设置画笔颜色
sidePaint.setColor(sideColor);
srcPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
textPaint.setStyle(Paint.Style.FILL);
//设置字体大小
textPaint.setTextSize(textSize);
mPorterDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
nearOverTextWidth = textPaint.measureText(nearOverText);
overTextWidth = textPaint.measureText(overText);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
//获取View的宽高
width = getWidth();
height = getHeight();
//圆角半径
radius = height / 2.0f;
//留出一定的间隙,避免边框被切掉一部分
if (bgRectF == null) {
bgRectF = new RectF(sideWidth, sideWidth, width - sideWidth, height - sideWidth);
}
if (baseLineY == 0.0f) {
Paint.FontMetricsInt fm = textPaint.getFontMetricsInt();
baseLineY = height / 2 - (fm.descent / 2 + fm.ascent / 2);
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(!isNeedAnim){
progressCount = currentCount;
}
if (totalCount == 0) {
scale = 0.0f;
} else {
scale = Float.parseFloat(new DecimalFormat("0.00").format((float) progressCount / (float) totalCount));
}
drawSide(canvas);
drawBg(canvas);
drawFg(canvas);
drawText(canvas);
//这里是为了演示动画方便,实际开发中进度只会增加
if(progressCount!=currentCount){
if(progressCount<currentCount){
progressCount++;
}else{
progressCount--;
}
postInvalidate();
}
}
//绘制背景边框
private void drawSide(Canvas canvas) {
canvas.drawRoundRect(bgRectF, radius, radius, sidePaint);
}
//绘制背景
private void drawBg(Canvas canvas) {
if (bgBitmap == null) {
bgBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
}
//Canvas是画布,对Canvas进行旋转、平移、缩放等操作
Canvas bgCanvas = new Canvas(bgBitmap);
if (bgSrc == null) {
bgSrc = BitmapFactory.decodeResource(getResources(), R.mipmap.bg);
}
//将Canvas还原成矩形
bgCanvas.drawRoundRect(bgRectF, radius, radius, srcPaint);
srcPaint.setXfermode(mPorterDuffXfermode);
//画图片
bgCanvas.drawBitmap(bgSrc, null, bgRectF, srcPaint);
canvas.drawBitmap(bgBitmap, 0, 0, null);
srcPaint.setXfermode(null);
}
//绘制进度条
private void drawFg(Canvas canvas) {
if (scale == 0.0f) {
return;
}
Bitmap fgBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas fgCanvas = new Canvas(fgBitmap);
if (fgSrc == null) {
fgSrc = BitmapFactory.decodeResource(getResources(),R.mipmap.fg);
}
fgCanvas.drawRoundRect(
new RectF(sideWidth, sideWidth, (width - sideWidth) * scale, height - sideWidth),
radius, radius, srcPaint);
srcPaint.setXfermode(mPorterDuffXfermode);
fgCanvas.drawBitmap(fgSrc, null, bgRectF, srcPaint);
canvas.drawBitmap(fgBitmap, 0, 0, null);
srcPaint.setXfermode(null);
}
//绘制文字信息
private void drawText(Canvas canvas) {
String scaleText = new DecimalFormat("#%").format(scale);
String saleText = String.format("已抢%s件", progressCount);
float scaleTextWidth = textPaint.measureText(scaleText);
Bitmap textBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas textCanvas = new Canvas(textBitmap);
textPaint.setColor(textColor);
if (scale < 0.8f) {
textCanvas.drawText(saleText, dp2px(10), baseLineY, textPaint);
textCanvas.drawText(scaleText, width - scaleTextWidth - dp2px(10), baseLineY, textPaint);
} else if (scale < 1.0f) {
textCanvas.drawText(nearOverText, width / 2 - nearOverTextWidth / 2, baseLineY, textPaint);
textCanvas.drawText(scaleText, width - scaleTextWidth - dp2px(10), baseLineY, textPaint);
} else {
textCanvas.drawText(overText, width / 2 - overTextWidth / 2, baseLineY, textPaint);
}
textPaint.setXfermode(mPorterDuffXfermode);
textPaint.setColor(Color.WHITE);
textCanvas.drawRoundRect(
new RectF(sideWidth, sideWidth, (width - sideWidth) * scale, height - sideWidth),
radius, radius, textPaint);
canvas.drawBitmap(textBitmap, 0, 0, null);
textPaint.setXfermode(null);
}
private int dp2px(float dpValue) {
float scale = getContext().getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
private int sp2px(float spValue) {
float scale = getContext().getResources().getDisplayMetrics().scaledDensity;
return (int) (spValue * scale + 0.5f);
}
public void setTotalAndCurrentCount(int totalCount, int currentCount) {
this.totalCount = totalCount;
if (currentCount > totalCount) {
currentCount = totalCount;
}
this.currentCount = currentCount;
postInvalidate();
}
}
3、使用
<com.fly.myview.progressbar.SaleProgressView
android:id="@+id/spv"
android:layout_width="220dp"
android:layout_height="30dp"
android:layout_centerInParent="true"
app:nearOverText="@string/nearOverText"
app:overText="@string/overText" />
4.效果
效果图希望对各位朋友有帮助,谢谢!!!!
网友评论