前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >swift动画 —— 颜色渐变以及转换动画

swift动画 —— 颜色渐变以及转换动画

作者头像
CC老师
发布于 2022-01-14 06:56:48
发布于 2022-01-14 06:56:48
2.2K00
代码可运行
举报
运行总次数:0
代码可运行

这篇文章是通过结合使用CAGradientLayer、CABasicAnimation

以及CAAnimationDelegate来达到颜色渐变以及转换的动画,

下面是今天要达成的效果图:

首先创建一个CAGradientLayer和几个自己喜欢的颜色,让VC持有。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
let colorOne = #colorLiteral(red: 0.2392156869, green: 0.6745098233, blue: 0.9686274529, alpha: 1).cgColor
let colorTwo = #colorLiteral(red: 0.8078431487, green: 0.02745098062, blue: 0.3333333433, alpha: 1).cgColor
let colorThree = #colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1).cgColor
let gradient = CAGradientLayer()

(滑动显示更多)

接下来为gradient赋值,将其frame等同于视图的大小,然后颜色先设置为colorOne和colorTwo,起始点和结束点分别为CGPoint(x:0, y:0)和CGPoint(x:1, y:1),并设置让其在后台线程异步绘制,最后添加到view的layer的sublayer中。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  gradient.frame = self.view.bounds
  gradient.colors = [colorOne,colorTwo]
  gradient.startPoint = CGPoint(x:0, y:0)
  gradient.endPoint = CGPoint(x:1, y:1)
  gradient.drawsAsynchronously = true
  self.view.layer.insertSublayer(gradient, at: 0)

(滑动显示更多)

现在运行后会得到下面的结果:

颜色渐变是做到了,那么如何做到颜色渐变的转换呢?这里还是需要用到CABasicAnimation.

在gradient创建完之后,添加并调用一个方法animateGradient,在里面添加一个keyPath为colors的CABasicAnimation,设置动画时长为3s,设置结束值等一系列属性。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    func animateGradient() {
     let gradientChangeAnimation = CABasicAnimation(keyPath: "colors")
        gradientChangeAnimation.duration = 3.0
        gradientChangeAnimation.toValue =  [colorTwo,colorThree]
        gradientChangeAnimation.fillMode = CAMediaTimingFillMode.forwards
        gradientChangeAnimation.isRemovedOnCompletion = false
        gradient.add(gradientChangeAnimation, forKey: "gradientChangeAnimation")
      }

(滑动显示更多)

这里就完成了转换动画。但是这里有个问题就是这里只转换了一次,无法转换多次颜色。那么这里就需要设置好toValue,让每次的toValue都不一样。

创建一个currentGradient和gradientSet让VC持有。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 var currentGradient: Int = 0
 var gradientSet = [[CGColor]]()

在animateGradient中每次调用的时候,都对currentGradient的值进行判断和处理。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   if currentGradient < gradientSet.count - 1 {
            currentGradient += 1
        } else {
            currentGradient = 0
        }

(滑动显示更多)

并修改gradientChangeAnimation的toValue:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
let gradientChangeAnimation = CABasicAnimation(keyPath: "colors")
gradientChangeAnimation.duration = 3.0
gradientChangeAnimation.toValue = gradientSet[currentGradient]
gradientChangeAnimation.fillMode = CAMediaTimingFillMode.forwards
gradientChangeAnimation.isRemovedOnCompletion = false
gradientChangeAnimation.repeatCount = Float.infinity
gradient.add(gradientChangeAnimation, forKey: "gradientChangeAnimation")

(滑动显示更多)

这里运行后发现还是不行,还是只有一种颜色的转换,这是因为这里只调用了一次animateGradient()。那么如何在合适的时机,也就是动画结束的时候再调用一次animateGradient呢?这里就需要用到CAAnimationDelegate。

在CAAnimationDelegate的animationDidStop方法中重新调用animateGradient。注意这里的gradient.colors 也要改变,否则就会一直是[colorOne, colorTwo]到其他颜色的变换。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {

        // if our gradient animation ended animating, restart the animation by changing the color set
        if flag {
            gradient.colors = gradientSet[currentGradient]
            animateGradient()
        }
    }

(滑动显示更多)

完整代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import UIKit

class ViewController: UIViewController, CAAnimationDelegate {
    let colorOne = #colorLiteral(red: 0.2392156869, green: 0.6745098233, blue: 0.9686274529, alpha: 1).cgColor
    let colorTwo = #colorLiteral(red: 0.8078431487, green: 0.02745098062, blue: 0.3333333433, alpha: 1).cgColor
    let colorThree = #colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1).cgColor
    let gradient = CAGradientLayer()

