iOS可复用控件之表盘

【 Flutter 绘制指南 】那个男人带着小册来了 绘制的本身是没有什么框架、语言限制的,所有的平台绘制的接口都基本一致,也就是说这份技能并不依赖平台而存在的,绘制本身是一种自我的能力,更体现一种主观能动性与创造性。我接触过AndroidHtml5的绘制,和Flutter并没有非常大的差异。所以只要会一个,其他平台上手都会非常容易。Flutter 作为一个跨平台的全新技术,AndroidiOSmacOSWindowsLinuxWeb都可以运行,我目前一直在做 Flutter桌面端和移动端的一个项目,也对 Flutter 的未来有很大的期待。 阅读详情

GitHub地址:https://github.com/runThor/HTDial

效果:



实现:

// 实际应用中,整个区域经常需要分为偏低区域、适中区域、偏高区域等不同的划分区域,要用不同的颜色标识,这里我们默认划分低、中、高三个区域,所以需要两个区域的间隔值

//  HTDialView.h


#import <UIKit/UIKit.h>


@interface HTDialView : UIView


@property (nonatomic,assign)CGFloat minValue;  // 表盘下限值

@property (nonatomic,assign)CGFloat maxValue;  // 表盘上限值

@property (nonatomic,assign)CGFloat firstSeparationValue;  // 第一个区域间隔值

@property (nonatomic,assign)CGFloat secondSeparationValue;  // 第二个区域间隔值


// 设置指针指向的值

- (void)pointValue:(CGFloat)value;


@end



//  HTDialView.m


#import "HTDialView.h"


@interface HTDialView ()


@property (nonatomic,strong)UIView *pointerView;  // 指针


@end



@implementation HTDialView


- (void)drawRect:(CGRect)rect {

    // 绘制划分区域

    [self drawAreas];

    

}


- (instancetype)initWithFrame:(CGRect)frame {

    

    if (self = [super initWithFrame:frame]) {

        // 初始化视图

        [self configViews];

        

    }

    

    return self;

}


// 初始化视图方法

- (void)configViews {

    

    // 表盘轮廓

    UIImageView *dialBgImgView = [[UIImageView alloc] initWithFrame:self.bounds];

    dialBgImgView.image = [UIImage imageNamed:@"dial_bg"];

    [self addSubview:dialBgImgView];

    

    // 初始化指针

    self.pointerView = [[UIView alloc]initWithFrame:CGRectMake(0,0,3,80)];

    [self.pointerView setCenter:dialBgImgView.center];

    self.pointerView.backgroundColor = [UIColor yellowColor];

    self.pointerView.layer.anchorPoint = CGPointMake(0.5,0.25);  // 指针旋转的支点

    self.pointerView.layer.masksToBounds = YES;

    // 优化渲染性能

    self.pointerView.layer.shouldRasterize = YES;  

    self.pointerView.layer.rasterizationScale = [UIScreen mainScreen].scale;

    [self addSubview:self.pointerView];

}


// 绘制划分区域及颜色

- (void)drawAreas {

    

    if (self.minValue ==self.maxValue) {

        

        return;

    

    }

    

    CGContextRef contextRef =UIGraphicsGetCurrentContext();

    CGSize viewSize =self.bounds.size;

    CGPoint center =CGPointMake(viewSize.width/2, viewSize.height/2);

    CGFloat radius = viewSize.width/2;

    

    // 绘制低值区域

    CGFloat lowAreaAngle = (self.firstSeparationValue -self.minValue)/(self.maxValue -self.minValue) * (1.5 *M_PI);

    

    CGContextBeginPath(contextRef);

    CGContextMoveToPoint(contextRef, center.x, center.y);

    CGContextAddArc(contextRef, center.x, center.y, radius,M_PI_2,M_PI_2 + lowAreaAngle,0);

    CGContextSetFillColorWithColor(contextRef, [UIColor colorWithRed:0/255.0 green:102.0/255.0 blue:255.0/255.0 alpha:1.0].CGColor);

    CGContextFillPath(contextRef);

    

    // 绘制中值区域

    CGFloat middleAreaAngle = (self.secondSeparationValue -self.firstSeparationValue)/(self.maxValue -self.minValue) * (1.5 *M_PI);

    

    CGContextBeginPath(contextRef);

    CGContextMoveToPoint(contextRef, center.x, center.y);

    CGContextAddArc(contextRef, center.x, center.y, radius,M_PI_2 + lowAreaAngle, M_PI_2 + lowAreaAngle + middleAreaAngle,0);

    CGContextSetFillColorWithColor(contextRef, [UIColor colorWithRed:13/255.0 green:142/255.0 blue:0/255.0 alpha:1.0].CGColor);

    CGContextFillPath(contextRef);

    

    // 绘制高值区域

    CGContextBeginPath(contextRef);

    CGContextMoveToPoint(contextRef, center.x, center.y);

    CGContextAddArc(contextRef, center.x, center.y, radius,M_PI_2 + lowAreaAngle + middleAreaAngle,M_PI *2,0);

    CGContextSetFillColorWithColor(contextRef, [UIColor colorWithRed:250/255.0 green:47/255.0 blue:47/255.0 alpha:1.0].CGColor);

    CGContextFillPath(contextRef);

    

    // 绘制遮罩圆,只展示环形区域

    CGContextBeginPath(contextRef);

    CGContextMoveToPoint(contextRef, center.x, center.y);

    CGContextAddArc(contextRef, center.x, center.y, radius *0.8,0,M_PI *2,0);

    CGContextSetFillColorWithColor(contextRef,self.backgroundColor.CGColor);

    CGContextFillPath(contextRef);

    

}


