(作业)View,Layer,Animation和Gesture

Android 视频手势缩放与回弹动效实现(一) 文章目录Android 视频播放画面手势缩放与缩放后自动吸附动效实现1. 功能需求2. 实现原理2.1 如何检测手势缩放?1. View.onTouchEvent关键代码2. ScaleGestureDetector2.2 缩放平移处理2.3 暂停画面下缩放2.4 缩放移动结束后动效1. 缩小居中2. 放大吸边3. 项目完整代码3.1 手势缩放处理:VideoTouchScaleHandler3.2 动画:VideoScaleEndAnimator Android 视频播放画面手势缩放与缩放后自动吸附动效实 阅读详情

又开始做作业了,这次虽然设计的知识点比较多,但是都比较简单,一个页面就能完成。先来看看要求吧
这里写图片描述

根据这个要求,我们先要自定制一个视图,所以需要新建一个继承自UIView的类,这里博主就使用MyView来命名。
然后在这个类中,我们需要先重写它的draw(_:)方法。

override func draw(_ rect: CGRect) {
        let viewRect = UIBezierPath(rect: rect)

        let redColor = CGFloat(Float(arc4random() % 255) / 255)
        let greenColor = CGFloat(Float(arc4random() % 255) / 255)
        let blueColor = CGFloat(Float(arc4random() % 255) / 255)

        UIColor(red: redColor, green: greenColor, blue: blueColor, alpha: 1.0).set()

        viewRect.stroke()
        viewRect.fill()
    }

在这个代码中,我们使用arc4random()方法来生成一个随机数,这个方法会返回一个UInt32的随机数,然后使用这个方法来生成rgb颜色,使用该颜色填充和描边矩形区域。

然后我们需要重写一个初始化函数

override init(frame: CGRect) {
        super.init(frame: frame)

        setup()
    }

因为如果子类自己重写了初始化函数的话,也必须实现UIView的另一个初始化函数,但我们需要在初始化函数中对自定义的视图类加一些功能,所以我们就把这些添加的功能放在一个setup()方法当中了。必须实现的初始化方法如下:

required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        setup()
    }

在这个setup()方法中,我们可以设置视图的阴影并添加要求的手势

func setup() {
        //设置矩形区域圆角
        self.layer.cornerRadius = 20
        //设置阴影
        self.layer.shadowColor = UIColor.black.cgColor
        self.layer.shadowOffset = CGSize(width: 5, height: 5)
        self.layer.shadowOpacity = 0.8
        //设置视图的内容模式为重绘
        self.contentMode = .redraw

        //pan移动
        let panGesture = UIPanGestureRecognizer(target: self, action: #selector(pan(gesture:)))
        self.addGestureRecognizer(panGesture)

        //tap删除
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tap(gesture:)))
        self.addGestureRecognizer(tapGesture)

        //pinch缩放
        let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(pinch(gesture:)))
        self.addGestureRecognizer(pinchGesture)

        //rotation旋转
        let rotationGesture = UIRotationGestureRecognizer(target: self, action: #selector(rotation(gestrue:)))
        self.addGestureRecognizer(rotationGesture)
    }

其中设置视图内容模式为重绘的好处是本次作业要求视图的大小和方向可以改变,当设置为重绘后,在每次改变时,他会将视图重新绘制,这样就不会出现锯齿或毛边,但这样会牺牲一些显卡和内存的资源。
在将视图设置完成之后就可以向视图添加手势了。添加手势都是用UIGestrueRecognizer的子类。用法如上,在初始化手势时,需要传入一个手势对应的方法,我们分别将对应的方法列举如下:

//pan移动
    @objc func pan(gesture: UIPanGestureRecognizer) {
        self.center = gesture.location(in: superview)
    }

    //tap删除
    @objc func tap(gesture: UITapGestureRecognizer) {
        self.removeFromSuperview()
    }

    //pinch缩放
    @objc func pinch(gesture: UIPinchGestureRecognizer) {
        let scale = gesture.scale
        self.transform = self.transform.scaledBy(x: scale, y: scale)
        gesture.scale = 1
    }

    //rotation旋转
    @objc func rotation(gestrue: UIRotationGestureRecognizer) {
        let rotation = gestrue.rotation
        self.transform = self.transform.rotated(by: rotation)
        gestrue.rotation = 0
    }

