Flutter汽车仪表盘DashBoard
今天對汽車儀表盤的代碼進行了優化,剛剛測試過,性能還是不錯的,因為沒有多余的動作和控件啦;我先放一張圖(以前的圖片,現在的更好);溫馨提示:儀表盤設置了可通過手指觸摸加速,抬起手減速的效果
上面的效果是Canvas畫出來的,繪制的原理和安卓原生的差不多啦,為了提高效率,我將底部的表格和指針預先畫成圖片,這樣每次 繪制圖片 比 繪制Path和Line 快多了;
第一步:我們先看看怎么繪制底圖的表格的。
要繪制表格,要先算出表格之間的偏移角度,這個可以根據需要個性計算哈;然后表格我們分2部分畫,即速度大于120的是一部分,小于120的分另一部分畫;怎么畫呢?我們就畫豎線即可,有人說140的速度可不是豎線呀?這個簡單,不是豎線我們旋轉下畫布,旋轉到讓140速度的那個刻度垂直于水平面,我們再畫豎線,其他速度的刻度都是一個道理,都是先旋轉到該刻度垂直于水平面;好了原理知道了,我們就開始動手吧,下面是我的代碼
class DashBoardTablePainter {final double tableSpace;var speedTexts=["0","20","40","60","80","100","120","140","160","180","200","230","260"];final Size size;final PictureRecorder _recorder = PictureRecorder();DashBoardTablePainter(this.tableSpace,this.size);Picture getBackGround() {Canvas canvas=Canvas(_recorder);canvas.clipRect(new Rect.fromLTWH(0.0, 0.0, size.width, size.height));drawTable( canvas, size);return _recorder.endRecording();}///畫儀表盤的表格void drawTable(Canvas canvas, Size size){canvas.save();double halfWidth=size.width/2;double halfHeight=size.height/2;canvas.translate(halfWidth, halfHeight);Paint paintMain=new Paint();paintMain.color=Colors.blue;paintMain.strokeWidth=2.5;paintMain.style=PaintingStyle.fill;Paint paintOther=new Paint();paintOther.color=Colors.blue;paintOther.strokeWidth=1;paintOther.style=PaintingStyle.fill;drawLongLine(canvas,paintMain,halfHeight,speedTexts[6]);canvas.save();for(int i=61;i<=120;i++){canvas.rotate(tableSpace);if(i%10==0){int a=(i/10).ceil();changePaintColors(paintMain,i);drawLongLine(canvas,paintMain,halfHeight,speedTexts[a]);}else if(i%5==0){changePaintColors(paintMain,i);drawMiddleLine(canvas,paintMain,halfHeight);}else{changePaintColors(paintOther,i);drawSmallLine(canvas,paintOther,halfHeight);}}canvas.restore();canvas.save();for(int i=59;i>=0;i--){canvas.rotate(-tableSpace);if(i%10==0){int a=(i/10).ceil();changePaintColors(paintMain,i);drawLongLine(canvas,paintMain,halfHeight,speedTexts[a]);}else if(i%5==0){changePaintColors(paintMain,i);drawMiddleLine(canvas,paintMain,halfHeight);}else{changePaintColors(paintOther,i);drawSmallLine(canvas,paintOther,halfHeight);}}canvas.restore();canvas.restore();}void changePaintColors(Paint paint,int value){if(value<=20){paint.color=Colors.green;}else if(value<80){paint.color=Colors.blue;}else{paint.color=Colors.red;}}///畫儀表盤上的長線void drawLongLine(Canvas canvas,Paint paintMain,double halfHeight,String text){canvas.drawLine(new Offset(0.0, -halfHeight), new Offset(0.0, -halfHeight+15), paintMain);TextPainter textPainter = new TextPainter();textPainter.textDirection = TextDirection.ltr;textPainter.text = new TextSpan(text: text, style: new TextStyle(color:paintMain.color,fontSize: 15.5,));textPainter.layout();double textStarPositionX = -textPainter.size.width / 2;double textStarPositionY = -halfHeight+19;textPainter.paint(canvas, new Offset(textStarPositionX, textStarPositionY));}void drawMiddleLine(Canvas canvas,Paint paintMain,double halfHeight){canvas.drawLine(new Offset(0.0, -halfHeight), new Offset(0.0, -halfHeight+10), paintMain);}///畫短線void drawSmallLine(Canvas canvas,Paint paintOther,double halfHeight){canvas.drawLine(new Offset(0.0, -halfHeight), new Offset(0.0, -halfHeight+7), paintOther);}}第二步:繪制指針。
指針這玩意也可以根據需要隨便自定義大小,顏色,形狀等,我的指針是Path繪制的,你們也可以不用代碼寫,直接找個圖片代替也是沒問題的哈,(補充下,上面講的表格其實也是可以通過圖片代替的,不過不能繪制特效哦)這個幾乎沒啥難度哈,我們看下代碼
class IndicatorPainter {final PictureRecorder _recorder = PictureRecorder();final Size size;IndicatorPainter(this.size);///畫速度指針Picture drawIndicator(){Canvas canvas=Canvas(_recorder);canvas.clipRect(new Rect.fromLTWH(0.0, 0.0, size.width, size.height));double halfHeight=size.height/2;double halfWidth=size.width/2;Path path=new Path();path.moveTo(-2.5, 20);path.lineTo(2.5, 20);path.lineTo(6.0, -30);path.lineTo(0.5, -halfHeight+8);path.lineTo(-0.5, -halfHeight+8);path.lineTo(-6.0, -30);path.close();canvas.save();canvas.translate(halfWidth, halfHeight);Paint paint=new Paint();paint.color=Colors.red;paint.style=PaintingStyle.fill;canvas.drawPath(path, paint);paint.color=Colors.black;canvas.drawCircle(new Offset(0.0,0.0), 6, paint);canvas.restore();return _recorder.endRecording();} }第三步:將底圖,指針,還有速度值疊加繪制
底圖,指針都畫出來了,那還有啥難度呢,就只剩根據需要將指針旋轉繪制,將速度值繪制在表盤上;另外嘮叨幾句,曾想過將底圖的表格單獨弄個控件,這樣就省去每次繪制底圖的麻煩,但是有的人想在速度高時表盤渲染成紅色,速度低時渲染成綠色,所以想想還是把底圖每次都繪制下吧;好了,看代碼
class DashBoardState extends State<DashBoard>{final platform = const MethodChannel('com.flutter.lgyw/sensor');bool _isGetPressure=false;int pressures=0;final double wholeCirclesRadian=6.283185307179586;///雖然一個圓被分割為160份,但是只顯示120份final int tableCount=160;Size dashBoardSize;double tableSpace;Picture _pictureBackGround;Picture _pictureIndicator;@overridevoid initState() {super.initState();dashBoardSize=new Size(300.0,300.0);tableSpace=wholeCirclesRadian/tableCount;_pictureBackGround=DashBoardTablePainter(tableSpace,dashBoardSize).getBackGround();_pictureIndicator=IndicatorPainter(dashBoardSize).drawIndicator();}@overrideWidget build(BuildContext context) {return new Scaffold(appBar: new AppBar(title: new Text("汽車儀表盤"),),body: new Center(child:GestureDetector(onPanDown:(DragDownDetails dragDownDetails){_isGetPressure=true;boostSpeed();},onPanCancel: (){handleEndEvent();},onPanEnd: (DragEndDetails dragEndDetails){handleEndEvent();},child:new CustomPaint(size: dashBoardSize,painter: new DashBoardIndicatorPainter(pressures,tableSpace,_pictureBackGround,_pictureIndicator),),),),);}void boostSpeed() async {while (_isGetPressure){if(pressures<120){setState(() {pressures++;});}await Future.delayed(new Duration(milliseconds: 30));}}void handleEndEvent(){_isGetPressure=false;bringDownSpeed();}void bringDownSpeed() async {while (!_isGetPressure){setState(() {pressures--;});if(pressures<=0){break;}await Future.delayed(new Duration(milliseconds: 30));}} }到這里,儀表盤控件就完成了,你只需要將它加到你需要的地方;是不是很簡單哈,
如果在使用的過程中有什么問題,請留言,隨時為你解答,
最后附上源碼地址:https://github.com/OpenFlutter/PullToRefresh;
里面有很多更酷的控件,歡迎Star;如果喜歡Flutter,可以加入我們哦,我們的QQ群是 :892398530
總結
以上是生活随笔為你收集整理的Flutter汽车仪表盘DashBoard的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【代码调试】《FSCE: Few-Sho
- 下一篇: 远程桌面连接发生身份验证错误(错误代码: