JBButton 0.1.0

JBButton 0.1.0

测试已测试
Lang语言 SwiftSwift
许可证 MIT
发布最后发布2016 年 6 月
SPM支持 SPM

Jérôme B. 维护。



JBButton 0.1.0

  • 作者
  • Jérôme Boursier

JBButton

JBButton 是用 Swift 编写的不可配置和可动画的按钮。它提供了一个加载状态,完全可定制,从而避免使用阻塞的HUD。

Connect Facebook Go! KeepBrowsing Key LogIn
PinIt Tweet

功能

  • [x] 可以直接在界面构建器(IBDesignable)中配置
  • [x] 委托方法处理点击手势
  • [x] 可动画的触摸开始和结束
  • [x] 处理加载状态/提供默认加载器
  • [x] 易于使用的方法

需求

  • iOS 8.0+
  • Xcode 7.3+


安装

手动

如果您不想使用上述任何依赖管理器,您可以通过下载 JBButton.framework 并将其添加到项目中来手动将 JBButton 集成到您的项目中。


使用方法

创建一个简单的 JBButton

1. 添加一个 UIView

将一个 UIView 拖拽到您想添加 JBButton 的 ViewController 中。在身份检查器中,将其设置为 JBButton 自定义类,并按 Enter。它将自动为您设置正确的模块。然后,只需在属性检查器中对其进行自定义!作为按钮是一个 IBDesignable 组件,大部分布局可以在故事板中完成。查看下面的简单示例。

界面构建器 结果
IBDesignable Tweet

2. 在您的 ViewController 中声明它

不要忘记首先导入 JBButton 🙃

根据您正在使用的语言

@IBOutlet weak var tweet: JBButton!

或者

@property(nonatomic, weak) IBOutlet JBButton *tweet;

如果您想与按钮交互,则您的类可以扩展 JBButtonDelegate 协议,以处理 didTapOnButton(:) 方法,并将 delegate 设置为代码或界面构建器中。

3. 👀可检查项说明

界面构建器中有许多 IBInspectable。您可以通过查看代码文档获取更多详细信息,或者参考以下表格。

