十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
Android 开发订单流程view实例详解
站在用户的角度思考问题,与客户深入沟通,找到樟树网站设计与樟树网站推广的解决方案,凭借多年的经验,让设计与互联网技术结合,创造个性化、用户体验好的作品,建站类型包括:成都网站制作、成都网站设计、外贸营销网站建设、企业官网、英文网站、手机端网站、网站推广、空间域名、网络空间、企业邮箱。业务覆盖樟树地区。
先看看最终效果图:
怎么样,效果还是很不错的吧?群里有人说切四张图的、recycleview的、各种的都有啊,但是最简单的就是通过自定义view来实现了~接下来让我们来实现下这个(订单流程view)。
首先我们定义好我们的自定义属性:
attrs.xml
<?xml version="1.0" encoding="utf-8"?>
然后就是我们的老套路了,创建一个叫ProcessView的类继承view,然后定义好我们需要的属性:
/** * Created by leo on 17/3/27. */ public class ProcessView extends View { /** * 默认线宽度 */ private static final float D_LINE_WIDTH = 3; /** * 默认滑动圆点半径 */ private static final float D_THUMB_RADIUS = 10; /** * 默认textsize */ private static final float D_TEXT_SIZE = 13f; private static final int D_REACH_COLOR = 0xFFF1AE0D; private static final int D_UNREACH_COLOR = Color.WHITE; private static final int D_TEXT_COLOR = Color.WHITE; private Paint linePaint; private TextPaint textPaint; private Paint thumbPaint; private float mTextSize = xx2px(TypedValue.COMPLEX_UNIT_SP, D_TEXT_SIZE); private float mLineWidth = xx2px(TypedValue.COMPLEX_UNIT_DIP, D_LINE_WIDTH); private float mThumbRadius = xx2px(TypedValue.COMPLEX_UNIT_DIP, D_THUMB_RADIUS); private int mReachedColor = D_REACH_COLOR; private int mUnreachedColor = D_UNREACH_COLOR; private int mTextColor = D_TEXT_COLOR; //当前进度 private float mProgress = 0.0f; //所有的状态文字 private String[] texts; public ProcessView(Context context) { this(context, null); } public ProcessView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ProcessView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); obtainStyledAttrs(context, attrs, defStyleAttr); initViews(); } /** * 获取我们的自定义属性 * @param context * @param attrs * @param defStyleAttr */ private void obtainStyledAttrs(Context context, AttributeSet attrs, int defStyleAttr) { TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ProcessView, defStyleAttr, 0); texts = a.hasValue(R.styleable.ProcessView_texts) ? getResources().getStringArray(a.getResourceId(R.styleable.ProcessView_texts, 0)) : texts; mLineWidth = a.hasValue(R.styleable.ProcessView_line_width) ? a.getDimensionPixelSize(R.styleable.ProcessView_line_width, 0) : mLineWidth; mThumbRadius = a.hasValue(R.styleable.ProcessView_thumb_radius) ? a.getDimensionPixelSize(R.styleable.ProcessView_thumb_radius, 0) : mThumbRadius; mTextSize = a.hasValue(R.styleable.ProcessView_textsize) ? a.getDimensionPixelSize(R.styleable.ProcessView_text_color, 0) : mTextSize; mReachedColor=a.hasValue(R.styleable.ProcessView_color_reached)? a.getColor(R.styleable.ProcessView_color_reached,D_REACH_COLOR):D_REACH_COLOR; mUnreachedColor=a.hasValue(R.styleable.ProcessView_color_unreached)? a.getColor(R.styleable.ProcessView_color_unreached,D_UNREACH_COLOR):D_UNREACH_COLOR; mTextColor=a.hasValue(R.styleable.ProcessView_text_color)? a.getColor(R.styleable.ProcessView_text_color,D_TEXT_COLOR):D_TEXT_COLOR; a.recycle(); } /** * 初始化一些对象 */ private void initViews() { linePaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG); linePaint.setStyle(Paint.Style.FILL); textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG); thumbPaint = new Paint(linePaint); textPaint.setTextSize(mTextSize); textPaint.setColor(mTextColor); linePaint.setStrokeWidth(mLineWidth); } }
然后就是重写我们的onmeasure方法了,我们这里就不考虑控件的高度为wrap_content这种情况了,所以我们只需要测量高度就可以了:
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int heightM = MeasureSpec.getMode(heightMeasureSpec); int defaultW = MeasureSpec.getSize(widthMeasureSpec); int defaultH = MeasureSpec.getSize(heightMeasureSpec); int resultW, resultH; resultW = defaultW; resultH = getDefaultHeight(defaultH, heightM); setMeasuredDimension(resultW, resultH); } private int getDefaultHeight(int height, int mode) { int result; if (mode == MeasureSpec.EXACTLY) { result = height; } else { //获取文字的高度 float textH = (textPaint.getFontMetrics().bottom - textPaint.getFontMetrics().top); //高度=圆半径+2.2*线条宽度(也就是竖线高度)+文字高度*1.3(也就是空隙高度)+0.5*文字高度 result = (int) (mThumbRadius + mLineWidth * 2.2f + textH * 1.3f + 0.5 * textH); } return result; }
接着就是我们的核心方法onDraw()了,代码很简单都有注释,我就不一一解释了:
@Override protected void onDraw(Canvas canvas) { //画底部的竖线跟文字 drawFoot(canvas); //画移动的小圆点跟进度条 drawProgressAndThumb(canvas); } /** * 画底部的竖线跟文字 */ private void drawFoot(Canvas canvas) { //设置底部竖线宽度(底部的竖线会比进度条的要小一点) float lineWidth = mLineWidth * 0.8f; linePaint.setStrokeWidth(mLineWidth * 0.8f); //起始位置(也就是"订单已提交"的"已"字位置) float startX = textPaint.measureText(texts[0]) / 2; //结束的文字的位置("已送达"的"送"字位置) float endTextW = textPaint.measureText(texts[texts.length - 1]) / 2; //绘制的终点位置 float endX = getMeasuredWidth() - endTextW; //线条的总长度 float lineW = (endX - startX) / (texts.length - 1); //竖线的高度 float lineH = mLineWidth * 2.2f; //竖线的终点位置 float lineY = mThumbRadius + mLineWidth / 2; //循环画出竖线跟文字 for (int i = 0; i < texts.length; i++) { canvas.save(); //每画一条竖线让画布水平平移linew个宽度 canvas.translate(i * lineW, 0); //如果当前进度>竖线所在的位置,就改变竖线的颜色 linePaint.setColor(i * lineW >= mProgress * (endX - startX) ? mUnreachedColor : mReachedColor); float endX2 = i == texts.length - 1 ? startX - lineWidth / 2 : startX + lineWidth / 2; canvas.drawLine(endX2, lineY, endX2, lineY + lineH, linePaint); //画文字 textPaint.setTextAlign(Paint.Align.CENTER); float textH = (textPaint.getFontMetrics().bottom - textPaint.getFontMetrics().top); canvas.drawText(texts[i], endX2, lineY + lineH + textH * 1.3f, textPaint); canvas.restore(); } } private void drawProgressAndThumb(Canvas canvas) { float startX = textPaint.measureText(texts[0]) / 2; float endTextW = textPaint.measureText(texts[texts.length - 1]) / 2; float endX = getMeasuredWidth() - endTextW; float lineY = mThumbRadius; linePaint.setStrokeWidth(mLineWidth); //draw basic line linePaint.setColor(mUnreachedColor); canvas.drawLine(startX, lineY, endX, lineY, linePaint); //draw progress line float progressX = startX + (endX - startX) * mProgress; linePaint.setColor(mReachedColor); canvas.drawLine(startX, lineY, progressX, lineY, linePaint); //给移动圆点一个RadialGradient颜色梯度效果 thumbPaint.setShader(new RadialGradient(progressX, mThumbRadius, mThumbRadius, new int[]{Color.WHITE, D_REACH_COLOR, Color.YELLOW}, null, Shader.TileMode.REPEAT)); canvas.drawCircle(progressX, mThumbRadius, mThumbRadius, thumbPaint); }
好啦~~然后我们暴露一个方法给外部,修改progress:
public void setProgress(float progress) { if (progress != mProgress) { mProgress = progress; if (Looper.myLooper() == Looper.getMainLooper()) { invalidate(); } else { postInvalidate(); } } }
最后我们就可以跑起来了:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
arrays.xml:
<?xml version="1.0" encoding="utf-8"?>- 订单已提交
- 已付款
- 商家已接单
- 已送达
然后是我们的测试activity:
package com.yasin.processdemo; import android.animation.ValueAnimator; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.animation.AccelerateDecelerateInterpolator; import com.yasin.processdemo.view.ProcessView; public class MainActivity extends AppCompatActivity { private ProcessView mProcessView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mProcessView= (ProcessView) findViewById(R.id.id_process); startAni(); } private void startAni() { ValueAnimator a = ValueAnimator.ofFloat(0, 1); a.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float progress = (float) animation.getAnimatedValue(); mProcessView.setProgress(progress); } }); a.setDuration(10000); a.setInterpolator(new AccelerateDecelerateInterpolator()); a.start(); } }
最后附上processview的全部代码:
package com.yasin.processdemo.view; import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RadialGradient; import android.graphics.Shader; import android.os.Looper; import android.text.TextPaint; import android.util.AttributeSet; import android.util.Log; import android.util.TypedValue; import android.view.View; import com.yasin.processdemo.R; /** * Created by leo on 17/3/27. */ public class ProcessView extends View { /** * 默认线宽度 */ private static final float D_LINE_WIDTH = 3; /** * 默认滑动圆点半径 */ private static final float D_THUMB_RADIUS = 10; /** * 默认textsize */ private static final float D_TEXT_SIZE = 13f; private static final int D_REACH_COLOR = 0xFFF1AE0D; private static final int D_UNREACH_COLOR = Color.WHITE; private static final int D_TEXT_COLOR = Color.WHITE; private Paint linePaint; private TextPaint textPaint; private Paint thumbPaint; private float mTextSize = xx2px(TypedValue.COMPLEX_UNIT_SP, D_TEXT_SIZE); private float mLineWidth = xx2px(TypedValue.COMPLEX_UNIT_DIP, D_LINE_WIDTH); private float mThumbRadius = xx2px(TypedValue.COMPLEX_UNIT_DIP, D_THUMB_RADIUS); private int mReachedColor = D_REACH_COLOR; private int mUnreachedColor = D_UNREACH_COLOR; private int mTextColor = D_TEXT_COLOR; //当前进度 private float mProgress = 0.0f; //所有的状态文字 private String[] texts; public ProcessView(Context context) { this(context, null); } public ProcessView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ProcessView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); obtainStyledAttrs(context, attrs, defStyleAttr); initViews(); } /** * 获取我们的自定义属性 * @param context * @param attrs * @param defStyleAttr */ private void obtainStyledAttrs(Context context, AttributeSet attrs, int defStyleAttr) { TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ProcessView, defStyleAttr, 0); texts = a.hasValue(R.styleable.ProcessView_texts) ? getResources().getStringArray(a.getResourceId(R.styleable.ProcessView_texts, 0)) : texts; mLineWidth = a.hasValue(R.styleable.ProcessView_line_width) ? a.getDimensionPixelSize(R.styleable.ProcessView_line_width, 0) : mLineWidth; mThumbRadius = a.hasValue(R.styleable.ProcessView_thumb_radius) ? a.getDimensionPixelSize(R.styleable.ProcessView_thumb_radius, 0) : mThumbRadius; mTextSize = a.hasValue(R.styleable.ProcessView_textsize) ? a.getDimensionPixelSize(R.styleable.ProcessView_text_color, 0) : mTextSize; mReachedColor=a.hasValue(R.styleable.ProcessView_color_reached)? a.getColor(R.styleable.ProcessView_color_reached,D_REACH_COLOR):D_REACH_COLOR; mUnreachedColor=a.hasValue(R.styleable.ProcessView_color_unreached)? a.getColor(R.styleable.ProcessView_color_unreached,D_UNREACH_COLOR):D_UNREACH_COLOR; mTextColor=a.hasValue(R.styleable.ProcessView_text_color)? a.getColor(R.styleable.ProcessView_text_color,D_TEXT_COLOR):D_TEXT_COLOR; a.recycle(); } /** * 初始化一些对象 */ private void initViews() { linePaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG); linePaint.setStyle(Paint.Style.FILL); textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG); thumbPaint = new Paint(linePaint); textPaint.setTextSize(mTextSize); textPaint.setColor(mTextColor); linePaint.setStrokeWidth(mLineWidth); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int heightM = MeasureSpec.getMode(heightMeasureSpec); int defaultW = MeasureSpec.getSize(widthMeasureSpec); int defaultH = MeasureSpec.getSize(heightMeasureSpec); int resultW, resultH; resultW = defaultW; resultH = getDefaultHeight(defaultH, heightM); setMeasuredDimension(resultW, resultH); } private int getDefaultHeight(int height, int mode) { int result; if (mode == MeasureSpec.EXACTLY) { result = height; } else { //获取文字的高度 float textH = (textPaint.getFontMetrics().bottom - textPaint.getFontMetrics().top); //高度=圆半径+2.2*线条宽度(也就是竖线高度)+文字高度*1.3(也就是空隙高度)+0.5*文字高度 result = (int) (mThumbRadius + mLineWidth * 2.2f + textH * 1.3f + 0.5 * textH); } return result; } @Override protected void onDraw(Canvas canvas) { //画底部的竖线跟文字 drawFoot(canvas); //画移动的小圆点跟进度条 drawProgressAndThumb(canvas); } /** * 画底部的竖线跟文字 */ private void drawFoot(Canvas canvas) { //设置底部竖线宽度(底部的竖线会比进度条的要小一点) float lineWidth = mLineWidth * 0.8f; linePaint.setStrokeWidth(mLineWidth * 0.8f); //起始位置(也就是"订单已提交"的"已"字位置) float startX = textPaint.measureText(texts[0]) / 2; //结束的文字的位置("已送达"的"送"字位置) float endTextW = textPaint.measureText(texts[texts.length - 1]) / 2; //绘制的终点位置 float endX = getMeasuredWidth() - endTextW; //线条的总长度 float lineW = (endX - startX) / (texts.length - 1); //竖线的高度 float lineH = mLineWidth * 2.2f; //竖线的终点位置 float lineY = mThumbRadius + mLineWidth / 2; //循环画出竖线跟文字 for (int i = 0; i < texts.length; i++) { canvas.save(); //每画一条竖线让画布水平平移linew个宽度 canvas.translate(i * lineW, 0); //如果当前进度>竖线所在的位置,就改变竖线的颜色 linePaint.setColor(i * lineW >= mProgress * (endX - startX) ? mUnreachedColor : mReachedColor); float endX2 = i == texts.length - 1 ? startX - lineWidth / 2 : startX + lineWidth / 2; canvas.drawLine(endX2, lineY, endX2, lineY + lineH, linePaint); //画文字 textPaint.setTextAlign(Paint.Align.CENTER); float textH = (textPaint.getFontMetrics().bottom - textPaint.getFontMetrics().top); canvas.drawText(texts[i], endX2, lineY + lineH + textH * 1.3f, textPaint); canvas.restore(); } } private void drawProgressAndThumb(Canvas canvas) { float startX = textPaint.measureText(texts[0]) / 2; float endTextW = textPaint.measureText(texts[texts.length - 1]) / 2; float endX = getMeasuredWidth() - endTextW; float lineY = mThumbRadius; linePaint.setStrokeWidth(mLineWidth); //draw basic line linePaint.setColor(mUnreachedColor); canvas.drawLine(startX, lineY, endX, lineY, linePaint); //draw progress line float progressX = startX + (endX - startX) * mProgress; linePaint.setColor(mReachedColor); canvas.drawLine(startX, lineY, progressX, lineY, linePaint); //给移动圆点一个RadialGradient颜色梯度效果 thumbPaint.setShader(new RadialGradient(progressX, mThumbRadius, mThumbRadius, new int[]{Color.WHITE, D_REACH_COLOR, Color.YELLOW}, null, Shader.TileMode.REPEAT)); canvas.drawCircle(progressX, mThumbRadius, mThumbRadius, thumbPaint); } public void setProgress(float progress) { if (progress != mProgress) { mProgress = progress; if (Looper.myLooper() == Looper.getMainLooper()) { invalidate(); } else { postInvalidate(); } } } private float xx2px(int unit, float value) { Context c = getContext(); Resources r; if (c == null) r = Resources.getSystem(); else r = c.getResources(); return (TypedValue.applyDimension( unit, value, r.getDisplayMetrics())); } }
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!