// 设置指针指向的值

- (void)pointValue:(CGFloat)value {

    

    if (self.minValue ==self.maxValue || value <self.minValue || value >self.maxValue) {

        

        return;

        

    }

    

    // 指针旋转动画

    [UIView animateWithDuration:1.0 animations:^{

        

        CGFloat angle = ((value -self.minValue)/(self.maxValue -self.minValue)) * (M_PI *1.5);

        

        if (angle >M_PI) {

            

            // 旋转角度大于180度,需要分两步旋转,否则会逆向旋转

            self.pointerView.transform =CGAffineTransformMakeRotation(M_PI);

            self.pointerView.transform =CGAffineTransformMakeRotation(angle);

            

        } else {

            

            // 旋转角度小于等于180度,旋转一次即可

            self.pointerView.transform =CGAffineTransformMakeRotation(angle);

        }

    }];

}


使用:

//  ViewController.m


#import "ViewController.h"

#import "HTDialView.h"


@interface ViewController ()


@end


@implementation ViewController


- (void)viewDidLoad {

    [super viewDidLoad];

    

    self.view.backgroundColor = [UIColor colorWithRed:0.1 green:0.1 blue:0.1 alpha:1];

    

    HTDialView *dialView = [[HTDialView alloc] initWithFrame:CGRectMake(0,0, 200,200)];

    dialView.backgroundColor = [UIColor colorWithRed:0.1 green:0.1 blue:0.1 alpha:1];

    [dialView setCenter:CGPointMake([UIScreen mainScreen].bounds.size.width/2, [UIScreen mainScreen].bounds.size.height/2)];

    dialView.minValue =0;  // 下限

    dialView.maxValue =100;  // 上限

    dialView.firstSeparationValue =30;  // 第一间隔值

    dialView.secondSeparationValue =60;  // 第二间隔值

    [dialView pointValue:50];  // 指针指向50

    [self.view addSubview:dialView];

}




PC桌面端UI设计规范:从核心原则到组件落地的完整指南 UI设计规范是构建一致、高效用户体验的基石,它通过定义统一的设计语言、组件和交互模式,确保产品在视觉和操作上保持协调。其原理在于将设计决策系统化、模块化,从而提升开发效率、降低维护成本,并保证不同团队间的协作顺畅。在技术价值上,一套成熟的设计系统能显著加速产品迭代,保障品牌一致性,并优化用户的学习曲线。在应用场景中,尤其在信息密集、操作复杂的PC桌面端——如企业级SaaS软件、开发工具、内容管理系统等生产力工具中,规范的指导作用尤为关键。本文聚焦于PC桌面端这一特定领域,深入探讨如何针对大屏幕、键鼠交互、多 阅读详情

相关推荐

.NET MAUI上位机开发:一次编码适配工控机与平板(工业UI组件库选型)

答案是肯定的,但有前提。.NET MAUI 凭借真正的跨平台能力和C#生态的统一性,正在逐步取代“WPF + Android原生”的双轨开发模式。对于中小型项目、手持巡检终端、轻量化监控看板,MAUI + Syncfusion/DevExpress 已经是最佳选择,能节省50%以上的开发成本。对于超高频实时控制(微秒级)、极度复杂的3D可视化,目前WPF或Qt仍是王者,但MAUI的性能正在快速追赶。给开发者的建议不要重复造轮子:工业UI组件库该买就买,时间成本远高于授权费。架构先行。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 873

ios 简单实现半圆形仪表盘 (进度条)

ios 简单实现半圆形仪表盘 (进度条)

u013712343的博客 1495

基于Bootstrap 5的开源后台模板,带深色主题、完整功能页与本地构建支持

