打造炫酷进度条
来源:互联网 发布:java xbootclasspath 编辑:程序博客网 时间:2024/04/27 11:55
如何自定义控件
1.自定义属性的声明与获取
2.测量onMeasure
3.布局onLayout(ViewGroup)
4.绘制onDraw
5.onTouchEvent
6.onInterceptTouchEvent(ViewGroup)
7.状态的恢复与保存
自定义属性的声明与获取
1.分析需要的自定义属性
2.在res/values/attrs.xml定义声明
3.在layout文件中进行使用
4.在View的构造方法中进行获取
条形进度条
attrs.xml
<?xml version="1.0" encoding="utf-8"?><resources> <attr name="progress_unreach_color" format="color"></attr> <attr name="progress_unreach_height" format="dimension"></attr> <attr name="progress_reach_color" format="color"></attr> <attr name="progress_reach_height" format="dimension"></attr> <attr name="progress_text_color" format="color"></attr> <attr name="progress_text_size" format="dimension"></attr> <attr name="progress_text_offset" format="dimension"></attr> <declare-styleable name="HorizontalProgressBarWithProgress"> <attr name="progress_unreach_color"></attr> <attr name="progress_unreach_height"></attr> <attr name="progress_reach_color"></attr> <attr name="progress_reach_height"></attr> <attr name="progress_text_color"></attr> <attr name="progress_text_size"></attr> <attr name="progress_text_offset"></attr> </declare-styleable></resources>
HorizontalProgressBarWithProgress.java
public class HorizontalProgressBarWithProgress extends ProgressBar { private static final int DEFAULT_TEXT_SIZE = 10; // sp private static final int DEFAULT_TEXT_COLOR = 0xFFFC00D1; private static final int DEFAULT_COLOR_UNREACH = 0xFFD3D6DA; private static final int DEFAULT_HEIGHT_UNREACH = 2; // dp private static final int DEFAULT_COLOR_REACH = DEFAULT_TEXT_COLOR; private static final int DEFAULT_HEIGHT_REACH = 2; // dp private static final int DEFAULT_TEXT_OFFSET = 10; // dp private int mTextSize = sp2px(DEFAULT_TEXT_SIZE); private int mTextColor = DEFAULT_TEXT_COLOR; private int mUnReachColor = DEFAULT_COLOR_UNREACH; private int mUnReachHeight = dp2px(DEFAULT_HEIGHT_UNREACH); private int mReachColor = DEFAULT_COLOR_REACH; private int mReachHeight = dp2px(DEFAULT_HEIGHT_REACH); private int mTextOffset = dp2px(DEFAULT_TEXT_OFFSET); private Paint mPaint = new Paint(); /** * 在onMeasure中初始化 * 在onDraw中使用 */ private int mRealWidth; public HorizontalProgressBarWithProgress(Context context) { this(context, null); } public HorizontalProgressBarWithProgress(Context context, AttributeSet attrs) { this(context, attrs, 0); } public HorizontalProgressBarWithProgress(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); //获取自定义属性 obtainStyledAttrs(attrs); } /** * 获取自定义属性 * * @param attrs */ private void obtainStyledAttrs(AttributeSet attrs) { TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.HorizontalProgressBarWithProgress); mTextSize = (int) ta.getDimension( R.styleable.HorizontalProgressBarWithProgress_progress_text_size, mTextSize); mTextColor = ta.getColor( R.styleable.HorizontalProgressBarWithProgress_progress_text_color, mTextColor); mTextOffset = (int) ta.getDimension( R.styleable.HorizontalProgressBarWithProgress_progress_text_offset, mTextOffset); mUnReachColor = ta.getColor( R.styleable.HorizontalProgressBarWithProgress_progress_unreach_color, mUnReachColor); mUnReachHeight = (int) ta.getDimension( R.styleable.HorizontalProgressBarWithProgress_progress_unreach_height, mUnReachHeight); mReachColor = ta.getColor( R.styleable.HorizontalProgressBarWithProgress_progress_reach_color, mReachColor); mReachHeight = (int) ta.getDimension( R.styleable.HorizontalProgressBarWithProgress_progress_reach_height, mReachHeight); ta.recycle(); mPaint.setTextSize(mTextSize); } @Override protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {// int widthMode = MeasureSpec.getMode(widthMeasureSpec); int widthVal = MeasureSpec.getSize(widthMeasureSpec); int height = measureHeight(heightMeasureSpec); //确定view的宽和高 setMeasuredDimension(widthVal, height); mRealWidth = getMeasuredWidth() - getPaddingLeft() - getPaddingRight(); } private int measureHeight(int heightMeasureSpec) { int result = 0; int mode = MeasureSpec.getMode(heightMeasureSpec); int size = MeasureSpec.getSize(heightMeasureSpec); //精确值(如match_parent、200dp一类) if (mode == MeasureSpec.EXACTLY) { result = size; } else { //当前绘制底线(descent) 当前绘制顶线(ascent) ascent为负值 //结果为文字的高度 int textHeight = (int) (mPaint.descent() - mPaint.ascent()); result = getPaddingTop() + getPaddingBottom() + Math.max(Math.max(mReachHeight, mUnReachHeight), Math.abs(textHeight)); //测量值不能超过给定的size值 if (mode == MeasureSpec.AT_MOST) { return Math.min(result, size); } } return result; } @Override protected synchronized void onDraw(Canvas canvas) { canvas.save(); canvas.translate(getPaddingLeft(), getHeight() / 2); boolean noNeedUnReach = false; //draw reach bar String text = getProgress() + "%"; int textWidth = (int) mPaint.measureText(text); float radio = getProgress() * 1.0f / getMax(); float progressX = radio * mRealWidth; if (progressX + textWidth > mRealWidth) { progressX = mRealWidth - textWidth; noNeedUnReach = true; } float endX = progressX - mTextOffset / 2; if (endX > 0) { mPaint.setColor(mReachColor); mPaint.setStrokeWidth(mReachHeight); canvas.drawLine(0, 0, endX, 0, mPaint); } //draw text mPaint.setColor(mTextColor); int y = (int) (-(mPaint.descent() + mPaint.ascent()) / 2); canvas.drawText(text, progressX, y, mPaint); //draw unreach bar if (!noNeedUnReach) { float start = progressX + mTextOffset / 2 + textWidth; mPaint.setColor(mUnReachColor); mPaint.setStrokeWidth(mUnReachHeight); canvas.drawLine(start, 0, mRealWidth, 0, mPaint); } canvas.restore(); } private int dp2px(int dpVal) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal, getResources().getDisplayMetrics()); } private int sp2px(int spVal) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spVal, getResources().getDisplayMetrics()); }}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?><ScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:liu="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <com.example.view.HorizontalProgressBarWithProgress android:id="@+id/id_progress01" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="30dp" android:padding="15dp" android:progress="0" liu:progress_reach_color="#ffff0000" liu:progress_text_color="#ffff0000" liu:progress_unreach_color="#44ff0000" /> <com.example.view.HorizontalProgressBarWithProgress android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="30dp" android:padding="15dp" android:progress="100" liu:progress_text_color="#44ff0000" liu:progress_unreach_color="#ffff0000" /> <com.example.view.HorizontalProgressBarWithProgress android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="30dp" android:padding="15dp" android:progress="30" liu:progress_text_color="#44ff0000" liu:progress_unreach_color="#ffff0000" /> </LinearLayout></ScrollView>
MainActivity.java
public class MainActivity extends AppCompatActivity { private final int MSG_UPDATE = 0x110; private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { int progress = mHProgress.getProgress(); mHProgress.setProgress(++progress); if (progress >= 100) { mHandler.removeMessages(MSG_UPDATE); } mHandler.sendEmptyMessageDelayed(MSG_UPDATE, 100); } }; private HorizontalProgressBarWithProgress mHProgress; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mHProgress = (HorizontalProgressBarWithProgress) findViewById(R.id.id_progress01); mHandler.sendEmptyMessage(MSG_UPDATE); }}
圆形进度条
attrs.xml
<declare-styleable name="RoundProgressBarWithProgress"> <attr name="radius" format="dimension"></attr> </declare-styleable>
activity_main.xml
<com.example.view.RoundProgressBarWithProgress android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="30dp" android:padding="15dp" android:progress="30" liu:radius="20dp" liu:progress_text_color="#ff000000" liu:progress_unreach_color="#ffff0000" /> <com.example.view.RoundProgressBarWithProgress android:id="@+id/id_progress02" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="30dp" android:padding="15dp" android:progress="0" liu:radius="60dp" liu:progress_text_color="#ff000000" liu:progress_text_size="30sp" liu:progress_unreach_color="#44ff0000" />
RoundProgressBarWithProgress.java
public class RoundProgressBarWithProgress extends HorizontalProgressBarWithProgress { private int mRadius = dp2px(30); private int mMaxPaintWidth; public RoundProgressBarWithProgress(Context context, AttributeSet attrs) { this(context, attrs, 0); } public RoundProgressBarWithProgress(Context context) { this(context, null); } public RoundProgressBarWithProgress(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mReachHeight = (int) (mUnReachHeight * 2.5f); TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.RoundProgressBarWithProgress); mRadius = (int) ta.getDimension(R.styleable.RoundProgressBarWithProgress_radius, mRadius); ta.recycle(); //设置画笔为空心 mPaint.setStyle(Paint.Style.STROKE); mPaint.setAntiAlias(true); //防抖动 mPaint.setDither(true); //设置画笔的笔触风格 //ROUND 圆角的笔触 mPaint.setStrokeCap(Paint.Cap.ROUND); } @Override protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { mMaxPaintWidth = Math.max(mReachHeight, mUnReachHeight); //默认四个padding一致 int expect = mRadius * 2 + mMaxPaintWidth + getPaddingLeft() + getPaddingRight(); int width = resolveSize(expect, widthMeasureSpec); int height = resolveSize(expect, heightMeasureSpec); int realWidth = Math.min(width, height); mRadius = (realWidth - getPaddingLeft() - getPaddingRight() - mMaxPaintWidth) / 2; setMeasuredDimension(realWidth, realWidth); } @Override protected synchronized void onDraw(Canvas canvas) { String text = getProgress() + "%"; float textWidth = mPaint.measureText(text); float textHeight = (mPaint.descent() + mPaint.ascent()) / 2; canvas.save(); canvas.translate(getPaddingLeft() + mMaxPaintWidth / 2, getPaddingTop() + mMaxPaintWidth / 2); mPaint.setStyle(Paint.Style.STROKE); //draw unreach bar mPaint.setColor(mUnReachColor); mPaint.setStrokeWidth(mUnReachHeight); canvas.drawCircle(mRadius, mRadius, mRadius, mPaint); //draw reach bar mPaint.setColor(mReachColor); mPaint.setStrokeWidth(mReachHeight); //弧度 float sweepAngle = getProgress() * 1.0f / getMax() * 360; canvas.drawArc(new RectF(0, 0, mRadius * 2, mRadius * 2), 0, sweepAngle, false, mPaint); //draw text mPaint.setColor(mTextColor); mPaint.setStyle(Paint.Style.FILL); canvas.drawText(text, mRadius - textWidth / 2, mRadius - textHeight, mPaint); canvas.restore(); }}
https://github.com/LiuchangDuan/demo
0 0
- 打造炫酷进度条
- Android-打造炫酷进度条
- 【Android自定义控件】打造炫酷进度条
- 【学习笔记】Android-打造炫酷进度条(条形)
- 从无到有打造一个炫酷的进度条效果
- 打造进度条
- Photoshop和WPF双剑配合,打造炫酷个性的进度条控件
- 打造形形色色的进度条
- Bootstrap打造特色进度条
- <Android> 打造自己的进度条
- NumberProgressBar酷炫进度条
- 自绘控件打造界面超炫功能超强的圆形进度条
- C#打造一个平滑的进度条
- CSS+JS打造带渐变的进度条
- Ajax+PHP打造等待进度条效果
- Ajax+PHP打造等待进度条效果
- HTML5+CSS3 打造个性进度条 一
- android下打造个性化的圆形进度条
- Android 6.0的变化之权限管理
- 根据浏览器截图
- JDBC(六)
- JS弹出窗口窗口的位置和大小
- vim字符串替换及小技巧
- 打造炫酷进度条
- 函数配置器的举例
- 日期格式转换
- swift学习笔记之继承
- 深入解读Quartz的原理(以及Spring配置)
- Servlet 工作原理解析
- Spring IOC原理解读 面试必读
- android项目中context为空的问题解决
- ANDROID-当网络发生变化时使用BroadcastReceiver和service通知