iOS自定义滚动条
- 引言
- 为什么要自定义ScrollIndictor
- 现有滚动条显示方案
- ( void) setAlpha:( CGFloat)alpha {
if ( self. superview. tag == noDisableVerticalScrollTag) {
if (alpha == 0 && self. autoresizingMask == UIViewAutoresizingFlexibleLeftMargin) {
if ( self. frame. size. width < 10 && self. frame. size. height > self. frame. size. width) {
UIScrollView *sc = ( UIScrollView*) self. superview;
if (sc. frame. size. height < sc. contentSize. height) {
return;
}
}
}
}
if ( self. superview. tag == noDisableHorizontalScrollTag) {
if (alpha == 0 && self. autoresizingMask == UIViewAutoresizingFlexibleTopMargin) {
if ( self. frame. size. height < 10 && self. frame. size. height < self. frame. size. width) {
UIScrollView *sc = ( UIScrollView*) self. superview;
if (sc. frame. size. width < sc. contentSize. width) {
return;
}
}
}
}
[ super setAlpha:alpha];
}
- 现有方案存在的问题
- 开始自定义之旅
#import "Constants.h"
@implementation BaseCollectionView{
UIView *scrollIndicatorView;
CGFloat contentSizeHeight;
}
- ( void)drawRect:( CGRect)rect {
[ self enableCustomVerticalScrollIndicatorWithColor:[ UIColor lightGrayColor]];
}
- ( void)reloadData{
[ super reloadData];
[ self setNeedsDisplay];
}
- ( UIView *)createIndicatorViewWithFrame:( CGRect) frame{
UIView *indicator = [[ UIView alloc] initWithFrame:frame];
indicator. layer. cornerRadius = ScrollIndicatorWidth/ 2.0f;
// viewScrollIndicator.alpha = 0.0f;
// viewScrollIndicator.layer.borderWidth = 1.0f;
// viewScrollIndicator.layer.borderColor = indicatorColor.CGColor;
[ self addSubview:indicator];
return indicator;
}
//Calculate the real height of scroll indictor accroding to the content size.
- ( CGFloat)getNormalScrollIndictorHeight{
CGFloat percent = self. frame. size. height / self. contentSize. height;
float normalHeight = MAX( 0.0f,(percent * self.frame.size.height));
return normalHeight;
}
- ( void)enableCustomVerticalScrollIndicatorWithColor:( UIColor *)indicatorColor
{
self. showsVerticalScrollIndicator = NO;
float height = [ self getNormalScrollIndictorHeight];
CGRect frame = CGRectMake( self. frame. size. width - ScrollIndicatorWidth - ScrollIndicatorRightSpace, 0.0f, ScrollIndicatorWidth, height);
if( scrollIndicatorView == nil){
scrollIndicatorView = [ self createIndicatorViewWithFrame:frame];
[ self addKVOObservers];
}
else{
scrollIndicatorView. frame = frame;
}
[ scrollIndicatorView setBackgroundColor:[indicatorColor colorWithAlphaComponent: 0.75]];
//If content size is larger than frame size, the indictor will be displayed.
if( self. frame. size. height >= self. contentSize. height){
scrollIndicatorView. alpha = 0;
}
else{
scrollIndicatorView. alpha = 1.0;
}
[ self refreshVerticalScrollIndicator];
}
- ( void)refreshVerticalScrollIndicator
{
if ( self. contentSize. height <= 0) {
return;
}
//Get the current frame of scroll indicator
CGRect rect = scrollIndicatorView. frame;
//Get the normal height of Indicator
float normalHeight = [ self getNormalScrollIndictorHeight];
//Calculate the real content offset ratio.
CGFloat maxConentOffset = self. contentSize. height - self. frame. size. height;
CGFloat offsetRatio = self. contentOffset. y / maxConentOffset;
//Calculate the indictor offset
CGFloat maxIndicatorOffset = ( self. frame. size. height - normalHeight);
CGFloat indicatorOffset = offsetRatio * maxIndicatorOffset;
//if scrolling out of top limitation, the scroll indictor will be compressed.
if (indicatorOffset < 0) {
rect. size. height = normalHeight + indicatorOffset;
}
//if scrolling out of bottom limitation, the scroll indictor will be compressed again.
else if(indicatorOffset > self. frame. size. height - normalHeight){
rect. size. height = normalHeight- (indicatorOffset - maxIndicatorOffset);
// indicatorOffset = self.frame.size.height - normalHeight;
}
else{
rect. size. height = normalHeight;
}
rect. origin. y = self. contentOffset. y + MAX( 0.0f,indicatorOffset);
if (rect. size. height < ScrollIndicatorMinHeight) {
rect. size. height = ScrollIndicatorMinHeight;
}
scrollIndicatorView. frame = rect;
}
- ( void)dealloc
{
[ self removeKVOObservers];
}
#pragma mark - KVO
- ( void)addKVOObservers
{
[ self addObserver: self forKeyPath: @"contentSize" options:( NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) context: NULL];
[ self addObserver: self forKeyPath: @"contentOffset" options:( NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) context: NULL];
}
- ( void)removeKVOObservers
{
[ self removeObserver: self forKeyPath: @"contentSize"];
[ self removeObserver: self forKeyPath: @"contentOffset"];
}
- ( void) observeValueForKeyPath: ( NSString *) keyPath ofObject: ( id) object change: ( NSDictionary *) change context: ( void *) context
{
if ( self. contentSize. width > 0.0f) {
[ self refreshVerticalScrollIndicator];
/*
UIView *viewScrollIndicator = [self getViewForHorizontalScrollIndicator];
CGRect rect = self.frame;
CGFloat pourcent = self.contentOffset.x / self.contentSize.width;
viewScrollIndicator.hidden = self.contentSize.width < self.frame.size.width;
rect.size.width = self.frame.size.width * (self.frame.size.width / self.contentSize.width);
rect.origin.x = pourcent * self.frame.size.width;
viewScrollIndicator.frame = rect;
*/
}
}
- 有待完善和改进的地方
相关文章:
iOS自定义滚动条
引言 最近一直在做数据通信相关的工作,导致了UI上的一些bug一直没有解决。这两天终于能腾出点时间大概看了一下Redmine上的bug,发现有很多bug都是与系统滚动条有关系的。所以索性就关注一下这个小小的滚动条。 为什么要自定义ScrollIndictor 原有的Scrol…...
C++知识点2:把数据写进switch case结构,和写进json结构,在使用上有什么区别
将数据存储在Switch Case结构和JSON结构中有明显的区别,它们用于不同的目的和方式。以下是它们之间的主要区别: 1、用途和结构: Switch Case结构:Switch Case是一种条件语句,通常用于根据条件执行不同的代码块。它通常…...
肖sir__linux详解__003(vim命令)
linux 文本编辑命令 作用:用于编辑一个文件 用法:vim 文件名称 或者vi (1)编辑一个存在的文档 例子:编辑一个file1文件 vim aa (2)编辑一个文件不存在,会先创建文件,再…...
瑞芯微RK3588开发板:虚拟机yolov5模型转化、开发板上python脚本调用npu并部署 全流程
目录 0. 背景1. 模型转化1.1 基础环境1.2 创建python环境1.3 将yolov5s.pt转为yolov5s.onnx1.4 将yolov5s.onnx转为yolov5s.rknn 2. 开发板部署2.1. c版本2.1. python版本(必须是python 3.9) 3. 性能测试 0. 背景 全面国产化,用瑞芯微rk3588…...
【Redis专题】RedisCluster集群运维与核心原理剖析
目录 课程内容一、Redis集群架构模型二、Redis集群架构搭建(单机搭建)2.1 在服务器下新建各个节点的配置存放目录2.2 修改配置(以redis-8001.conf为例) 三、Java代码实战四、Redis集群原理分析4.1 槽位定位算法4.2 跳转重定位4.3 …...
我眼中的《视觉测量技术基础》
为什么会写这篇博客: 首先给大家说几点:看我的自我介绍对于学习这本书没有任何帮助,如果你是为了急切的想找一个视觉测量的解决方案那可以跳过自我介绍往下看或者换一篇博客看看,如果你是刚入门想学习计算机视觉的同学࿰…...
【Cisco Packet Tracer】管理方式,命令,接口trunk,VLAN
💐 🌸 🌷 🍀 🌹 🌻 🌺 🍁 🍃 🍂 🌿 🍄🍝 🍛 🍤 📃个人主页 :阿然成长日记 …...
深入协议栈了解TCP的三次握手、四次挥手、CLOSE-WAIT、TIME-WAIT。
TCP网络编程的代码网上很多,这里就不再赘述,简单用一个图展示一下tcp网络编程的流程: 1、深入connect、listen、accept系统调用,进一步理解TCP的三次握手 这三个函数都是系统调用,我们可以分为请求连接方和被…...
接口自动化测试系列-yml管理测试用例
项目源码 目录结构及项目介绍 整体目录结构,目录说明参考 测试用例结构类似httprunner写法,可参考demo 主要核心函数 用例读取转换json import yaml import main import os def yaml_r():curpath f{main.BASE_DIR}/quality_management_logic/ops_ne…...
开源对象存储系统minio部署配置与SpringBoot客户端整合访问
文章目录 1、MinIO安装部署1.1 下载 2、管理工具2.1、图形管理工具2.2、命令管理工具2.3、Java SDK管理工具 3、MinIO Server配置参数3.1、启动参数:3.2、环境变量3.3、Root验证参数 4、MinIO Client可用命令 官方介绍: MinIO 提供高性能、与S3 兼容的对…...
Matlab之数组字符串函数汇总
一、前言 在MATLAB中,数组字符串是指由字符组成的一维数组。字符串可以包含字母、数字、标点符号和空格等字符。MATLAB提供了一些函数和操作符来创建、访问和操作字符串数组。 二、字符串数组具体怎么使用? 1、使用单引号或双引号括起来的字符序列 例…...
基于深度学习网络的火灾检测算法matlab仿真
目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 ................................................................................ load F…...
【Linux】高级IO和多路转接 | select/poll/epoll
多路转接和高级IO 咳咳,写的时候出了点问题,标点符号全乱了(批量替换了几次),干脆就把全文的逗号和句号都改成英文的了(不然代码块里面的代码都是中文标点就跑不动了) 1.高级IO 1.1 五种IO模型…...
el-select 支持多选 搜索远程数据 组件抽取
el-select 支持多选 搜索远程数据 组件抽取 使用方式 import selectView from ./components/selectView<el-form><el-form-item label"选择器"><selectView v-model"selValue" change"handleChange"></el-form-item> …...
el-table纵向垂直表头
参考:https://www.jianshu.com/p/1f38eaffd070 <el-tablestyle"width: 100%":data"getValues":show-header"false"border:cell-style"cellStyle" ><el-table-columnv-for"(item, index) in getHeaders"…...
Pinyin4j介绍和简单使用
前言 Pinyin4j是一个Java库,用于将汉字转换为拼音。它是由中国清华大学的Tsinghua University和中国科学院计算技术研究所的研究人员开发的。Pinyin4j可以用于Java应用程序中,以便在需要时将汉字转换为拼音。例如,它可以用于中文输入法、文本…...
【数据结构】查找
【数据结构】查找 数据结构中,有顺序查找、二分查找、散列查找、插值查找、斐波那契额查找 1.顺序查找 条件:待查找的元素与数组中的元素按顺序排列。算法:从数组的第一个元素开始,逐个比较,直到找到目标元素或遍历完…...
第一次面试
1.多态的原理 2.编译原理 3.HTTPS的加密原理 4.说一说C11新特性 5.平时用过哪些STL容器 6.STL的比较器 原来就是自定义工具类hhhhhh 7.函数指针用过吗 8.I/O多路复用 9.Redis 问的基本都背过,但是一紧张啥都忘了hhhhhhhhh...
Nacos配置文件更新+热更新+多环境配置共享+集群搭建
对服务配置文件 场景: 如果多个服务对应的配置文件都需要更改时,可以利用配置管理,方便对配置文件进行更新,而且是在本地配置前先读取nacos的配置文件,优先级大于本地配置文件 配置步骤 1.首先在Nacos中的配置列表中增…...
李宏毅-机器学习hw4-self-attention结构-辨别600个speaker的身份
一、慢慢分析学习pytorch中的各个模块的参数含义、使用方法、功能: 1.encoder编码器中的nhead参数: self.encoder_layer nn.TransformerEncoderLayer( d_modeld_model, dim_feedforward256, nhead2) 所以说,这个nhead的意思,就…...
边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...
高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...
AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...
初探Service服务发现机制
1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源…...
JavaScript基础-API 和 Web API
在学习JavaScript的过程中,理解API(应用程序接口)和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能,使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...
深入理解Optional:处理空指针异常
1. 使用Optional处理可能为空的集合 在Java开发中,集合判空是一个常见但容易出错的场景。传统方式虽然可行,但存在一些潜在问题: // 传统判空方式 if (!CollectionUtils.isEmpty(userInfoList)) {for (UserInfo userInfo : userInfoList) {…...
CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!
本文介绍了一种名为AnomalyAny的创新框架,该方法利用Stable Diffusion的强大生成能力,仅需单个正常样本和文本描述,即可生成逼真且多样化的异常样本,有效解决了视觉异常检测中异常样本稀缺的难题,为工业质检、医疗影像…...