MajesticAdmin 是一套开箱即用的免费后台管理界面模板,底层基于 Bootstrap 5,提供仪表盘、用户管理、表单、图表、数据表格、权限控制等标准后台页面。所有页面均采用响应式设计,适配手机、平板和桌面设备,并兼容主流浏览器。源码结构清晰:SCSS 文件按模块组织在 scss/ 目录下,CSS 和 JS 分别存放于 css/ 和 js/,partials/ 包含可复用的 HTML 片段,vendors/ 集成了 Chart.js、jQuery、Bootstrap Icons 等常用插件。通过 g

gray5的博客 218

IOS自定义表盘,刻度值和指针支持颜色渐变

自定义的一个表盘控件:数值变化动画、刻度值和指针支持颜色渐变;

顺着天赋做事,逆着性格做人 466

iOS非常漂亮的全代码绘制的仪表盘

iOS端非常漂亮的全代码绘制的仪表盘,提供两种显示模式。

ios-一个类似于仪表盘的百分比选择控件.zip

一个类似于仪表盘的百分比选择控件 github地址:https://github.com/chuting/CTDial 支持pod集成

iOS 非常漂亮的仪表盘和温度计

iOS仪表盘和温度计

撸大师的博客 729

IOS上实现的自定义仪表盘,可以用来做流量监控之类的应用

IOS 上实现的自定义仪表盘,像车速里程表,可以用来做流量监控之类的应用

SwiftUI 4.0(iOS 16+)使用新的 Gauge 视图极简实现仪表盘外观

在本篇博文中,我们介绍了在 SwiftUI 4.0 中如何使用新的 Gauge 视图创建极具个性的仪表盘外观,相信小伙伴们会喜欢

享受开发,颠倒银河 2023

iOS仪表盘项目

iOS 仪表盘,仪表盘的画法和详情,刻度等得画法,

软考中级-软件设计师 知识点整理(一篇就过了 建议收藏)

软考中级-软件设计师上午题知识点总结

片言可决讼,半纸能缚龙 17万+

iOS UIViewPage 指示器 仿简书实现

UIIndicatorView 这是一个用于viewpage的一个索引指示器 pod install target 'Pro' do pod 'UIIndicatorView' end 使用 可用于viewpage索引指标控件,可以参考下以下用法 ### 例一 UIIndicatorView *indicator = [[UIIndicatorView a...

在下李逍遥的博客 3597

【SpringBoot 3.x 第43节】你还敢说 Spring 启动慢是“宿命”?Spring AOT 把启动剧本都提前写死了,你服不服?

🏆本文收录于《滚雪球学SpringBoot 3》,专门攻坚指数提升,本年度国内最系统+最专业+最详细(永久更新)。

**My Coding Family** 543

第31章 精密输入与社交连接:复杂控件的系统化设计

本文探讨了移动应用中精密交互控件与社交连接设计的系统化方法。从滑杆、分段选择器等精密输入控件的商业场景应用,到用户主页、好友列表等社交界面的情感化设计,再到设置中心与分享功能的信息架构优化,详细阐述了如何通过Sketch构建可复用、可扩展的设计系统。文章强调将孤立功能模块转化为与商业目标紧密对齐的完整体验链,在细节交互中体现专业度,在社交连接中创造用户价值,最终提升产品的专业感、归属感与增长潜力。

小宝哥Code的专栏 639

多思计组实验实验三、存储器读写实验

实验三、存储器读写实验

qq_53089329的博客 3653

(2-2-2)位置控制算法:常用的位置控制算法(2)

例如下面是一个使用滑模控制算法实现机器人位置控制的例子,在该例子中,假设机器人在一维空间中移动,目标是使机器人的位置迅速、鲁棒地达到设定的目标位置。自适应控制算法通过实时地调整控制器参数,可以适应系统的变化,从而提高系统的鲁棒性和性能。模型预测控制(Model Predictive Control,MPC)是一种先进的控制策略,通常应用于动态系统,以实现对系统状态的优化控制。(6)迭代优化:随着时间推移,MPC迭代执行上述步骤,持续优化控制输入,以适应系统动态和外部扰动,实现对系统状态的稳健控制。

码农三叔 1608

【OpenHarmony】React Native鸿蒙实战:SegmentControl 分段控件详解

本文深入解析 React Native for OpenHarmony 环境下 SegmentControl 分段控件的实战应用。

2401_85686768的博客 973

(九)DFI接口时序

文章目录一、DFI Interface 一、DFI Interface   DFI接口是连接DDR Controller与DDR_PHY之间的通用接口,其信号组如下表:       