在pinch手势和rotation手势当中,我们在使用完手势获取的值之后,都需要将它初始化一次,否则的话手势的值会在之前的基础上增加,比如pinch手势,你第一次放大了2倍,第二次想再放大2倍,你所预想的结果是最后的视图的大小是原始的4倍,但如果你不初始化的话,最后的结果会是2+4=6倍。rotation手势类似。

到这里,我们自定义视图需要实现的方法就已经完成了,接下来该在控制器当中来使用我们自定义的视图了。首先为了方便管理按钮,我们将UIWindow的根视图设置为导航栏控制器(下面这句代码添加到AppDelegate.swift当中)

self.window?.rootViewController = UINavigationController(rootViewController: ViewController())

然后我们在控制器的viewDidLoad()方法中,设置根视图的标题和背景颜色,然后想导航栏上添加三个按钮

title = "Custom View"
        self.view.backgroundColor = UIColor.white

        let addBtn = UIBarButtonItem(title: "添加", style: .plain, target: self, action: #selector(addView))
        let moveBtn = UIBarButtonItem(title: "移动", style: .plain, target: self, action: #selector(moveViews))
        self.navigationItem.rightBarButtonItems = [addBtn, moveBtn]

        let clearBtn = UIBarButtonItem(title: "清空", style: .plain, target: self, action: #selector(clearView))
        self.navigationItem.leftBarButtonItem = clearBtn

我们先来实现“添加”按钮的功能,当点击这个按钮后,我们要在随机位置生成随机大小的自定义视图,所以我们需要随机生成一个点,这个点就是自定义视图的左上角的点,然后再随机生成大小值,我们就用这个点和大小来初始化一个自定义视图,并添加到根视图上即可。

@objc func addView() {
        let maxWidth: CGFloat = 150

        let x = CGFloat(arc4random() % UInt32(self.view.bounds.width))
        let y = CGFloat(arc4random() % UInt32(self.view.bounds.height - 40)) + 40
        let point = CGPoint(x: x, y: y)

        let width = CGFloat(arc4random() % UInt32(maxWidth))
        let height = CGFloat(arc4random() % UInt32(maxWidth))
        let size = CGSize(width: width, height: height)

        let view = MyView(frame: CGRect(origin: point, size: size))
        self.view.addSubview(view)
    }

(博主为了不是随机生成的自定义视图太大,所以设置了其最大宽度)

然后实现“清除”按钮,用户点击这个按钮之后,会将控制器根视图上的所有子视图全部移除。所以要用的subViews方法返回根视图的子视图的数组,然后博主使用数组的map方法来移除视图,读者如果不熟悉map方法,也可以使用循环完成。

@objc func clearView() {
        self.view.subviews.map { $0.removeFromSuperview() }
    }

最后就是随机移动视图了。在iOS 4.0之前做动画的步骤非常繁琐,但在iOS 4.0之后,Apple公司提供了一个UIView 的工厂方法来实现一些简单的动画,我们这里使用这个就可以了。

@objc func moveViews() {
        self.view.subviews.map { (view) in
            let x = CGFloat(arc4random() % UInt32(self.view.bounds.width))
            let y = CGFloat(arc4random() % UInt32(self.view.bounds.height - 40)) + 40
            let point = CGPoint(x: x, y: y)

            UIView.animate(withDuration: 3, animations: {
                view.center = point
            })
        }
    }

这个方法的使用也很简单,我们只需要先随机生成一个点,然后调用UIView 的animate(withDuration:animations:)方法就可以实现了,在这个方法中,只需要填入动画结束之后的效果即可,可以改变视图的位置、大小、方向,甚至我们可以使用一些特殊的动画,比如淡入淡出等等,读者可以自行查找相关文章阅读。(如果读者们想省事的话,可以留言博主发学习笔记给你们,如果人数太多,博主也可以写一篇相关的博文)

到这里本次的作业就完成了。
下面看看运行的效果吧:
这里写图片描述

国央企创新负责人如何通过平台实现科研成果的快速识别与转化?.docx 科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。 立即下载

相关推荐

【毕设】基于LoRa的物联网控制器:从原理图到PCB的完整硬件设计指南

本文提供了一份完整的基于LoRa的物联网控制器硬件设计指南,涵盖从系统框图、原理图设计到PCB布局布线的全流程。详细讲解了电源电路、单片机最小系统、信号接口以及LoRa无线模块等核心模块的设计要点与抗干扰技巧,并分享了实用的调试心得,旨在帮助电子、物联网专业学生顺利完成毕业设计,掌握低功耗远距离物联网节点的硬件开发实践。

weixin_42126677的博客 306

GestureOverlayView(手势识别2)

GestureOverlayView:一种用于手势输入的透明覆盖层,用于识别各种手势,可以覆盖在控件上,也可以包含其他控件,有三个监听接口 1.GestureOverlayView.OnGestureListener//手势监听器 2.GestureOverlayView.OnGesturePerformed//手势执行监听器 3.GestureOverlayView.onGesturing

Ashurol的博客 746

金证股份软件测试笔试题面试题

boss上这家公司的HR找到了我,我看了一下这家公司的业务,是我以前做过的基金与证券。还是很感兴趣的,决定去面试看看情况。 (因为只是想去涨面试经验,没有想拿offer,一些回答有点不太对,为后面木有offer埋下伏笔。其实有点亏,毕竟走路过去,而且还花了3个小时) 地点在金证股份科技大楼8楼。 2月25号 主要分为笔试题和面试。 1、笔试题 进来的时候直接给我一份笔试题做,做了一个半小时吧。 分为3道选择题和1道SQL查询题、1道案例设计题 选择题都是考察SQL函数,可能日常生活中没有见过

全村的希望的博客 4451

Android中的动画总结

Android 动画 View Animation(视图动画) 概述: 视图动画,也叫 Tween (补间)动画可以在一个视图容器内执行一系列简单变换(位置、大小、旋转、透明度)。 譬如,如果你有一个 TextView 对象,您可以移动、旋转、缩放、透明度设置其文本,当然,如果它有一个背景图像,背景图像会随着文本变化。 补间动画通过 XML 或 Android 代码定义,建议使用 XML 文件定义,因为它更具可读性、可重用性 如下是视图动画相关的类继承关系: java 类名 xml 关..

haoxuhong的博客 1389

PID算法(位置式pid算法和增量式pid算法)

PID 算法是闭环控制系统中常用的算法,PID 分别是 Proportion(比例)、Integral(积分)、Differential(微分)的首字母缩写。它是一种结合比例、积分和微分三个环节于一体的闭环控。

m0_57678852的博客 2万+

【深度学习基础】Temporal Fusion Transformer

从下向上看:全连接(Dense) → ELU(指数线性激活函数(比relu好点,有利于模型收敛)) → 全连接(Dense) → 门控线性单元(Gate)(Gated Linear Units (GLUs)) → Layernorm。:一方面,它可以进行静态上下文变量和动态变量的融合,另一方面,通过门控进行了特征选择操作,门控体现在GLU(门控线性单元)中,用了sigmoid控制信息的通过程度,具有良好的适应性,能够自动选择有效信息,自适应地调整网络复杂性。输入:主输入,可选的上下文向量c。

weixin_41838721的博客 1225

Animation Foundations: Gesture 动画基础课程之姿势 Lynda课程中文字幕

Animation Foundations: Gesture 中文字幕 动画基础课程之姿势 中文字幕Animation Foundations: Gesture 什么让一个伟大的动画角色? 一个关键部分是手势 手势是我们如何通过身体表达想法或感受; 创造自然的手势让我们的角色感到可信 指导动画师Andrew Gordon,目前在皮克斯,带领我们了解动画中的手势原理,从手部和面部手势到全身姿势 他展...

BeautifulCoding的博客 367

Tessy学习系列(三):单元测试——官方例程isValueInRange

注意:工程名称以及路劲不能包含空格和中文

不吃鱼的猫的博客 2347

Swift4.0 Codable踩坑之派生类数据的保存

本以为之前使用Codable的过程中踩的坑已经够多了,今天博主有遇到一个坑,调了一个下午才解决,问题不大,但是中文的技术文里都很少涉及这个问题。问题描述:遵循了Codable协议的自定义类,派生出的子类JSON化与反JSON化。简单来说,就是这儿有一个类遵循了Codable协议,其自身可以很方便地使用JSONEncoder和JSONDecoder来JSON化和反JSON化。但是子类就不是那么方便了。

麻豆_matou 6659

(ICLR 2025)【源码讲解+复现】TIMER-XL: Long-Context Transformers for Unified Time Series Forecasting

本文提出了一种统一的多变量时序预测模型Timer-XL,其核心创新包括:1)采用自回归解码器架构,将多变量时序预测统一为next-token预测问题;2)设计TimeAttention机制,通过相对位置编码和因果掩码捕获时序位置和变量间交互;3)支持长上下文预训练以提升零样本迁移能力。模型架构包含嵌入层、时间感知注意力块和预测头,采用MSE损失进行端到端训练。实验表明该方法在多种时序任务上表现优异,特别是在长跨度预测和少样本场景下。代码实现提供了完整的模型定义、数据加载和训练流程,支持自定义配置参数。

