0
点赞
收藏
分享

微信扫一扫

(加入显示电量功能)模仿魅族

快乐小鱼儿_9911 2022-04-27 阅读 54

import android.graphics.PaintFlagsDrawFilter;

import android.graphics.Path;

import android.graphics.PorterDuff;

import android.graphics.PorterDuffXfermode;

import android.graphics.Rect;

import android.graphics.drawable.BitmapDrawable;

import android.util.AttributeSet;

import android.util.TypedValue;

import android.view.View;

import mcxtzhang.weixin521.R;

import mcxtzhang.weixin521.utils.TipsUtils;

/**

* @author zhangxutong

*/

public class BatteryView extends View {

private Context mContext;

/**

* 电池电量 */ private float level;

/**

* 控件半径 */ private int radius;

/**

* 波浪圆的半径 (弃用,被控件半径-padding 取代) */ private int flowRadius;

/**

* 波浪圆的颜色值 */ private int flowColor;

/**

* 绘制的电量文字颜色值 */ private int textColor;

/**

* 绘制的电量文字大小 */ private int textSize;

/**

* 波浪圆X轴偏移 */ private float FAI;

/**

* 波浪圆振幅 */ private float A;

/**

* 波浪圆的周期 */ private float W;

/**

* 波浪圆Y轴偏移 */ private float K;

// 画图相关

/**

* 画笔(遮罩) */ private Paint mPaint;

/**

* 画笔 绘制,电量 */ private Paint mTextPaint;

/**

* 绘制矩形波浪的Path */ private Path mPath;

/**

* 设置抗锯齿 */ private PaintFlagsDrawFilter mDrawFilter;

/**

* 设置遮罩模式 */ private PorterDuffXfermode mPorterDuffXfermode;

/**

* 存放遮罩图片 */ private Bitmap mBitmap;

/**

* 控件宽度 */ private int mWidth;

/**

* 控件高度 */ private int mHeight;

/**

* 中心点 横坐标 */ private int mCenterX;

/**

* 中心点 纵坐标 */ private int mCenterY;

/**

* 遮罩取源区域 */ private Rect mSrcRect;

/**

* 遮罩绘制目标区域 */ private Rect mDestRect;

/**

* 用于得到将要绘制的电量文字信息的区域 */ private Rect mTextRect;

/**

* 用于构建将要绘制的电量文字的字符串 */ private StringBuilder sb;

/**

* 暴漏出给外部调用的接口,用于监听 */ interface OnLevelChangeListener {

int onLevelChange();

}

OnLevelChangeListener mOnLevelChangeListener;

public void setOnLevelChangeListener(

OnLevelChangeListener onLevelChangeListener) {

mOnLevelChangeListener = onLevelChangeListener;

}

/**

* 监听电池广播 */ private BroadcastReceiver mBatteryChangeReceiver = new BroadcastReceiver() {

@Override

public void onReceive(Context context, Intent intent) {

if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {

LogI(“onReceiver BatteryChanged”);

level = intent.getIntExtra(“level”, -1);

int curScale = intent.getIntExtra(“scale”, -1);

sb.delete(0, sb.length());

sb.append(“” + (int) level * 100 / curScale).append(“%”);

//计算AK,以防在电量接近边界,最大最小的时候,绘图超过范围

setA();

//setK();

}

}

};

/**

* 设置Y轴偏移K, 以防在电量接近边界,最大最小的时候,绘图超过范围(弃用) */ private void setK() {

// K:-5~+5 , level :0~100

/*float k = 20f/100f; K = k*level;*/ }

/**

* 设置振幅A,A的计算公式为一个二次方程,在level = 50时,振幅最大,在两端最小,在0和100临界值时为0 */ private void setA() {

//y = ax;

/*float k = 10f / 50f ; A = level<50? k*level:-k*(level-100);*/ //y = ax2+bx+c ( 0,3) (50,10 )( 100,3) if (level == 0 || level == 100) {

A = 0;

} else {

float a = -7f / 2500;

float b = -100 * a;

float c = 3;

A = (float) (a * Math.pow(level, 2) + b * level + c);

}

//LogI(“A:”+A);

}

@Override

protected void onAttachedToWindow() {

super.onAttachedToWindow();

LogI(“onAttachedToWindow”);

//onAttachedToWindow会在onDraw前调用,注册监听电量变化的广播

mContext.registerReceiver(mBatteryChangeReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));

}

