我需要创建从右到左过渡的幻灯片菜单,我已经成功创建了它,但是当我按菜单图标时,向我显示幻灯片菜单without animation!而且我无法通过hide it在幻灯片菜单之外按!
如何创建从右到左过渡的动画? 在幻灯片菜单外按时如何设置隐藏?
SlideInMenu类:
import UIKit
class SlideInMenu: NSObject, UIViewControllerAnimatedTransitioning {
var isPresenting = false
let dimmingView = UIView()
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 3
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
guard let toVC = transitionContext.viewController(forKey: .to),
let fromVC = transitionContext.viewController(forKey: .from) else { return }
let containerView = transitionContext.containerView
let finalWidth = toVC.view.bounds.width * 0.8375
let finalHeight = toVC.view.bounds.height
if (isPresenting) {
dimmingView.backgroundColor = UIColor(red: 32/255, green: 70/255, blue: 86/255, alpha: 0.8)
containerView.addSubview(dimmingView)
dimmingView.frame = containerView.bounds
containerView.addSubview(toVC.view)
toVC.view.frame = CGRect(x: -(finalWidth - toVC.view.bounds.width), y: 0, width: finalWidth, height: finalHeight)
}
let transform = {
self.dimmingView.alpha = 0.9
toVC.view.transform = CGAffineTransform(translationX: finalWidth - toVC.view.bounds.width, y: 0)
}
let identiy = {
self.dimmingView.alpha = 0.9
fromVC.view.transform = .identity
}
let duration = transitionDuration(using: transitionContext)
let isCancelled = transitionContext.transitionWasCancelled
UIView.animate(withDuration: duration, animations: {
self.isPresenting ? transform () : identiy()
}) { (_) in
transitionContext.completeTransition(!isCancelled)
}
}
}
ViewController类:
import UIKit
class ViewController: UIViewController {
let transition = SlideInMenu()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
@IBAction func tapBtnMenu(_ sender: Any) {
guard let menuVC = storyboard?.instantiateViewController(withIdentifier: "MenuViewController") else { return }
menuVC.modalPresentationStyle = .overCurrentContext
menuVC.transitioningDelegate = self
present(menuVC, animated: true)
}
}
extension ViewController: UIViewControllerTransitioningDelegate {
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
transition.isPresenting = true
return transition
}
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
transition.isPresenting = false
return transition
}
}
答案 0 :(得分:2)
输出:
您可以复制粘贴以下代码,以实时查看它。
说明:
ViewController:
侧边栏:
这完成了主要工作。
黑色透明视图为关闭按钮,另一部分为NavigationViewController
在show方法中,关闭按钮设置为60宽度,导航vc视图使用约束在其旁边对齐。请注意,导航vc的x位置设置为screenwidth的宽度。
借助于UIView.animate,X位置被设置为0,因此它从右向左动画。
,单击任何选项或单击导航vc外部,即关闭按钮,即会调用closeSidebar
方法。
closeSidebar再次具有UIViw.animate块,该块再次将X位置设置为屏幕宽度,从而从左到右进行动画处理。并在完成时将其从视图层次结构中删除。
ViewController在此委托人的SidebarDelegate
方法中确认sidebarDidClose
,您将了解到侧边栏已关闭,并且用户是否选择了任何选项。
ViewController:
import UIKit
class ViewController: UIViewController {
public let button: UIButton = {
let v = UIButton()
v.translatesAutoresizingMaskIntoConstraints = false
v.setTitle("Open Menu", for: .normal)
v.setTitleColor(.blue, for: .normal)
v.setTitleColor(UIColor.blue.withAlphaComponent(0.5), for: .highlighted)
return v
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(button)
let constrains = [
button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
button.centerYAnchor.constraint(equalTo: view.centerYAnchor)
]
NSLayoutConstraint.activate(constrains)
button.addTarget(self, action: #selector(didSelect(_:)), for: .touchUpInside)
}
@objc func didSelect(_ sender: UIButton){
SidebarLauncher.init(delegate: self).show()
}
}
extension ViewController: SidebarDelegate{
func sidbarDidOpen() {
}
func sidebarDidClose(with item: NavigationModel?) {
guard let item = item else {return}
switch item.type {
case .home:
print("called home")
case .star:
print("called star")
case .about:
print("called about")
case .facebook:
print("called facebook")
case .instagram:
print("instagram")
}
}
}
SideBar:
import UIKit
protocol SidebarDelegate {
func sidbarDidOpen()
func sidebarDidClose(with item: NavigationModel?)
}
class SidebarLauncher: NSObject{
var view: UIView?
var delegate: SidebarDelegate?
var vc: NavigationViewController?
init(delegate: SidebarDelegate) {
super.init()
self.delegate = delegate
}
public let closeButton: UIButton = {
let v = UIButton()
v.backgroundColor = UIColor.black.withAlphaComponent(0.5)
v.translatesAutoresizingMaskIntoConstraints = false
return v
}()
func show(){
let bounds = UIScreen.main.bounds
let v = UIView(frame: CGRect(x: bounds.width, y: 0, width: bounds.width, height: bounds.height))
v.backgroundColor = .clear
let vc = NavigationViewController()
vc.delegate = self
v.addSubview(vc.view)
v.addSubview(closeButton)
vc.view.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
closeButton.topAnchor.constraint(equalTo: v.topAnchor),
closeButton.leadingAnchor.constraint(equalTo: v.leadingAnchor),
closeButton.bottomAnchor.constraint(equalTo: v.bottomAnchor),
closeButton.widthAnchor.constraint(equalToConstant: 60),
vc.view.topAnchor.constraint(equalTo: v.topAnchor),
vc.view.leadingAnchor.constraint(equalTo: closeButton.trailingAnchor),
vc.view.bottomAnchor.constraint(equalTo: v.bottomAnchor),
vc.view.trailingAnchor.constraint(equalTo: v.trailingAnchor, constant: 0)
])
closeButton.addTarget(self, action: #selector(close(_:)), for: .touchUpInside)
self.view = v
self.vc = vc
UIApplication.shared.keyWindow?.addSubview(v)
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: [.curveEaseOut], animations: {
self.view?.frame = CGRect(x: 0, y: 0, width: self.view!.frame.width, height: self.view!.frame.height)
self.view?.backgroundColor = UIColor.black.withAlphaComponent(0.5)
}, completion: {completed in
self.delegate?.sidbarDidOpen()
})
}
@objc func close(_ sender: UIButton){
closeSidebar(option: nil)
}
func closeSidebar(option: NavigationModel?){
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: [.curveEaseOut], animations: {
if let view = self.view{
view.frame = CGRect(x: view.frame.width, y: 0, width: view.frame.width, height: view.frame.height)
self.view?.backgroundColor = .clear
}
}, completion: {completed in
self.view?.removeFromSuperview()
self.view = nil
self.vc = nil
self.delegate?.sidebarDidClose(with: option)
})
}
}
extension SidebarLauncher: NavigationDelegate{
func navigation(didSelect: NavigationModel?) {
closeSidebar(option: didSelect)
}
}
有关代码的完整性
NavigationView
import Foundation
import UIKit
class NavigationView: UIView{
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
func commonInit(){
addSubview(mainView)
mainView.addSubview(collectionView)
setConstraints()
}
func setConstraints() {
let constraints = [
mainView.topAnchor.constraint(equalTo: topAnchor),
mainView.leadingAnchor.constraint(equalTo: leadingAnchor),
mainView.bottomAnchor.constraint(equalTo: bottomAnchor),
mainView.trailingAnchor.constraint(equalTo: trailingAnchor),
collectionView.topAnchor.constraint(equalTo: mainView.topAnchor),
collectionView.leadingAnchor.constraint(equalTo: mainView.leadingAnchor),
collectionView.bottomAnchor.constraint(equalTo: mainView.bottomAnchor),
collectionView.trailingAnchor.constraint(equalTo: mainView.trailingAnchor)
]
NSLayoutConstraint.activate(constraints)
}
public let collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical
layout.minimumLineSpacing = 0
layout.minimumInteritemSpacing = 0
let v = UICollectionView(frame: .zero, collectionViewLayout: layout)
v.translatesAutoresizingMaskIntoConstraints = false
v.register(NavigationCell.self, forCellWithReuseIdentifier: "NavigationCell")
v.backgroundColor = .clear
return v
}()
public let mainView: UIView = {
let v = UIView()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = .blue
return v
}()
}
NavigationViewController加上导航模型
import Foundation
import UIKit
protocol NavigationDelegate{
func navigation(didSelect: NavigationModel?)
}
enum NavigationTypes{
case home,star,about,facebook,instagram
}
struct NavigationModel {
let name: String
let type: NavigationTypes
}
class NavigationViewController: UIViewController{
var myView: NavigationView {return view as! NavigationView}
unowned var collectionView: UICollectionView {return myView.collectionView}
var delegate: NavigationDelegate?
var list = [NavigationModel]()
override func loadView() {
view = NavigationView()
}
override func viewDidLoad() {
super.viewDidLoad()
setupList()
collectionView.delegate = self
collectionView.dataSource = self
}
func setupList(){
list.append(NavigationModel(name: "Home", type: .home))
list.append(NavigationModel(name: "Star", type: .star))
list.append(NavigationModel(name: "About", type: .about))
list.append(NavigationModel(name: "Facebook", type: .facebook))
list.append(NavigationModel(name: "Instagram", type: .instagram))
}
}
extension NavigationViewController: UICollectionViewDataSource{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return list.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "NavigationCell", for: indexPath) as! NavigationCell
let model = list[indexPath.item]
cell.label.text = model.name
return cell
}
}
extension NavigationViewController: UICollectionViewDelegate{
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
delegate?.navigation(didSelect: list[indexPath.item])
}
}
extension NavigationViewController: UICollectionViewDelegateFlowLayout{
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.frame.width, height: 45)
}
}
NavigationCell
import Foundation
import UIKit
class NavigationCell: UICollectionViewCell{
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
func commonInit(){
[label,divider].forEach{contentView.addSubview($0)}
setConstraints()
}
func setConstraints() {
let constraints = [
label.centerYAnchor.constraint(equalTo: centerYAnchor),
label.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16),
divider.leadingAnchor.constraint(equalTo: leadingAnchor),
divider.bottomAnchor.constraint(equalTo: bottomAnchor),
divider.trailingAnchor.constraint(equalTo: trailingAnchor),
divider.heightAnchor.constraint(equalToConstant: 1)
]
NSLayoutConstraint.activate(constraints)
}
public let label: UILabel = {
let v = UILabel()
v.text = "Label Text"
v.textColor = .white
v.translatesAutoresizingMaskIntoConstraints = false
return v
}()
public let divider: UIView = {
let v = UIView()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = .white
return v
}()
}