版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_20451879/article/details/87930949
此篇应该算一个基础的自定义控件入门,内部没有去写自定义属性 ~
目录
- 实现效果
- 了解部分
- 核心部分
- 使用部分
实现效果
了解部分
- 创建画笔
Paint paint = new Paint();
- 画笔颜色
paint.setColor(Color.parseColor("#FFFFFF"));
3.设置画笔样式,如果不设置,默认是全部填充(FILL)
paint.setStyle(Paint.Style.FILL);
画笔样式分三种
-
Paint.Style.STROKE:描边
-
Paint.Style.FILL_AND_STROKE:描边并填充
-
Paint.Style.FILL:填充
4.打开抗锯齿;抗锯齿是依赖于算法的,算法决定抗锯齿的效率,在我们绘制棱角分明的图像时,比如一个矩形、一张位图,我们不需要打开抗锯齿
paint.setAntiAlias(true);
5.设置笔刷的粗细度
int linePaintStroke = dp2px(context, 3);
paint.setStrokeWidth(linePaintStroke);
核心部分
ProgressLineView
package com.advance.yongliu.customlineview;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
/**
* @author YongLiu
* date 2019/1/6.
* desc:
*/
public class ProgressLineView extends View {
private Paint paint;
private int viewWidth;
private int viewHeight;
private Paint behindPaint;
private Paint textPaint;
private float mPresent;
private String growthValue = "成长值";
private String current = "目前";
public ProgressLineView(Context context) {
super(context);
init(context);
}
public ProgressLineView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context);
}
public ProgressLineView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
/**
* 顶部画笔配置
* */
paint = new Paint();
paint.setColor(Color.parseColor("#FFFFFF"));
paint.setStyle(Paint.Style.FILL);
paint.setAntiAlias(true);
int linePaintStroke = dp2px(context, 3);
paint.setStrokeWidth(linePaintStroke);
/**
* 底部画笔配置
* */
behindPaint = new Paint();
behindPaint.setColor(Color.parseColor("#33000000"));
behindPaint.setStyle(Paint.Style.FILL);
behindPaint.setAntiAlias(true);
int linePaintStroke1 = dp2px(context, 3);
behindPaint.setStrokeWidth(linePaintStroke1);
/**
* 控件文字画笔配置
* */
textPaint = new Paint();
textPaint.setColor(Color.parseColor("#FFFFFF"));
textPaint.setStyle(Paint.Style.FILL);
textPaint.setTextSize(16);
textPaint.setAntiAlias(true);
int linePaintStroke2 = dp2px(context, 50);
textPaint.setStrokeWidth(linePaintStroke2);
}
/**
* 设值 - 绘制
* */
public void setPresent(float present, String growthValue) {
this.growthValue = growthValue;
//动画效果,不适合此处控件
/* ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, present).setDuration(2000);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mPresent = (float) animation.getAnimatedValue();
invalidate();
}
});
valueAnimator.start();*/
mPresent = present;
//绘制
invalidate();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
/**
* 获取我们控件的宽、高
* */
viewWidth = MeasureSpec.getSize(widthMeasureSpec);
viewHeight = MeasureSpec.getSize(heightMeasureSpec);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/**
* 设置图片,并获取图片宽高 (俩图自行找UI获取)
* @params bigBitmap 进度大圆点
* @params smallBitmap 首尾小圆点
*/
Bitmap bigBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_big_whirte_dot);
int bitmapWidth = bigBitmap.getWidth();
int bitmapHeight = bigBitmap.getHeight();
Bitmap smallBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_small_white_dot);
int smallWidth = bigBitmap.getWidth();
int smallHeight = bigBitmap.getHeight();
//字体宽高
float text1Width = textPaint.measureText(current);
float text2Width = textPaint.measureText(growthValue);
Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
float textHeight = fontMetrics.bottom - fontMetrics.top;
/**
* @params mPresent 进度百分比
* @params stopLine 上层线条展示的区域长度
* */
float stopLine = viewWidth * mPresent;
if (stopLine == 0) {
stopLine = smallWidth / 2;
}
if (mPresent >= 0.95) {
stopLine = viewWidth - (smallWidth + 20);
}
/**
* 文字间距配置
* */
float text1Start = stopLine - text1Width / 2 > 0 ? stopLine - text1Width : 0;
float text2Start = stopLine - text2Width / 2 > 0 ? stopLine - text2Width : 0;
if (text1Start <= 0) {
text1Start = 15;
}
if (text2Start <= 0) {
text2Start = 15;
}
if (mPresent != 1) {
if (text1Start == 15 || text2Start == 15) {
canvas.drawText(current, text1Start, viewHeight / 2 - textHeight, textPaint);
canvas.drawText(growthValue, text2Start, viewHeight / 2, textPaint);
} else {
canvas.drawText(current, text1Start + smallWidth / 2 + 10, viewHeight / 2 - textHeight, textPaint);
canvas.drawText(growthValue, text2Start + smallWidth + 10, viewHeight / 2, textPaint);
}
} else {
canvas.drawText(current, viewWidth - text1Width, viewHeight / 2 - textHeight, textPaint);
canvas.drawText(growthValue, viewWidth - text2Width, viewHeight / 2, textPaint);
}
/**
* 进行绘制!!! 俩条线、首位俩个圆点、一个进度点
* */
canvas.drawLine(10, viewHeight / 2 + 40, viewWidth - 10, viewHeight / 2 + 40, behindPaint);
canvas.drawLine(10 , viewHeight / 2 + 40, stopLine, viewHeight / 2 + 40, paint);
canvas.drawBitmap(bigBitmap, stopLine, viewHeight / 2 - bitmapHeight / 2 + 40, null);
canvas.drawBitmap(smallBitmap, 0, viewHeight / 2 - smallHeight / 2 + 42, null);
canvas.drawBitmap(smallBitmap, viewWidth - smallWidth, viewHeight / 2 - smallHeight / 2 + 42, null);
}
private int dp2px(Context context, float dpValue) {
float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
}
使用部分
MainActivity
package com.advance.yongliu.customlineview;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ProgressLineView mLineView = findViewById(R.id.line_progress_view);
TextView mCurrent = findViewById(R.id.tv_current);
TextView mLast = findViewById(R.id.tv_last);
/**
* 传入自定义控件的数据,此处先行设置模拟值(这里一般都是接口返回处理我们进行组装)
* @params currentData 当前成长值 用于文字显示区域
* @params newCurrent 此处有公式 newCurrent = currentData - 上一等级值 ; 因此处上一等级值为0 故直接设置
* @params newNestData 下一等级值
* */
float currentData = Float.parseFloat("20");
float newCurrent = 20;
float newNestData = 100;
mLineView.setPresent(newCurrent / newNestData, "成长值" + Float.valueOf(currentData).intValue());
mCurrent.setText(String.format("青铜等级:%d", 0));
mLast.setText(String.format("白银等级:%s", 100));
/**
* 参考代码 :目前项目中使用的
* @params lastLevelValue 上个等级
* @params nextLevelValue 下个个等级
*
* float lastData = Float.parseFloat(lastLevelValue);
* float nestData = Float.parseFloat(nextLevelValue);
*
* float newCurrent = currentData - lastData;
* float newNestData = nestData - lastData;
* */
}
}
MainActivity xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#f00"
android:orientation="vertical"
tools:context="com.advance.yongliu.customlineview.MainActivity">
<com.advance.yongliu.customlineview.ProgressLineView
android:id="@+id/line_progress_view"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginTop="20dp"
/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_current"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginTop="5dp"
android:text="当前等级"
android:textColor="#fff"
android:textSize="11sp"
/>
<TextView
android:id="@+id/tv_last"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginRight="5dp"
android:layout_marginTop="5dp"
android:text="下一等级"
android:textColor="#fff"
android:textSize="11sp"
/>
</RelativeLayout>
</LinearLayout>