Mr.翟的博客 1万+

JavaFX数据可视化生态全解析:从入门到实战的完整指南

你是否曾为Java桌面应用的数据展示而烦恼?是否在寻找既能保持高性能又能实现精美视觉效果的数据可视化方案?今天,我将带你深入探索JavaFX生态系统中那些令人惊叹的数据可视化工具,让你彻底告别枯燥的数据表格。 ## 为什么JavaFX是数据可视化的理想选择? 在数据驱动的时代,如何将复杂数据转化为直观的视觉呈现是每个开发者面临的挑战。JavaFX作为Java平台上的现代化GUI框架,为数据可视

gitblog_01146的博客 349

基于STM32L4XX、HAL库的GC9307 TFT 液晶驱动IC驱动程序设计

GC9307是一款常用的TFT液晶驱动IC,支持240x320分辨率的RGB接口显示屏。(Master Out Slave In): 连接到STM32L4的SPI数据输出引脚(如PA7)(Serial Clock): 连接到STM32L4的SPI时钟引脚(如PA5)(Data/Command): 连接到STM32L4的GPIO引脚(如PA3)(Chip Select): 连接到STM32L4的GPIO引脚(如PA4)(Reset): 连接到STM32L4的GPIO引脚(如PA2): 分别连接到电源和地。

zhusl6688的博客 1037

微信小程序启用蓝牙设备特征值变化时的notify功能

注意:这里的serviceUUID、notifyCharacteristicUUID 我会在后面写入数据时做重点说明。isNotifyBLECharacteristic:false, //是否启用蓝牙设备服务特征 notify。二、启用蓝牙设备特征值变化时的notify功能。下一篇 将继续介绍 微信小程序蓝牙设备写入数据。

wsk198726的专栏 1173

【-Flutter-绘制指南-】那个男人带着小册来了

绘制的本身是没有什么框架、语言限制的,所有的平台绘制的接口都基本一致,也就是说这份技能并不依赖平台而存在的,绘制本身是一种自我的能力,更体现一种主观能动性与创造性。我接触过AndroidHtml5的绘制,和Flutter并没有非常大的差异。所以只要会一个,其他平台上手都会非常容易。Flutter 作为一个跨平台的全新技术,AndroidiOSmacOSWindowsLinuxWeb都可以运行,我目前一直在做 Flutter桌面端和移动端的一个项目,也对 Flutter 的未来有很大的期待。

2301_79985012的博客 852

STM32入门教程:车牌识别

在本文中,我们介绍了如何使用STM32实现车牌识别功能,并提供了详细的代码案例。通过以上步骤,你可以开始开发自己的车牌识别系统了。希望本文对你有所帮助!

2401_85258012的博客 874

SpotifyRadar架构深度拆解:MVVM + Coordinator + RxSwift的最佳实践

SpotifyRadar是一个基于 Swift 的开源 iOS 项目,它通过 Spotify 官方 API 帮你自动拉取喜爱艺人的最新歌曲发行,并统计 Top Tracks(热门歌曲)、Top Artists(热门艺人)与最近播放记录,且全部支持按时间范围查询。这篇文章将深度拆解 SpotifyRadar 的架构设计,看看它如何用 **MVVM + Coordinator + RxSwift**

gitblog_00864的博客 620

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

KMS_VL_ALL_AIO 完整指南:三步完成 Windows 与 Office 智能激活,从此不用操心到期

刚重装完系统,右下角"未激活"水印又冒出来,打开 Office 还直接进了只读模式——这种糟心场景,多半是激活到期或失效了。KMS_VL_ALL_AIO 就是一个开源的 KMS 智能激活脚本:它在你的电脑里模拟一台 KMS 服务器(KMS 是微软的批量激活机制,客户端向 KMS 服务器请求激活),一次搞定 Windows 和 Office 的激活,之后由计划任务在后台自动续期。覆盖 Windows

gitblog_00930的博客 406

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Vane 架构全解:一个 Next.js 应用如何把 AI 聊天与网络搜索融合成回答引擎

Vane([README](https://link.gitcode.com/i/b82c30c37a1d2d438123fafa3f38b7aa))是一个用 Next.js 编写的 AI 回答引擎,它的核心思路是:用户在聊天界面提问后,系统先分类问题,再并行执行"研究(搜索)"与"小部件",最后由大语言模型生成带引用的答案。本文以 [架构总览](https://link.gitcode.com/

gitblog_00380的博客 471

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

上一篇: iOS开发笔记之元素为字典的数组,按元素的value排序
下一篇: iOS开发笔记之view的渲染优化
zzyeeaa
博客等级 码龄11年 6粉丝 39原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值