    var currentGradient: Int = 0
    var gradientSet = [[CGColor]]()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        NotificationCenter.default.addObserver(self, selector: #selector(handleEnterForeground), name: UIApplication.willEnterForegroundNotification, object: nil)

    }
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()

        createGradientView()
    }

    @objc private func handleEnterForeground() {
        animateGradient()
    }

    func animateGradient() {
        // cycle through all the colors, feel free to add more to the set
        if currentGradient < gradientSet.count - 1 {
            currentGradient += 1
        } else {
            currentGradient = 0
        }

        // animate over 3 seconds
        let gradientChangeAnimation = CABasicAnimation(keyPath: "colors")
        gradientChangeAnimation.duration = 3.0
        gradientChangeAnimation.toValue = gradientSet[currentGradient]
        gradientChangeAnimation.fillMode = CAMediaTimingFillMode.forwards
        gradientChangeAnimation.isRemovedOnCompletion = false
        //gradientChangeAnimation.repeatCount = Float.infinity
        gradientChangeAnimation.delegate = self
        gradient.add(gradientChangeAnimation, forKey: "gradientChangeAnimation")
    }

    func createGradientView() {

        // overlap the colors and make it 3 sets of colors
        gradientSet.append([colorOne, colorTwo])
        gradientSet.append([colorTwo, colorThree])
        gradientSet.append([colorThree, colorOne])

        // set the gradient size to be the entire screen
        gradient.frame = self.view.bounds
        gradient.colors = gradientSet[currentGradient]
        gradient.startPoint = CGPoint(x:0, y:0)
        gradient.endPoint = CGPoint(x:1, y:1)
        gradient.drawsAsynchronously = true

        self.view.layer.insertSublayer(gradient, at: 0)

        animateGradient()
    }
    func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {

        // if our gradient animation ended animating, restart the animation by changing the color set
        if flag {
            gradient.colors = gradientSet[currentGradient]
            animateGradient()
        }
    }

}

