当前位置:网站首页>仪表盘
仪表盘
2022-08-09 14:55:00 【按劳分配】
自定义View–仪表盘
写之前一定先想好各个坐标的计算方式,间隔,内边距,还有需要的各种参数。
主要涉及控件测量、画布移动、线性渐变shader、Path、三角函数,没有什么难度。。。
1、效果如下:
2、首先分析效果,第一步要实现最外面的这个闭合的圆弧,利用path来实现
//设置了控件内部的padding,避免在控件的边缘绘制,
//由于paint的宽度导致线条绘制在控件外部而看不到。
int pianyi = innerPadding;
acr1 = new RectF(0 + pianyi, 0 + pianyi, bwidth - pianyi, bwidth - pianyi);
acr2 = new RectF(0 + arcWidth + pianyi, 0 + arcWidth + pianyi,
bwidth - arcWidth - pianyi, bwidth - arcWidth - pianyi);
path_arc.arcTo(acr1, 180, 180);
path_arc.lineTo(bwidth - arcWidth - pianyi, bheight);
path_arc.arcTo(acr2, 0, -180);
path_arc.close();
//这样就得到了最外面的闭合圆弧的path,然后直接绘制path就ok了
3、线性渐变
//准备好一个线性渐变的画笔
linearGradient = new LinearGradient(0, 0, bwidth, 0, new int[]{
getResources().getColor(R.color.shadercolor1),
getResources().getColor(R.color.shadercolor2),
getResources().getColor(R.color.shadercolor3)}, null, Shader.TileMode.CLAMP);
paint_shader.setShader(linearGradient);
4、绘制闭合圆弧
//绘制最底层的渐变圆弧
canvas.drawPath(path_arc, paint_shader);
//绘制圆弧边框
canvas.drawPath(path_arc, paint_KeDu);
canvas.save();
5、绘制刻度(画布旋转)
//绘制刻度
int keduNum = 10 * (datas_kudu.length - 1) + 1;//一共有多少个刻度
float preDrgee = (float) (totalDrgee * 1.0 / (keduNum-1));//每个刻度间隔多少角度
for (int i = 0; i < keduNum; i++) {
if (i % 10 == 0&&i!=0&&i!=keduNum-1) {
canvas.drawLine(0 + innerPadding, bheight , bigKeduLength, bheight , paint_KeDuBig);
} else {
canvas.drawLine(0 + innerPadding, bheight, smallKeduLenth, bheight, paint_KeDuSmall);
}
if (i != keduNum - 1) {//最后一次不用再旋转,因为旋转是对下次的绘制起作用
canvas.rotate(preDrgee, getWidth() / 2, getWidth()/2);//旋转画布
}
}
canvas.restore();
canvas.save();
6、绘制刻度的值,将坐标原点移动到下边的中心,方便根据三角函数计算坐标
canvas.restore();
canvas.save();
canvas.translate(getWidth() / 2, getWidth() / 2);
for (int i = 0; i < datas_kudu.length; i++) {
//绘制文字
String text = datas_kudu[i] + "";
double drgee = (totalDrgee*1.0f / (datas_kudu.length - 1)) * i * 1.0d;
WandH wh = getTextRotateXY(drgee, text,i);
canvas.drawText(text, wh.width, wh.height, paint_text);
}
canvas.restore();
canvas.save();
public WandH getTextRotateXY(double drgee, String str, int index) {
drgee = (float) ((Math.PI / 180.0f) * drgee);
int innerRadius = getWidth()/2-innerPadding*3-bigKeduLength;
int wp = 0;
int width = -(int) (Math.cos(drgee) * innerRadius);
if(width>0){
width-=wp;
}else if(width<0){
width+=wp;
}
int height = -(int) (Math.sin(drgee) * innerRadius);
if(null==textrect){
textrect = new Rect();
paint_text.getTextBounds("12", 0, "12".length(), textrect);
}
int tw = textrect.width();
int th = textrect.height();
if(index==0||index==datas_kudu.length-1){
height = height-DensityUtil.dip2px(context,2);
}
if(datas_kudu.length%2!=0&&index==datas_kudu.length/2){//基数个,并且是中间那个
width = width-tw/2;
}else{
if (width > 0) {
width = width - tw;
}
}
if(str.length()==2){
width = width - textrect.width()/2;
}
Log.i(Tag, "width:" + width + ",height:" + height + ",drgee:" + drgee + "innerRadius:" + innerRadius);
// Log.i(Tag,"drgee:"+(Math.sin(drgee)*radius)+",height:"+height+",w:"+width+",radius:"+radius);
return new WandH(width, height);
}
7、在计算指针的角度的时候,还是跟以前一样,先把180度分配为几段,然后计算当前值在哪一段,
再计算当前值在这一段中占据的比例,来计算当前值应该有的度数
8、绘制指针,根据当前值,计算出应该旋转的角度,来旋转画布
/**
* 绘制指针
*
* @param canvas
*/
public void drawZhiZhen(Canvas canvas) {
//先在中心位置画一个圆形
//先绘制中心的红色圆形
canvas.restore();
canvas.save();
paint_zhizhen.setColor(Color.RED);
int rx = getWidth() / 2;
int ry = getWidth() / 2 ;
// currentDrgee = (float) (currentDrgee - Math.atan(zhizhen_circleRadus * 1.0d / (getWidth() / 2)) * 180 / Math.PI);
canvas.rotate(currentDrgee, rx, ry);
canvas.drawCircle(rx, ry, zhizhen_circleRadus, paint_zhizhen);
Path path_zhizhen = new Path();
path_zhizhen.moveTo(getWidth() / 2, ry+zhizhen_circleRadus/2);
path_zhizhen.lineTo(getWidth() / 2, ry-zhizhen_circleRadus/2);
path_zhizhen.lineTo(innerPadding * 2 + 20, ry);
path_zhizhen.close();
canvas.drawPath(path_zhizhen, paint_zhizhen);
paint_zhizhen.setColor(Color.WHITE);
canvas.drawCircle(rx, ry, zhizhen_circleRadus / 2, paint_zhizhen);
canvas.save();
}
边栏推荐
- NetCore 5.0连接MySql
- bin document read and write
- Several important functional operations of general two-way circular list
- 小型项目如何使用异步任务管理器实现不同业务间的解耦
- 相干光(光学)
- 单向链表几个比较重要的函数(包括插入、删除、反转等)
- Simple analysis of regularization principle (L1 / L2 regularization)
- Sequelize配置中的timezone测试
- 关于亚马逊测评你了解多少?
- 通用的双向循环列表的几个比较重要的函数操作
猜你喜欢
随机推荐
【C语言初阶】求最小公倍数的三种方法
路由的懒加载与接口的封装
Analysis of the common methods and scopes of the three servlet containers
flex布局总结
关于亚马逊的坑你知道几个?
WebGL:BabylonJS入门——初探:我的世界
What are the implications of programmatic trading rules for the entire trading system?
bin document read and write
SNR 信噪比
实现一个支持请求失败后重试的JS方法
cheerio根据多个class匹配
Talking about Shallow Cloning and Deep Cloning of ArraryList
地铁预约Postman脚本使用
PHP开源 | ysKit(ys工具包) - 微型Web框架
Sequelize配置中的timezone测试
(13)Filter过滤器
Several important functions of singly linked list (including insertion, deletion, reversal, etc.)
自定义指令,实现默认头像和用户上传头像的切换
Mathematica 数据分析(简明)
Server运维:设置.htaccess按IP和UA禁止访问