一,雷速体育球队趋势图,看着就麻烦
二,实现思路,利用MPChart+自定义View
方案思路
1.两个LineChart显示主队客队的走势,要通过自定修改背景
2.自定义View,显示顶部和底部事件图标
代码实现,图标各位读者自行补充哈
1.自定义LineChart
public class CustomLineChartextends LineChart {
private static final StringTAG ="CustomLineChart";
private Listlist;
private boolean enableDrawCross =false;
private float crossWidth =3;
private float crossLength =30;
private boolean enableDrawBgColor =false;
private ArrayListbgList =new ArrayList<>();
public CustomLineChart(Context context) {
super(context);
}
public CustomLineChart(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomLineChart(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
/**
* 重写onDraw方法,注意绘制顺序,先绘制背景色,再绘制叉号,最后绘制图表
* @param canvas
*/
@Override
protected void onDraw(Canvas canvas) {
drawBgColor(canvas);
drawCross(canvas);
super.onDraw(canvas);
Log.i(TAG, "onDraw");
}
private void drawCross(Canvas canvas) {
if (enableDrawCross) {
if (this.getData() !=null) {
LineDataSet set = (LineDataSet)this.getData().getDataSetByIndex(0);
list = set.getValues();
set.setDrawCircles(false);
LineData data =new LineData(set);
this.setData(data);
for (Entry e :list
) {
MPPointD p =this.getPixelForValues(e.getX(), e.getY(), YAxis.AxisDependency.LEFT);
drawNode(canvas, (float) p.x, (float) p.y);
}
}else{
Log.i(TAG, "No Data to Draw");
}
}
}
private void drawNode(Canvas canvas, float x, float y) {
Paint paint =new Paint();
paint.setColor(Color.RED);
paint.setStrokeWidth(crossWidth);
canvas.drawLine(x -crossLength /2, y -crossLength /2, x +crossLength /2, y +crossLength /2, paint);
canvas.drawLine(x -crossLength /2, y +crossLength /2, x +crossLength /2, y -crossLength /2, paint);
}
public void setDrawBgColor(boolean enabled) {
enableDrawBgColor = enabled;
}
/**
* 设置背景时应以BgColor为单位,将多个BgColor添加到一个ArrayList中
* 最后通过此方法给图表加上颜色背景
* @param arrayList 背景色集合
*/
public void setBgColor(ArrayList arrayList) {
bgList = arrayList;
}
private void drawBgColor(Canvas canvas) {
if (enableDrawBgColor) {
if (!bgList.isEmpty()) {
Paint paint =new Paint();
for (BgColor r :bgList
) {
MPPointD pStart =this.getPixelForValues(this.getXChartMin(), r.getStart(), YAxis.AxisDependency.LEFT);
MPPointD pStop =this.getPixelForValues(this.getXChartMax(), r.getStop(), YAxis.AxisDependency.LEFT);
paint.setColor(r.getColor());
canvas.drawRect(new RectF((float) pStart.x, (float) pStart.y, (float) pStop.x, (float) pStop.y), paint);
}
}else {
Log.i(TAG, "No BgColor to Draw");
}
}
}
}
2.自定义顶部时间轴
public class TimeEventViewextends View {
private PaintmPaint;
BitmapcornerIconBitmap; //角球
BitmapinballIconBitmap; //进球
BitmapredCardIconBitmap; //红牌
BitmapyellowCardIconBitmap; //黄牌
BitmapchangePersonBitmap; //换人
BitmapinBallPoint ,inballWrong,yellowChangeRed;
int viewWidth;
private ViewmFistPart;
private int lastX =0;
private ListlistEvent =new ArrayList<>();
public TimeEventView(Context context) {
super(context);
init(context);
}
public TimeEventView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context);
}
public TimeEventView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
public TimeEventView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context);
}
private void init(Context context) {
mPaint =new Paint();
mPaint.setAntiAlias(true);
cornerIconBitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.small_corners);
inballIconBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.icon_live_1);
redCardIconBitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.small_red_card);
yellowCardIconBitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.small_yellow_card);
changePersonBitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.small_change_person);
inBallPoint = BitmapFactory.decodeResource(context.getResources(), R.drawable.icon_live_8);
inballWrong = BitmapFactory.decodeResource(context.getResources(), R.drawable.icon_live_17);
yellowChangeRed = BitmapFactory.decodeResource(context.getResources(), R.drawable.icon_live_14);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
this.setMeasuredDimension(parentWidth, parentHeight);
viewWidth = parentWidth;
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onDraw(Canvas canvas) {
drawEvent(canvas);
super.onDraw(canvas);
}
private void drawEvent(Canvas canvas){
BigDecimal value =divide(BigDecimal.valueOf(viewWidth),BigDecimal.valueOf(90));
int oneWidth = value.intValue();
Logger.e("drawEvent","viewWidth"+viewWidth);
Logger.e("oneWidth","oneWidth"+oneWidth);
for(TimeChangeDTO timeChangeDTO:listEvent){
Rect dst =new Rect(); // 目标矩形
dst.left = oneWidth*timeChangeDTO.getEventTime()-15;
dst.top =0;
dst.right =oneWidth*timeChangeDTO.getEventTime()+15;
dst.bottom =30;
if(dst.left==lastX){
dst.left+=6;
dst.right+=6;
}
lastX = dst.left;
if(dst.right>viewWidth){
dst.left =viewWidth-30;
dst.top =0;
dst.right =viewWidth;
dst.bottom =30;
}
if(dst.left<0){
dst.left =0;
dst.top =0;
dst.right =30;
dst.bottom =30;
}
switch (timeChangeDTO.getEventType()){
case 1:
canvas.drawBitmap(inballIconBitmap, null, dst, mPaint);
break;
case 2:
canvas.drawBitmap(cornerIconBitmap, null, dst, mPaint);
break;
case 4:
canvas.drawBitmap(redCardIconBitmap, null, dst, mPaint);
break;
case 3:
canvas.drawBitmap(yellowCardIconBitmap, null, dst, mPaint);
break;
case 9:
canvas.drawBitmap(changePersonBitmap, null, dst, mPaint);
break;
case 8:
canvas.drawBitmap(inBallPoint, null, dst, mPaint);
break;
case 17:
canvas.drawBitmap(inballWrong, null, dst, mPaint);
break;
case 15:
canvas.drawBitmap(yellowChangeRed, null, dst, mPaint);
break;
default:
break;
}
}
}
public void setListEvent(List listEvent) {
this.listEvent = listEvent;
}
/**
* 除法结果保留两位小数(四舍五入)
* @param a
* @param b
* @return
*/
public static BigDecimaldivide(BigDecimal a, BigDecimal b){
BigDecimal result= a.divide(b, 0, RoundingMode.HALF_UP);
return result;
}
}
public class TimeChangeDTO {
private int eventType; //事件类型 0-无状态,1-进球,2-角球,3-黄牌,4-红牌,5-界外球,6-任意球,7-球门球,8-点球,9-换人,10-比赛开始,11-中场,12-结束,13-半场比分,15-两黄变红,16-点球未进,17-乌龙球,19-伤停补时,21-射正,22-射偏,23-进攻,24-危险进攻,25-控球率
private int eventTime; //事件时间
public int getEventType() {
return eventType;
}
public void setEventType(int eventType) {
this.eventType = eventType;
}
public int getEventTime() {
return eventTime;
}
public void setEventTime(int eventTime) {
this.eventTime = eventTime;
}
public TimeChangeDTO(int eventType, int eventTime){
this.eventTime = eventTime;
this.eventType = eventType;
}
}
布局文件:
android:layout_width="match_parent"
android:layout_height="110dp"
android:background="@color/color_white"
android:id="@+id/layoutTopChart"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
android:layout_width="15dp"
android:layout_height="15dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginLeft="15dp"
android:layout_marginTop="31dp"
android:id="@+id/home_icon"
>
android:layout_width="15dp"
android:layout_height="15dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/home_icon"
android:layout_marginLeft="15dp"
android:layout_marginTop="20dp"
android:id="@+id/away_icon"
>
android:layout_width="match_parent"
android:layout_height="15dp"
android:background="@color/color_white"
android:layout_marginLeft="48dp"
android:layout_marginRight="15dp"
app:layout_constraintBottom_toTopOf="@id/lineChartHome"
android:id="@+id/timeEventHome"
android:layout_marginBottom="2dp"
>
android:id="@+id/lineChartHome"
android:layout_width="match_parent"
android:layout_height="20dp"
android:layout_marginTop="36.5dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginLeft="48dp"
android:layout_marginRight="15dp"
/>
android:id="@+id/lineChartAway"
android:layout_width="match_parent"
android:layout_height="20dp"
app:layout_constraintTop_toBottomOf="@id/lineChartHome"
android:layout_marginLeft="48dp"
android:layout_marginRight="15dp"
/>
android:layout_width="match_parent"
android:layout_height="15dp"
android:background="@color/color_white"
android:layout_marginLeft="48dp"
android:layout_marginRight="15dp"
app:layout_constraintTop_toBottomOf="@id/lineChartAway"
android:id="@+id/timeEventAway"
android:layout_marginTop="2dp"
>
android:layout_width="0.5dp"
android:layout_height="56dp"
app:layout_constraintLeft_toLeftOf="@id/lineChartAway"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:background="@color/color_E6E6E6"
android:id="@+id/left_line"
>
android:layout_width="0.5dp"
android:layout_height="56dp"
app:layout_constraintLeft_toLeftOf="@id/left_line"
app:layout_constraintRight_toRightOf="@id/second_ver_line"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:background="@color/color_E6E6E6"
android:id="@+id/first_ver_line"
>
android:layout_width="0.5dp"
android:layout_height="56dp"
app:layout_constraintLeft_toLeftOf="@id/first_ver_line"
app:layout_constraintRight_toRightOf="@id/center_line"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:background="@color/color_E6E6E6"
android:id="@+id/second_ver_line"
>
android:layout_width="0.5dp"
android:layout_height="56dp"
app:layout_constraintLeft_toLeftOf="@id/lineChartAway"
app:layout_constraintRight_toRightOf="@id/lineChartAway"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:background="@color/color_E6E6E6"
android:id="@+id/center_line"
>
android:layout_width="0.5dp"
android:layout_height="56dp"
app:layout_constraintLeft_toLeftOf="@id/center_line"
app:layout_constraintRight_toRightOf="@id/forth_ver_line"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:background="@color/color_E6E6E6"
android:id="@+id/third_ver_line"
>
android:layout_width="0.5dp"
android:layout_height="56dp"
app:layout_constraintLeft_toLeftOf="@id/third_ver_line"
app:layout_constraintRight_toRightOf="@id/right_line"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:background="@color/color_E6E6E6"
android:id="@+id/forth_ver_line"
>
android:layout_width="0.5dp"
android:layout_height="56dp"
app:layout_constraintLeft_toRightOf="@id/lineChartAway"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:background="@color/color_E6E6E6"
android:id="@+id/right_line"
>
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@id/left_line"
android:layout_marginBottom="5dp"
app:layout_constraintLeft_toLeftOf="@id/left_line"
app:layout_constraintRight_toRightOf="@id/left_line"
android:text="0'"
android:textSize="11sp"
android:textColor="@color/color_999999"
>
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@id/first_ver_line"
android:layout_marginBottom="5dp"
app:layout_constraintLeft_toLeftOf="@id/first_ver_line"
app:layout_constraintRight_toRightOf="@id/first_ver_line"
android:text="15'"
android:textSize="11sp"
android:textColor="@color/color_999999"
>
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@id/second_ver_line"
android:layout_marginBottom="5dp"
app:layout_constraintLeft_toLeftOf="@id/second_ver_line"
app:layout_constraintRight_toRightOf="@id/second_ver_line"
android:text="30'"
android:textSize="11sp"
android:textColor="@color/color_999999"
>
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@id/center_line"
android:layout_marginBottom="5dp"
app:layout_constraintLeft_toLeftOf="@id/center_line"
app:layout_constraintRight_toRightOf="@id/center_line"
android:text="HT"
android:textColor="@color/color_F7D15D"
android:textSize="11sp"
>
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@id/third_ver_line"
android:layout_marginBottom="5dp"
app:layout_constraintLeft_toLeftOf="@id/third_ver_line"
app:layout_constraintRight_toRightOf="@id/third_ver_line"
android:text="60'"
android:textSize="11sp"
android:textColor="@color/color_999999"
>
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@id/forth_ver_line"
android:layout_marginBottom="5dp"
app:layout_constraintLeft_toLeftOf="@id/forth_ver_line"
app:layout_constraintRight_toRightOf="@id/forth_ver_line"
android:text="75'"
android:textSize="11sp"
android:textColor="@color/color_999999"
>
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@id/right_line"
android:layout_marginBottom="5dp"
app:layout_constraintLeft_toLeftOf="@id/right_line"
app:layout_constraintRight_toRightOf="@id/right_line"
android:text="90'"
android:textSize="11sp"
android:textColor="@color/color_999999"
>