1、概述

1.1 目的 :

在我们的日常开发中,有很多Android UI界面上有一些特殊或者特别的控件与界面,是Android自带的控件所不能满足的,需要我们自己定制一些适合的控件来完成。

1.2 Android自定义View步骤 :

  1. 自定义属性;
  2. 选择和设置构造方法;
  3. 重写onMeasure()方法;
  4. 重写onDraw()方法;
  5. 重写onLayout()方法;
  6. 重写其他事件的方法(滑动监听等)。

2、代码实现

2.1 自定义属性:

我们通常将自定义属性定义在/values/attr.xml文件中(attr.xml文件需要自己创建)。

                                                                 

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;/** * 
 *           .----. *        _.'__    `. *    .--(Q)(OK)---/$\ *  .' @          /$$$\ *  :         ,   $$$$$ *   `-..__.-' _.-\$$$/ *         `;_:    `"' *       .'"""""`. *      /,  FLY  ,\ *     //         \\ *     `-._______.-' *     ___`. | .'___ *    (______|______) * 
* 包 名 : com.fly.myview.processbar * 作 者 : FLY * 创建时间 : 2017/9/26 *

* 描述: 仿淘宝抢购进度条 */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 totalCount) { currentCount = totalCount; } this.currentCount = currentCount; postInvalidate(); }}

3、使用

      

4.效果

效果图

希望对各位朋友有帮助,谢谢!!!!

更多相关文章

  1. Android歌词秀设计思路(1)SafetyTimer
  2. 保存/恢复Activity和Fragment状态的最佳实践(译)
  3. Android(安卓)View构造方法第三参数使用方法详解
  4. Android中定时执行任务的3种实现方法
  5. Android(安卓)Lambda表达式
  6. 《第一行代码:Android(第2版)》,作者郭霖
  7. Android(安卓)WebView那些坑之上传文件
  8. Android开发实战(二十一):浅谈android:clipChildren属性
  9. Android(安卓)进阶 教你打造 Android(安卓)中的 IOC 框架 【View

随机推荐

  1. Android Framework architecture -- blue
  2. Android adb功能使用方法
  3. Android开发学习1 - Android架构
  4. 值得推荐的Android App (一)
  5. Android 计算器解析(一): 建立简单界面
  6. Android 关于定位中的那点事(GPS,GPGGA,NM
  7. android 扫描文件栈溢出问题,自己写的扫描
  8. Android 基于回调的事件处理----事件分发
  9. Android(安卓)8.1 添加属性SystemPropert
  10. Android(安卓)AsyncTask for Long Runnin