(滑动显示更多)

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-10-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 HelloCoder全栈小集 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
秒懂HTTPS接口(接口测试篇)
在秒懂HTTPS接口(实现篇)中我们通过Java实现了一个简单的HTTPS项目示例,下面我们来测试下我们上面这个HTTPS接口(Java版)
高楼Zee
2019/07/17
3.4K0
秒懂HTTPS接口(接口测试篇)
httpclient发送https协议请求以及javax.net.ssl.SSLHandshakeException解决办法
本人在做接口自动化的过程中,遇到了请求第三方https协议请求,在经过了短暂的知识重新学习之后,写完代码执行起来总是遇到一个异常,在用客户端执行请求的时候抛出来的,下面是异常的信息:
FunTester
2019/10/17
3.9K0
【Java爬虫】005-HttpClient学习笔记(补充:网页内容获取相关)
使用HttpClient可设置三种超时时间:RequestTimeout(获取连接超时时间)、ConnectTimeout(建立连接超时时间)、SocketTimeout(获取数据超时时间)。配置这三种超时时间,需要用到HttpClient的RequestConfig类中的方法custom(),该方法返回值为实例化的内部类Builder(配置器),其功能是配置先关请求的字段,还可以设置代理(proxy)、Cookie规范(cookieSpec)、是否允许HTTP相关认证等;
訾博ZiBo
2025/01/06
1330
如何让Apache HttpClient 支持SSL配置?
按照Httpclient的设计要求编写一个响应信息处理类,也可以使用匿名内部类或者Lambda表达式。
阿东
2024/05/08
9690
如何让Apache HttpClient 支持SSL配置?
springboot restTemplate https请求 忽略ssl证书
与http请求不同的是,https使用restTemplate的时候需要手动创建对象,并传入参数。而http直接用Autowired注入restTemplate对象就可以直接使用。
艾瑞莉娅
2021/05/18
8.5K0
封装httpClient工具类进行get、post、put、delete的http接口请求,可添加请求头与参数,支持多线程
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/157763.html原文链接:https://javaforall.cn
全栈程序员站长
2022/09/18
2.7K0
HttpClient 辅助类,简化调用
默认带有的INSTANCE 可以请求所有的HTTPS 和HTTP,使用带有证书的构造函数自己构建的client对象可以请求需要证书验证的HTTPS地址和HTTP。client对象为线程安全的,所以一个client允许在多个线程下使用。不要关闭client对象,否则多个线程使用同一个client就会有问题。
前Thoughtworks-杨焱
2021/12/08
8680
【连载 29】HttpClient详解之客户端
在当今高性能、高并发的网络应用开发中,HTTP客户端作为系统间通信的核心组件,其配置优化直接影响着整体性能表现。Apache HttpClient作为Java生态中最成熟、功能最丰富的HTTP客户端工具库,为开发者提供了高度可定制的连接管理、请求控制和异常处理机制。本节将深入剖析HttpClient的核心配置项,从连接池管理、SSL安全策略到超时控制、重试机制,全面讲解如何构建一个高性能、高可靠的HTTP客户端实例。通过精细调节连接数、路由策略、报文约束等参数,开发者能够有效提升系统吞吐量,避免资源浪费,同时掌握多用户并发场景下的Cookie管理技巧和异常请求的智能重试策略,为构建企业级应用通信框架奠定坚实基础。
FunTester
2025/04/06
1580
【连载 29】HttpClient详解之客户端
Http接口调用示例教程
本文链接:https://blog.csdn.net/u014427391/article/details/97398717
SmileNicky
2019/08/29
1.1K0
HTTP 请求工具类
坐标 <dependency> <groupId>net.sf.json-lib</groupId> <artifactId>json-lib</artifactId> <version>2.1</version> <classifier>jdk15</classifier> </dependency> 工具类 package com.baomidou.springboot.uti
高大北
2022/06/14
9750
Java发送HTTPS请求
上篇文章介绍了 java 发送 http 请求,大家都知道发送http是不安全的 。我也是由于对接了其他企业后总结了一套发送 https的工具。大家网上找方法很多的,但是可不是你粘过来就能用啊,我也是踩过坑的,所以我这个工具,只要粘贴到你们自己项目里就可以用。我的工具跟网上没什么区别,唯一的区别是我亲身实战过,把需要注意的细节列出来,不让大家浪费时间。
胖虎
2019/06/26
5.4K0
HttpClient详细解释
Http协议的重要性相信不用我多说了,HttpClient相比传统JDK自带的URLConnection,增加了易用性和灵活性(具体区别,日后我们再讨论),它不仅是客户端发送Http请求变得容易,而且也方便了开发人员测试接口(基于Http协议的),即提高了开发的效率,也方便提高代码的健壮性。因此熟练掌握HttpClient是很重要的必修内容,掌握HttpClient后,相信对于Http协议的了解会更加深入。
全栈程序员站长
2022/11/16
1.5K0
HttpClient工具类
基于restTemplate的httpClient通用工具类。 方案 import lombok.extern.slf4j.Slf4j; import org.springframework.http.*; import org.springframework.util.MultiValueMap; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.Re
earthchen
2020/09/24
1.1K0
java模拟http/https post请求
之前每次代码执行到上述代码的第二行的时候,会等一段时间然后会捕获到Exception异常。
翎野君
2023/05/12
1.2K0
java模拟http/https post请求
日常开发必备神器 HttpUtil 分享(超详细)
最近在工作中需要在后台调用各种上传、下载、以及第三方服务接口,经过研究决定使用 HttpClient,自己封装了一个 HttpClient 工具类,简单轻松的实现get、post、put、delete 以及上传、下载请求,在此分享给大家。
Java极客技术
2022/12/04
3.2K1
工具篇:apache-httpClient 和 jdk11-HttpClient的使用
apache HttpClient 是 java项目里 较为常用的组件之一;对接外部服务时,各个商家提供的接口是各式各样的,有自己的要求,因此要定制对应的请求客户端。httpClient是一个不错的选择
潜行前行
2021/12/02
2K0
工具篇:apache-httpClient 和 jdk11-HttpClient的使用
【微信开发】 红包接口开发
参考网上好几个版本的答案咯~ 分装 红包工具类 : package com.tepusoft.web.weixin.utils; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.security.KeyStore; import java.security.NoSuchAlgorithmEx
冷冷
2018/02/08
2.6K0
CloseableHttpClient简单使用实例[通俗易懂]
import java.io.BufferedReader; import java.io.IOException; import java.nio.charset.Charset; import java.security.KeyManagementException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException;
全栈程序员站长
2022/07/25
9030
Apache HttpClient4使用教程
HttpClient默认情况 会对302、307的GET和HEAD请求以及所有的303状态码做重定向处理
全栈程序员站长
2022/09/15
7970
HttpClient与CloseableHttpClient
起因是最近做的一个历史遗留项目,需要加些新需求,在本机进行压测时,发现在并发600的状态下跑一段时间后,就会开始偶现500的错误。可能是老项目用的人少(B2B的项目),实际部署后以前也没有人反馈过这个问题,大致跟踪了下日志,发现是系统在调用第三方服务出现异常,这种情况原因很多,需要仔细看异常堆栈打出来的Exception信息,将问题范围缩小并求证,这次抛出的是java.net.SocketException: Too many open files。表明服务器上开启了过多socket句柄,超上限了(一般是1024),这种情况下是无法建立新的网络连接的。
全栈程序员站长
2022/07/25
1.8K0
HttpClient与CloseableHttpClient
相关推荐
秒懂HTTPS接口(接口测试篇)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验