产品需求中难免有一些不符合常理的设计!!!今天来设计针对一个会员,积分系统,设计一个水平的进度条,首先看图说话
看出图中会员等级分为4级,每一级的长度均分4个实心的点,分为四个区间,每个区间中设置均分的进度,所以用普通的ProgressBar、SeekBar是无法实现的,所以必须自定义View,使用画笔画。
我的思路就是先画一条灰色的虚线,让后,画四个点,根据传入的当前的成长值,计算出在哪个区间,进而绘画出红色的线,并且设置实心的红点的点
package com.wj.progressbardemo;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
/**
* 成长值进度条
*/
public class GrowthValueProgress extends View {
private MyCallback callback;
private Context context;
private int currentValues = 1100;//当前成长值
private int v0Values = 0;//v0会员成长值
private int v1Values = 100;//v1会员成长值
private int v2Values = 10000;//v2会员成长值
private int v3Values = 40000;//v3会员成长值
private int v4Values = 80000;//v4会员成长值
private Paint paint;//会员画笔
private Paint grayPaint;
private Paint pointPaint1;
private Paint pointPaint2;
private Paint pointPaint3;
private Paint pointPaint4;
private int lineHeight = 8;//线的高度
private int pointSize = 8;//圆心的半径
private int offsetX = 0;//x的坐标;
private int width;
private int hight;
private List paintList;
public GrowthValueProgress(Context context) {
super(context);
this.context = context;
initPaint();
}
public GrowthValueProgress(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
initPaint();
}
public GrowthValueProgress(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context = context;
initPaint();
}
public int getCurrentValues() {
return currentValues;
}
public void setCurrentValues(int currentValues) {
this.currentValues = currentValues;
}
private void initPaint() {
lineHeight=hight/2;//线的高度设置为布局的一半高度
pointSize=hight/2;//圆点的半径设置为布局的一半高度
grayPaint = new Paint();
grayPaint.setColor(Color.GRAY);
grayPaint.setStrokeWidth(lineHeight);
grayPaint.setAntiAlias(true);
grayPaint.setTextAlign(Paint.Align.CENTER);
grayPaint.setStyle(Paint.Style.STROKE);
paint = new Paint();
paint.setColor(Color.RED);
paint.setStrokeWidth(lineHeight);
paint.setAntiAlias(true);
paint.setTextAlign(Paint.Align.CENTER);
paint.setStyle(Paint.Style.STROKE);
pointPaint1 = new Paint();
pointPaint2 = new Paint();
pointPaint3 = new Paint();
pointPaint4 = new Paint();
paintList=new ArrayList<>();
paintList.add(pointPaint1);
paintList.add(pointPaint2);
paintList.add(pointPaint3);
paintList.add(pointPaint4);
for (int i = 0; i < paintList.size(); i++) {
Paint mPaint = paintList.get(i);
mPaint.setStrokeWidth(10);
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setTextAlign(Paint.Align.CENTER);
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int lineLength = width / 5;
//绘制底部长灰线
canvas.drawLine(0, lineHeight, width, lineHeight, grayPaint);
drawProgress(canvas, lineLength);
}
/**
* 画进度
*
* @param canvas
* @param lineLength 每个区间的平均长度
*/
private void drawProgress(Canvas canvas, int lineLength) {
//在V0~V1区间内
if (currentValues >= v0Values && currentValues < v1Values) {
int stopX = currentValues * lineLength / (v1Values - v0Values);
//x起始位置,y起始位置,x停止位置,y停止位置
offsetX = stopX;
pointPaint1.setColor(Color.RED);
pointPaint2.setColor(Color.GRAY);
pointPaint3.setColor(Color.GRAY);
pointPaint4.setColor(Color.GRAY);
} else if (currentValues >= v1Values && currentValues < v2Values) {
//在V1~V2区间内
int stopX = (currentValues - v1Values) * lineLength / (v2Values - v1Values);
offsetX = lineLength * 1 + stopX;
pointPaint1.setColor(Color.RED);
pointPaint2.setColor(Color.GRAY);
pointPaint3.setColor(Color.GRAY);
pointPaint4.setColor(Color.GRAY);
} else if (currentValues >= v2Values && currentValues < v3Values) {
//在V2~V3区间内
int stopX = (currentValues - v2Values) * lineLength / (v3Values - v2Values);
offsetX = lineLength * 2 + stopX;
pointPaint1.setColor(Color.RED);
pointPaint2.setColor(Color.RED);
pointPaint3.setColor(Color.GRAY);
pointPaint4.setColor(Color.GRAY);
} else if (currentValues >= 00 && currentValues <= v4Values) {
//在V3~V4区间内
int stopX = (currentValues - v3Values) * lineLength / (v4Values - v3Values);
offsetX = lineLength * 3 + stopX;
pointPaint1.setColor(Color.RED);
pointPaint2.setColor(Color.RED);
pointPaint3.setColor(Color.RED);
pointPaint4.setColor(Color.GRAY);
} else if (currentValues > v4Values) {
int stopX = 10;//超过8万使用固定值
offsetX = lineLength * 4 + stopX;
pointPaint1.setColor(Color.RED);
pointPaint2.setColor(Color.RED);
pointPaint3.setColor(Color.RED);
pointPaint4.setColor(Color.RED);
}
canvas.drawLine(0, lineHeight, offsetX, lineHeight, paint);
//圆心的XY坐标,圆心半径
canvas.drawCircle(1 * lineLength - pointSize, pointSize, pointSize, pointPaint1);
canvas.drawCircle(2 * lineLength - pointSize, pointSize, pointSize, pointPaint2);
canvas.drawCircle(3 * lineLength - pointSize, pointSize, pointSize, pointPaint3);
canvas.drawCircle(4 * lineLength - pointSize, pointSize, pointSize, pointPaint4);
if (callback != null) {
callback.callBack(offsetX,currentValues);
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = this.getMeasuredWidth();
hight = this.getMeasuredHeight();
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
}
public void getOffsetX(MyCallback callback){
this.callback=callback;
}
public interface MyCallback {
public void callBack(int offsetX,int currentValues);
}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="@+id/ll_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="100dp"
android:orientation="vertical">
LinearLayout>
<com.wj.progressbardemo.GrowthValueProgress
android:id="@+id/progress"
android:layout_marginTop="3dp"
android:layout_width="match_parent"
android:layout_height="6dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.5" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="V1会员\n100" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="V2会员\n10000" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="V3会员\n40000" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="V4会员\n80000" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.5" />
LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp">
<EditText
android:id="@+id/et_text"
android:layout_width="100dp"
android:layout_height="40dp" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="btnSetValues"
android:text="设置" />
LinearLayout>
LinearLayout>
ok,那么就有疑问了,线条上面的黑色会话框,是该怎么搞呢,我的想法是在View之外搞,根据接口回调,我能知道我的红色的线有多长,也就相当于我知道我的黑色会话框距离左边多远
package com.wj.progressbardemo;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private int values=100;
private EditText et_text;
private GrowthValueProgress progress;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progress = (GrowthValueProgress) findViewById(R.id.progress);
final LinearLayout ll_content= (LinearLayout) findViewById(R.id.ll_content);
et_text = (EditText) findViewById(R.id.et_text);
progress.setCurrentValues(values);
progress.getOffsetX(new GrowthValueProgress.MyCallback() {
@Override
public void callBack(int offsetX,int currentValues) {
TextView tv=new TextView(MainActivity.this);
tv.setBackgroundResource(R.drawable.ic_growth_values);
if (currentValues>80000){
tv.setText(8+"万+成长值");
}else{
tv.setText(currentValues+"成长值");
}
tv.setTextColor(Color.WHITE);
tv.setTextSize(10);
tv.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT));
ll_content.removeAllViews();
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) tv.getLayoutParams();
params.setMargins(offsetX,0,0,0);
ll_content.addView(tv);
}
});
}
public void btnSetValues(View view) {
String trim = et_text.getText().toString().trim();
progress.setCurrentValues(Integer.parseInt(trim));
progress.invalidate();
}
}