(作业)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+工具与数智化解决方案,推动科技创新与产业创新智能化发展。 立即下载

相关推荐

AI训练师团队管理运营思路

工具运营AI训练师主要是支撑运营,协助算法和运营提高托管机器人的解决能力,以协助降低业务场景熔断与优化场景识别为核心运营目标,通过算法聚类、标注分析等方式,结合业务知识,提供精准、清晰的标注数据和解决方案,确保训练效果满足需求。过程中需要与算法、运营一块参与模型搭建和数据验收,并且负责核心指标和数据日常的跟踪维护。④针对知识库已有意图进行梳理和分析,反馈运营评估缺失或合并意图优化方向。③对语料数据进行挖掘、清洗,解除缠绕、冗余等问题导致的未识别。①线上case分析,及时发现识别问题导致的托管熔断问题。

qq_25438419的博客 1085

GestureOverlayView(手势识别2)

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

Ashurol的博客 746

[uboot] (第四章)uboot流程——uboot编译流程

uboot编译流程简单介绍

ooonebook的博客 1万+

Android中的动画总结

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

haoxuhong的博客 1389

Oracle Scheduler任务故障诊断 实战指南

当基础环境无异常时,需聚焦任务本身的配置与状态。定义(JOB)→ 调度(SCHEDULE)→ 执行(SLAVE进程)→ 日志(LOG),每个环节都可能存在卡点。Oracle Scheduler任务的“隐性故障”看似棘手,实则是环境配置、资源竞争、时间逻辑等问题的集中体现。通过本文的诊断工具和排查思路,你可以构建从“基础环境→任务配置→执行链路→日志追踪”的全维度分析体系,让每一个“消失”的任务都无所遁形。

Nuzbb的博客 1073

直流有刷电机控制 - 认识电机(一)

电机控制学习

u011030644的博客 917

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

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

BeautifulCoding的博客 367

SAP Business One自定义表与字段实战:从零构建企业专属数据模型

本文详细介绍了如何在SAP Business One中创建自定义表与字段,从零构建企业专属数据模型。通过实战案例和避坑指南,帮助用户掌握业务适配、流程优化和权限隔离等关键技巧,提升系统灵活性和数据管理效率。特别适合需要扩展标准功能的SAP Business One用户。

weixin_28730927的博客 362

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

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

麻豆_matou 6659

基于STM32的多传感器融合的设施农业小型搬运机器人避障控制系统设计

针对设施农业场景中狭窄通道、障碍物多样(如农机具、作物植株、水管)的特点,设计一款基于 STM32 的小型搬运机器人避障控制系统。系统通过多传感器融合实现 360° 环境感知,采用模糊 PID 控制算法实现平滑避障,满足温室、大棚等场景的搬运需求。通过在温室环境测试,系统可实现对直径≥5cm 障碍物的有效检测(检测距离误差≤5%),避障转向半径≤30cm,平均功耗≤15W。后续可通过增加激光雷达(如 TFmini)提升远距离障碍物检测能力,结合 SLAM 算法实现路径规划。

weixin_42300449的博客 860

Plant Simulation 快速建模与布局(3)——自动生成的对象 代码“安全”删除管理

《PlantSimulation快速布局建模课程》教授利用SimTalk语言实现高效建模的技术要点,包括批量对象创建、阵列布局、属性管理及自动连接功能。重点讲解对象安全删除机制,通过existsObject检查对象存在性后使用deleteObject方法删除,避免程序报错。课程提供完整代码示例,展示如何通过循环结构实现矩阵布局对象的创建与安全删除,确保代码健壮性,显著提升建模效率。

qq_31964455的博客 116

Swift使用极光推送JPush的Demo

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

麻豆_matou 5649

半导体工艺仿真:离子注入工艺仿真_(8).损伤和缺陷仿真

离子注入工艺在半导体制造中是一个重要的步骤,用于在半导体材料中引入特定的掺杂剂。然而,离子注入过程中不可避免地会产生损伤和缺陷,这些损伤和缺陷会直接影响器件的性能和可靠性。因此,对离子注入工艺中的损伤和缺陷进行仿真研究是必不可少的。本节将详细介绍如何使用仿真软件对离子注入过程中的损伤和缺陷进行建模和分析。

2401_87715305的博客 1339

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

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

麻豆_matou 4001

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

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

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

麻豆_matou 3189

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

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

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

麻豆_matou 2998

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

(作业)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、付费专栏及课程。

余额充值