1146

微信小程序 - {errCode: 10008, errno: 1500104, errMsg: “writeBLECharacteristicValue:fail write characteris

微信小程序errCode: 10008, errno: 1500104, errMsg: "writeBLECharacteristicValue:fail write characteristics error. 10008, errMsg=The value's length is invalid.",uni-app微信小程序报错,uniApp小程序调用蓝牙api报错,向低功耗蓝牙设备的某个特征写入数据时错误,UniApp微信小程序蓝牙API调用报错10008解决方案,蓝牙设备进行通信时,向设备写入数据

🏆 前端领域优质创作者 4431

Swift使用极光推送JPush的Demo

JPushDemo github项目地址 需要导入JPush框架,可以使用cocoapod导入,也可以手动导入 环境配置 配置环境可以参考极光推送的官方文档: iOS 证书设置指南 iOS SDK 集成指南 iOS SDK API 使用说明 待环境配置好了之后,就可以进入极光推送开始推送消息了 极光推送首页 推送使用示例如下: 发送通知 发送自定义消息 代码...

麻豆_matou 5649

YOLO11涨点优化:创新多尺度卷积注意力(MSCA)模块,小目标检测神器!

MSCA模块通过创新的多尺度设计,在保持计算效率的同时显著提升小目标检测能力。实验证明,在YOLOv5/v8等模型上嵌入MSCA后,mAP提升超过2%,小目标检测精度提升近4%,且计算代价增加极小。注意力机制的未来发展方向动态核尺寸:根据输入特征自适应调整卷积核大小跨模态融合:结合RGB与深度/热力图等多模态信息自监督优化:利用对比学习预训练注意力模块尝试在你的YOLO模型中插入MSCA模块,欢迎在评论区分享你的涨点结果!参考文献。

QQ_778132974的博客 470

Swift从相册选择图片,图文混排并且可以保存、上传数据

博主最近突发奇想想做一个自己的日记本App,在过程中遇到了一些坑,摸索了很久才做出一个简单的日记本功能。先来看看一下效果吧: 先来说说这次用到的一些东西吧: 1、UIImagePickerController:用来获取Photos里面的照片 2、UITexeView:用来做图文混排 3、NSKeyedArchiver和NSKeyedUnarchiver:保存和读取数据 具体的一些细节在过程

麻豆_matou 4001

SAP B1中文培訓教材_SDK

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

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

(作业)Swift类的属性与方法

话不多说,先贴作业要求 因为Person类需要一个枚举类型的gender,所以先定义枚举 //性别的枚举 enum Gender: Int { case male //男性 case female //女性 case unknow //未知 //重载>操作符,方便后面排序使用 static func >(lhs: Ge

麻豆_matou 3189

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Swift中UIScrollView与自定义上下滑动手势冲突

今天博主在封装下拉刷新时遇到了这个问题,在给UIScrollView添加UIPanGestureRecognizer时UIScrollView无法滑动了。博主也试了UITableView和UICollectionView,也出了同样的问题。在网上找了很久,终于解决了这个问题,只需要扩展UIScrollView使它遵循UIGestureRecognizerDelegate,并实现其中的一个方法就可以

麻豆_matou 2998

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

(作业)animation、transition、UIDynamicAnimator

第二个作业要求,先来看看吧,很有趣的一些动画效果 看要求,a和b都不是很麻烦,之前博主自学的时候接触过,第三个接触不多,老师上课时演示的时候有点着迷了,因为,如果有了这个UIDynamicAnimator,那么愤怒的小鸟就不是很难实现的游戏了(有这么神么?后面再介绍吧) 关于UIDynamicAnimator,优快云的前辈写得很不错先来看看第一个用animation实现视图位置、大小、转换

麻豆_matou 2941

字符串转换为整型

在Swift中,字符串转换为整型的方法有两种,我们在这里比较一下这两种方法的区别: 1、使用强制类型转换,代码如下:var str = "1234" var integer = Int(str) print(integer) // 输出1234 但如果换一个字符串 var str = "123,4" var integer = Int(str) print(intege

麻豆_matou 2822

Swift自定义类的存储

在Swift开发中,许多时候会涉及到存储自定义的类,不管是存储到本地文件还是远程服务器,都会涉及到编码和解码的问题。下面就来介绍一下在Swift中怎么存储自定义的类。 在Swift中存储自定义的类有两种方法,一种是Swift 3.0版本的NSCoding,还有一种是Swift 4.0版本的Codable。我们就两种方法来谈谈其中的区别吧。Swift 3.0: NSCoding在NSCoding这个

麻豆_matou 2667

(作业)TableView、Delegate、DataSource

来来来,继续作业系列的博客,老规矩了,直接上要求 这次作业涉及到iOS开发中最常用的一个UI组件UITableView,App Store中的几乎所有工具型和应用型App都使用了UITableView,而初学UITableView又不是那么容易,因为它涉及到很多代理和数据源的问题,但用熟练了,会觉得它非常地方便。 废话不多说了,先来完成要求吧,在这个过程中,博主会讲解一些细节方面的东西。首先是需

麻豆_matou 2318

Swift使用XMPPFramework做IM即时通信的Demo

上一篇文章处理了文本中表情的替换,现在来完成消息的发送功能吧(貌似前后并没有逻辑关系哈) 首先为了测试,我们需要下载spark工具,它可以连接openfire搭建的后台来完成即时通信的功能,方便测试。 下载地址点这儿 博主这里用的是Spark 2.8.3,各位可以根据自己所使用的平台不同选择对应的客户端下载。由于目前只是做移动端开发,所以后台的搭建各位可以自行google。 使用S...

麻豆_matou 2288

(作业)纯代码版HelloWorld,斯坦福iOS10教学视频

这次作业不止上一篇哦,还有第二个和第三个,第三个作业是按照斯坦福老爷子的视频做一个计算器,那个很简单,博主会在文章末尾附上链接,这次主要完成第二个作业。照常,要求先上 第一个作业就用的工程里自带的视图控制器来做的,这次需要将storyboard删除并自己创建自定义的视图控制器。我们需要删除的是工程创建完成之后的Main.storyboard和ViewController.swift,然后需要更

麻豆_matou 2129

framework和cocoapod加载图片问题

最近博主应实习公司要求封装一个下拉刷新上拉加载的控件,当功能实现之后想要集成到framework中和发布到cocoapod时都遇到了图片资源读取失败的问题,现将解决办法贴下。 framework中资源读取失败: 我们需要将资源打包到.bundle文件中(其实就是后缀为.bundle的文件夹,把资源放置其中即可). 然后根据你的目录结构来获取bundle let bundle = Bundl

麻豆_matou 2041

字符串表情替换

博主最近在研究IM的实现,不想直接使用第三方的界面,于是就开始了自己的作死之路。今天把包含表情格式的文本转换成相应的富文本贴一下吧。 首先,博主的表情格式是现在常用的中括号+标志符,类似[11]就是一个表情格式的字符。 我们需要实现的功能就是把形如: 你好[11] 这样的字符串变成: 你好 这样的字符串,具体的步骤就不再叙述了,注释已经很详细了 /// 将字符串转换为含有表情的富文本 ...

麻豆_matou 1976

Swift自定义下拉刷新、上拉加载(CZXRefresh的使用)

CZXRefresh github项目地址 可以cocoapod导入 也可以下载之后手动导入 先把CZXRefresh.xcodeproj文件拖到项目下 然后配置项目文件 添加framework 使用方法 在需要使用的文件中import框架即可使用 import CZXRefresh 下拉刷新和上拉加载都可以在UITableView和UICo

麻豆_matou 1969

(作业)使用autolayout和约束实现简单的界面布局

感觉好久没有写博客了,最近博主在复习java web准备考试,顺便为后面使用UIWebKit做铺垫吧。 今天就用xcode中的stroyboard实现自动布局,我们不用写一句代码,就能实现一些基本的布局。第一套布局这儿有两套布局,我们先来看看简单的那一套。 看这套布局特别简单,只需要创建三个UIView,然后让他们总的宽度等于屏幕的宽度,然后各自的长宽相等就可以了。接下来看一步一步的操作

麻豆_matou 1852
上一篇: Swift4.0 Codable踩坑之派生类数据的保存
下一篇: (作业)ActionSheet、Alert
麻豆_matou
博客等级 码龄10年 41粉丝 46原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值