Android 开发订单流程view实例详解 先看看最终效果图: 怎么样,效果还是很不错的吧?群里有人说切四张图的、recycleview的、各种的都有啊,但是最
Android 开发订单流程view实例详解
先看看最终效果图:
怎么样,效果还是很不错的吧?群里有人说切四张图的、recycleview的、各种的都有啊,但是最简单的就是通过自定义view来实现了~接下来让我们来实现下这个(订单流程view)。
首先我们定义好我们的自定义属性:
attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="ProcessView">
<!--滑动圆点的半径-->
<attr name="thumb_radius" fORMat="dimension"/>
<!--到达的颜色-->
<attr name="color_reached" format="color"/>
<!--未到达的颜色-->
<attr name="color_unreached" format="color"/>
<!--textsize的大小-->
<attr name="textsize" format="dimension"/>
<!--text的颜色-->
<attr name="text_color" format="color"/>
<!--线的宽度-->
<attr name="line_width" format="dimension"/>
<!--状态文字数组-->
<attr name="texts" format="reference"/>
</declare-styleable>
</resources>
然后就是我们的老套路了,创建一个叫ProcessView的类继承view,然后定义好我们需要的属性:
public class ProcessView extends View {
private static final float D_LINE_WIDTH = 3;
private static final float D_THUMB_RADIUS = 10;
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();
}
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"?>
<LinearLayout xmlns:Android="Http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
android:background="#b2000000"
android:orientation="vertical"
>
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="5dp"
app:cardElevation="3Dp"
app:cardBackgroundColor="#FF2384DD"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="商家已接单"
android:textSize="14.5sp"
android:textColor="#FFF1AE0D"
/>
<TextView
android:layout_marginTop="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="订单超过12小时自动完成"
android:textSize="13sp"
android:textColor="#fff"
/>
<View
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_width="match_parent"
android:layout_height="2dp"
android:background="@drawable/bg_line"
android:layerType="software"
/>
<com.yasin.processdemo.view.ProcessView
android:id="@+id/id_process"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:texts="@array/process_states"
/>
</LinearLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
arrays.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<array name="process_states">
<item>订单已提交</item>
<item>已付款</item>
<item>商家已接单</item>
<item>已送达</item>
</array>
</resources>
然后是我们的测试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;
public class ProcessView extends View {
private static final float D_LINE_WIDTH = 3;
private static final float D_THUMB_RADIUS = 10;
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();
}
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()));
}
}
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
--结束END--
本文标题: Android 开发订单流程view实例详解
本文链接: https://lsjlt.com/news/21895.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-01-21
2023-10-28
2023-10-28
2023-10-27
2023-10-27
2023-10-27
2023-10-27
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0