@Override

protected void onDetachedFromWindow() {

super.onDetachedFromWindow();

LogI(“onDetachedFromWindow”);

//防止内存泄露,需要注销该广播

mContext.unregisterReceiver(mBatteryChangeReceiver);

}

public BatteryView(Context context) {

this(context, null);

}

public BatteryView(Context context, AttributeSet attrs) {

this(context, attrs, 0);

}

public BatteryView(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

mContext = context;

LogI(“inital func”);

init();

// 获取我们在attr中定义的样式属性

TypedArray a = context.ge 《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》无偿开源 徽信搜索公众号【编程进阶路】 tTheme().obtainStyledAttributes(attrs,

R.styleable.BatteryView, defStyleAttr, 0);

int n = a.getIndexCount();

for (int i = 0; i < n; i++) {

int attr = a.getIndex(i);

switch (attr) {

case R.styleable.BatteryView_batteryLevel:

level = a.getFloat(attr, 0);

break; case R.styleable.BatteryView_flowRadius:

flowRadius = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 150, getResources().getDisplayMetrics()));

break; case R.styleable.BatteryView_radius:

radius = a.getInt(attr, getWidth());

break; case R.styleable.BatteryView_textColor:

textColor = a.getColor(attr, Color.WHITE);

break; case R.styleable.BatteryView_textSize:

textSize = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(

TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics()));

break; case R.styleable.BatteryView_flowViewColor:

TipsUtils.showToast(context,“flowViewColor”);

flowColor = a.getColor(attr,0x88FFFFFF);

break; }

}

a.recycle();

initPaint();

//这个线程就是为了将波浪滚动起来,改变FAI,即X轴的偏移 ,稍后完善会用属性动画实现

new Thread() {

@Override

public void run() {

while (true) {

changeFAI();

try {

Thread.sleep(60);

} catch (InterruptedException e) {

e.printStackTrace();

}

postInvalidate();

}

}

private void changeFAI() {

FAI += 0.2;

}

}.start();

}

/**

* 初始化参数函数 */ private void init() {

level = 0;

radius = getWidth();

flowRadius = 150;

flowColor = 0x88FFFFFF;

FAI = 0;

A = 9;

W = 0.75f;

K = 0;

}

/**

* 初始化画笔相关参数 */ private void initPaint(){

// 绘图参数初始化

// 抗锯齿 mDrawFilter = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);

//设置遮罩模式为,先绘制DST,再绘制SRC,取交集,留下DST

mPorterDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);

mPaint = new Paint();

mPaint.setStyle(Paint.Style.FILL);

mPath = new Path();

// 防抖动

mPaint.setDither(true);

// 开启图像过滤

mPaint.setFilterBitmap(true);

//绘制出的滚动波浪的颜色

mPaint.setColor(flowColor);

// 初始化遮罩图片

mBitmap = ((BitmapDrawable) getResources().getDrawable(

R.drawable.battery_view_bg_round)).getBitmap();

//初始化电量文字的Paint和Rect

mTextPaint = new Paint();

//设置文字样式,实心,居中,字体

mTextPaint.setStyle(Paint.Style.FILL);

mTextPaint.setTextAlign(Paint.Align.CENTER);

/*Typeface tf = Typeface.createFromAsset(mContext.getAssets(), “fonts/Roboto-Thin.ttf”);

mTextPaint.setTypeface(tf);*/ mTextRect = new Rect();

sb = new StringBuilder();

}

//private int temp = 0;

@Override

protected void onDraw(Canvas canvas) {

//LogI(“flowRadius” + flowRadius + " getPaddingRight:" + getPaddingRight());

//if(temp++==0) //LogI(“onDraw”); // 从canvas层面抗锯齿 canvas.setDrawFilter(mDrawFilter);

//新开启一个图层,用于绘制波浪

int sc = canvas.saveLayer(0 + getPaddingLeft(), 0 + getPaddingTop(), mWidth - getPaddingRight(), mHeight - getPaddingBottom(), null,

Canvas.ALL_SAVE_FLAG);

//清除上次的path

mPath.reset();

/* level = 0;

setA(); //setK();

举报

相关推荐

0 条评论