可检查项 类型 文档 默认值
title String? 要显示的文本 "击中我!"
titleColor UIColor 文本颜色 UIColor.blackColor()
标题对齐方式 Int 文本对齐方式。将其视为 NSTextAlignment.<alignment>.rawValue 1 (即 NSTextAlignmentCenter
图片 UIImage? 要显示的图片 无默认值
图片颜色 UIColor 如果以模板方式呈现,图片的颜色 UIColor.blackColor()
图片渲染模式 Int 图片的渲染模式。
0 表示 .Original
1 表示 .Template
0
图片位置 Int 图片在按钮中的位置。
0 表示 .Top
1 表示 .Bottom
2 表示 .Left
3 表示 .Right
4 表示 .Centered
0
圆角半径 CGFloat 按钮的圆角半径 0
边框宽度 CGFloat 按钮的边框宽度 1
borderColor  UIColor 按钮的边框颜色 UIColor.blackColor()
内边距 CGFloat 按钮的内边距 0
高亮 Bool 决定按钮是否在点击时高亮显示 true

在下面的示例中,
imageRenderingMode 设置为模板,
imagePosition 设置为顶部,
highlight 设置为 true,…

快速点击 较长时间的点击
TweetTap TweetTapLong

4. 👀可访问属性和方法

属性或方法 文档
delegate: JBButtonDelegate? 按钮的代理。可以在代码或IB中设置。
customTouchesBeganAnimations: CAAnimationGroup? 自定义触摸开始动画组。在代码中设置。
customTouchesEndedAnimations: CAAnimationGroup? 自定义触摸结束动画组。在代码中设置。
customLoadingAnimations: CAAnimationGroup? 自定义加载动画组。在代码中设置。
hideTitleOnLoad: Bool 告诉按钮是否在加载时隐藏标题。
isLoading: Bool 告诉您按钮是否处于加载状态。
setTitleFont(font: UIFont) 为标题设置自定义字体。
setTitleText(title: String) 设置新的标题。

动画

按钮动画已经变得很简单。您可以设置属性,例如 customTouchesBeganAnimationscustomTouchesEndedAnimations,以传递 CAAnimationGroup

示例

// Scale animation
let scaleDown = CASpringAnimation(keyPath: "transform.scale")
scaleDown.damping = 0.4
scaleDown.initialVelocity = 12.0
scaleDown.fromValue = 1.0
scaleDown.toValue = 0.9

// Group set to customTouchesBeganAnimations
let group = CAAnimationGroup()
group.animations = [scaleDown]
group.duration = 0.35
group.fillMode = kCAFillModeForwards
group.removedOnCompletion = false
self.pinIt.customTouchesBeganAnimations = group

// Reverse scale animation
let scaleUp = CASpringAnimation(keyPath: "transform.scale")
scaleUp.damping = 0.4
scaleUp.initialVelocity = 12.0
scaleUp.fromValue = 0.9
scaleUp.toValue = 1.0

// Rotation animation
let rotate = CABasicAnimation(keyPath: "transform.rotation")
rotate.fillMode = kCAFillModeBoth
rotate.toValue = (360 * M_PI / 180)

// Group set to customTouchesEndedAnimations
let group2 = CAAnimationGroup()
group2.animations = [scaleUp, rotate]
group2.duration = 0.35
group2.fillMode = kCAFillModeForwards
group2.removedOnCompletion = false 
self.pinIt.customTouchesEndedAnimations = group2

结果

PinItAnimated

加载

按钮可以用来避免令人反感的HUDs。它提供方便的方法来处理长时间加载过程。它可以进行相当好的定制,但示例会说明一切。

示例

1. 带默认加载器的简单按钮 - 通过Facebook登录
1.1 我们想要什么?

一个简单的Facebook登录按钮,包含文本和Facebook标志。我们希望它在连接过程中为 “加载中”

该组件的默认行为是在加载过程中用 UIActivityIndicatorView 替换图片。

1.2. 结果

FacebookLoader

1.3. 示例代码

不是很多要做… 对于这种需求,IB就足够了。

要激活“加载状态”,您只需实现以下方法 didTapOnButton(:)

func didTapOnButton(sender: JBButton!) {
    if sender == self.signInWithFacebook {
        sender.startLoading(withTitle: "Signing in")
    }
}

不带任何配置的方法 startLoading(:) 将替换图像为默认加载器,并替换标题。您可以不带 withTitle 参数调用该方法。

1.4 替代方案

viewDidLoad(:) 中,您可以告诉按钮

self.signInWithFacebook.hideTitleOnLoad = true

在这种情况下,加载时将隐藏文本,加载器将居中。

FacebookLoaderNoText

2. 简单按钮带自定义加载器 - 1Password 连接
2.1 我们想要什么?

一个简单的 1Password 连接按钮,包含文本和 1Password 徽标。我们希望它在连接过程中处于“加载”状态。我们想要添加自定义加载器。

2.2 结果

OnePasswordLoader

2.3 示例代码
// Creating a custom indicator
let indicator = NVActivityIndicatorView(frame: CGRect.zero, type: NVActivityIndicatorType.Pacman, color: UIColor.whiteColor(), padding: 0)
// Setting it to the button
self.onePassword.setCustomLoader(indicator, startAnimationBlock: { () in
    indicator.startAnimation()
}, stopAnimationBlock: { () in
    indicator.stopAnimation()
})

// Set the font
self.onePassword.setTitleFont(UIFont(name: "Menlo-Regular", size: 18)!)

⚠️🎵注意 #1:创建自定义指示器时,将框架设置为 CGRect.zero。这会让按钮自动计算框架。⚠️

⚠️🎵注意 #2:创建自定义指示器时,必须在按钮的 startAnimationBlockstopAnimationBlock 中定义开始和停止方法,以便按钮可以正确地开始和停止动画。在此处,我使用了来自 @ninjaprox 的精彩 pod From NVActivityIndicatorView。这些指标响应自定义开始和停止方法 startAnimation()stopAnimations()⚠️

func didTapOnButton(sender: JBButton!) {
    if sender == self.onePassword {
        sender.startLoading()
    }
}
2.4 替代方案

viewDidLoad(:) 中,您可以告诉按钮

self.onePassword.hideTitleOnLoad = true

在这种情况下,文本将在加载时隐藏,加载器将居中(如果框架设置为 CGRect.zero)。

OnePasswordLoaderNoText

3. 在图像按钮上随机动画 - 关键按钮
3.1 我们想要什么?

一个包含仅图像的边框按钮。我们希望“加载”过程是强化的。👯👯.

3.2 结果

KeyLoader

3.3 示例代码
// Pulse animation
let pulseAnimation = CABasicAnimation(keyPath: "transform.scale")
pulseAnimation.duration = 2
pulseAnimation.toValue = 1.15

// Rotate animation
let rotateLayerAnimation = CABasicAnimation(keyPath: "transform.rotation")
rotateLayerAnimation.duration = 0.5
rotateLayerAnimation.beginTime = 0.5
rotateLayerAnimation.fillMode = kCAFillModeBoth
rotateLayerAnimation.toValue = (360 * M_PI / 180)

// Group set to customLoadingAnimations
let group = CAAnimationGroup()
group.animations = [pulseAnimation, rotateLayerAnimation]
group.duration = 2
group.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
group.autoreverses = true
group.repeatCount = FLT_MAX
self.key.customLoadingAnimations = group
func didTapOnButton(sender: JBButton!) {
    if sender == self.key {
        sender.startLoading()
    }
}
4. 黑色带阴影按钮 - 去吧!按钮
4.1 我们想要什么?

一个带“去吧!”标题的黑色按钮。我们希望它有阴影。我们希望“加载”状态要微妙,有一个自定义漂亮的加载器。我们希望当按下按钮时,阴影消失,当我们停止按下按钮时重新出现——当然,以动画的形式。

4.2 结果

GoLoader

4.3 示例代码
// Set the title font
self.go.setTitleFont(UIFont(name: "Copperplate-Light", size: 18.0)!)

// Hide the shadow on tap
let hideShadowAnimation = CABasicAnimation(keyPath: "shadowOpacity")
hideShadowAnimation.fromValue = 0.5
hideShadowAnimation.toValue = 0

let hideShadow = CAAnimationGroup()
hideShadow.animations = [hideShadowAnimation]
hideShadow.duration = 0.2
hideShadow.fillMode = kCAFillModeForwards
hideShadow.removedOnCompletion = false
self.go.customTouchesBeganAnimations = hideShadow

// Show the shadow when tap stops
let showShadowAnimation = CABasicAnimation(keyPath: "shadowOpacity")
showShadowAnimation.fromValue = 0
showShadowAnimation.toValue = 0.5

let showShadow = CAAnimationGroup()
showShadow.animations = [showShadowAnimation]
showShadow.duration = 0.2
showShadow.fillMode = kCAFillModeForwards
showShadow.removedOnCompletion = false
self.go.customTouchesEndedAnimations = showShadow

// Add a shadow
self.go.layer.masksToBounds = false
self.go.layer.shadowColor = UIColor.blackColor().CGColor
self.go.layer.shadowOffset = CGSize(width: 5, height: 5)
self.go.layer.shadowOpacity = 0.5

// Add a custom loader
let indicator = NVActivityIndicatorView(frame: CGRect.zero, type: NVActivityIndicatorType.BallPulseSync, color: UIColor.whiteColor(), padding: 0)
self.go.setCustomLoader(indicator, startAnimationBlock: { () in
    indicator.startAnimation()
    }, stopAnimationBlock: { () in
indicator.stopAnimation()
})
func didTapOnButton(sender: JBButton!) {
    if sender == self.go {
        sender.startLoading()
    }
}
4.4. ⚠️故障排除

要以那种方式向 UIView 添加阴影,它可能没有圆角。为了将阴影添加到圆角的 UIView 中,请参看下面的示例。

5. 渐变层叠圆角阴影动画按钮 - 登录按钮
5.1. 我们想要什么?

基本上是一个按钮。但是…我们希望它有一个渐变层,是圆角的,有阴影,在加载时动画,在点击时动画,并且包含自定义的登录按钮。这很简单,对吧?👯💃

5.2. 结果

GradiantLoader

5.3. 示例代码

由于我想有一个圆角和阴影的按钮,我需要在 IB 中将相同大小的 JBButton 嵌入到UIView中。

// Set the title font
self.gradientLogin.setTitleFont(UIFont(name: "AmericanTypewriter-Bold", size: 18.0)!)

// Create a gradiant layer
let c1 = UIColor(red: 0/255, green: 161/255, blue: 0/255, alpha: 1)
let c2 = UIColor(red: 0/255, green: 161/255, blue: 255/255, alpha: 1)
let gradientLayer = CAGradientLayer()
gradientLayer.frame = self.gradientLogin.bounds
gradientLayer.colors = [c1.CGColor, c2.CGColor]
gradientLayer.startPoint = CGPoint(x: 0, y: 0)
gradientLayer.endPoint = CGPoint(x: 1, y: 1)
self.gradientLogin.layer.addSublayer(gradientLayer)
// Rounded
self.gradientLogin.cornerRadius = 25

// Add the custom indicator
let indicator = NVActivityIndicatorView(frame: CGRect.zero, type: NVActivityIndicatorType.LineScalePulseOut, color: UIColor.whiteColor(), padding: 0)
self.gradientLogin.setCustomLoader(indicator, startAnimationBlock: { () in
    indicator.startAnimation()
    }, stopAnimationBlock: { () in
indicator.stopAnimation()
})

// Add a shadow to the container view
self.gradientLoginContainer.layer.masksToBounds = false
self.gradientLoginContainer.layer.shadowColor = UIColor.blackColor().CGColor
self.gradientLoginContainer.layer.shadowOffset = CGSize(width: 5, height: 5)
self.gradientLoginContainer.layer.shadowOpacity = 0.5

// Scale animation
let scaleSmallAnimation = CASpringAnimation(keyPath: "transform.scale")
scaleSmallAnimation.fromValue = 1.0
scaleSmallAnimation.toValue = 0.9
scaleSmallAnimation.damping = 0.4
scaleSmallAnimation.initialVelocity = 12.0
// Group set to customTouchesBeganAnimations
let touchesBegan = CAAnimationGroup()
touchesBegan.animations = [scaleSmallAnimation]
touchesBegan.duration = 0.2
touchesBegan.fillMode = kCAFillModeForwards
touchesBegan.removedOnCompletion = false
self.gradientLogin.customTouchesBeganAnimations = touchesBegan

// Scale animation
let scaleBigAnimation = CASpringAnimation(keyPath: "transform.scale")
scaleBigAnimation.fromValue = 0.9
scaleBigAnimation.toValue = 1.0
scaleBigAnimation.damping = 0.4
scaleBigAnimation.initialVelocity = 12.0
// Group set to customTouchesEndedAnimations
let touchesEnded = CAAnimationGroup()
touchesEnded.animations = [scaleBigAnimation]
touchesEnded.duration = 0.2
touchesEnded.fillMode = kCAFillModeForwards
touchesEnded.removedOnCompletion = false
self.gradientLogin.customTouchesEndedAnimations = touchesEnded

// Pulse animation
let pulseAnimation = CABasicAnimation(keyPath: "transform.scale")
pulseAnimation.duration = 2
pulseAnimation.toValue = 0.85
// Group set to customLoadingAnimations
let group = CAAnimationGroup()
group.animations = [pulseAnimation]
group.duration = 2
group.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
group.autoreverses = true
group.repeatCount = FLT_MAX
self.gradientLogin.customLoadingAnimations = group
func didTapOnButton(sender: JBButton!) {
    if sender == self.gradientLogin {
        sender.startLoading()
    }
}