In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-20 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article mainly introduces how to use the Tab Bar icon, has a certain reference value, interested friends can refer to, I hope you can learn a lot after reading this article, the following let the editor take you to understand it.
Background
The Tab Bar that comes with the framework believes that everyone is already familiar with it. Generally, when you use it, you just set two icons to represent the selected and unselected states, and it is inevitable that there are some insipid ones. Later, many controls do some eye-catching animation when the label is selected, but I think most of them are animated for the sake of animation. It wasn't until I saw the animation of the Outlook client that I realized that it could still be combined with user interaction.
Figure 1 the label icon follows the gesture for different animations
Interesting, but this article is not intended to copy exactly the same, there will be a slight change:
Figure 2 the final result of this article
Implementation analysis
Before writing the code, let's discuss the implementation. I'm sure you've guessed that the icon on the tab is obviously not a picture, but a custom UIView. It is not difficult to mount a view to the location of the original icon, what is slightly more complicated is the realization of the digital wheel effect. Despite the fact that the numbers are constantly scrolling, take a closer look at the fact that at most 2 kinds of numbers are displayed, that is to say, only 2 Label is enough.
Based on the space, the article will not involve the clock effect on the right, please refer to the source code directly if you are interested.
Digital roller
Open the project TabBarInteraction and create a new file, WheelView.swift, which is a subclass of UIView. First, set up the initialization function:
Class WheelView: UIView {required init? (coder aDecoder: NSCoder) {super.init (coder: aDecoder) setupView ()} override init (frame: CGRect) {super.init (frame: frame) setupView ()}}
Then create two Label instances, representing the upper and lower Label in the wheel:
Private lazy var toplabel: UILabel = {return createDefaultLabel ()} () private lazy var bottomLabel: UILabel = {return createDefaultLabel ()} () private func createDefaultLabel ()-> UILabel {let label = UILabel () label.textAlignment = NSTextAlignment.center label.adjustsFontSizeToFitWidth = true label.translatesAutoresizingMaskIntoConstraints = false return label}
Now complete the setupView () method, where you add the above two Label to the view, and then set constraints to align their four sides with the layoutMarginsGuide.
Private func setupView () {translatesAutoresizingMaskIntoConstraints = false for label in [toplabel, bottomLabel] {addSubview (label) NSLayoutConstraint.activate ([label.topAnchor.constraint (equalTo: layoutMarginsGuide.topAnchor), label.bottomAnchor.constraint (equalTo: layoutMarginsGuide.bottomAnchor), label.leftAnchor.constraint (equalTo: layoutMarginsGuide.leftAnchor), label.rightAnchor.constraint (equalTo: layoutMarginsGuide.rightAnchor)])}}
One might ask, aren't the two Label overlapping states now? Don't worry, we will adjust their size and position dynamically according to the parameters.
Add two instance variables, progress and contents, to represent the overall progress of the scroll and the entire display, respectively.
Var progress: Float = 0.0var contents = [String] ()
The next step is to calculate what the current two Label displays and their zoom positions based on these two variables. These calculations are done in progress's didSet:
Var progress: Float = 0.0 {didSet {progress = min (max (progress, 1.0) guard contents.count > 0 else {return} / * * calculate the content displayed by the upper and lower label and the compression degree and location of label based on progress and contents * * Example: * progress = 0.4, contents = ["A", "B", "C" "D"] * * 1) calculate the content displayed by the two label * topIndex = 4 * 0.4 = 1.6, topLabel.text = contents [1] = "B" * bottomIndex = 1.6 + 1 = 2.6, bottomLabel.text = contents [2] = "C" * * 2) calculate how the two label are compressed and relocated This is the principle of realizing the roller effect * indexOffset = 1.6% 1 = 0.6 * halfHeight = bounds.height / 2 * ┌─┐ ┌─┐ * | ┌─┐ | scaleY | | * | | 1-0.6% 0.4 | | translationY * | | topLabel |-> | ┌─ topLabel ─┐ |-* | └─┘ |-halfHeight * 0.6 ⎞ ┌─┐ * | └─┘ | ⎥ | ┌─ toplabel ─┐ | * └── | ─┘ └─┘ ⎟ | └─┘ | * ❯ | ┌─┐ | * ┌─┐ ┌─┐ ⎟ | | bottomLabel | * | ┌─ ─┐ | scaleY | | ⎟ | └─┘ | * | 0.6 | ┌─┐ | translationY ⎠ └─┘ * | bottomLabel | |-> | bottomLabel | |-* | └── | ─┘ | halfHeight * 0.4 * | └─┘ | * └─┘ └─┘ * * you can imagine When indexOffset increases from 0.999 to 0, * topLabel shrinks from full view to 0, while bottomLabel becomes larger and larger to full view. That is, to form a complete scrolling * / let topIndex = min (max (0.0, Float (contents.count) * progress), Float (contents.count-1)) let bottomIndex = min (topIndex + 1, Float (contents.count-1)) let indexOffset = topIndex.truncatingRemainder (dividingBy: 1) toplabel.text = contents [topIndex)] toplabel.transform = CGAffineTransform (scaleX: 1.0,y: CGFloat (1-indexOffset)) .concatenating (CGAffineTransform (translationX: 0)) Y:-(toplabel.bounds.height / 2) * CGFloat (indexOffset)) bottomLabel.text = contents [Int (bottomIndex)] bottomLabel.transform = CGAffineTransform (scaleX: 1.0,y: CGFloat (indexOffset)) .concatenating (CGAffineTransform (translationX: 0, y: (bottomLabel.bounds.height / 2) * (1-CGFloat (indexOffset)}}
Finally, we need to expose some styles for customization:
Extension WheelView {/ foreground color change event override func tintColorDidChange () {[toplabel, bottomLabel]. ForEach {$0.textColor = tintColor} layer.borderColor = tintColor.cgColor} / / background color override var backgroundColor: UIColor? {get {return toplabel.backgroundColor} set {[toplabel, bottomLabel]. ForEach {$0.backgroundColor = newValue} / Border width var borderWidth: CGFloat {get {return layer.borderWidth} set {layoutMargins = UIEdgeInsets (top: newValue, left: newValue) Bottom: newValue, right: newValue) layer.borderWidth = newValue}} / font var font: UIFont {get {return toplabel.font} set {[toplabel, bottomLabel] .forEach {$0.font = newValue}}
At this point, the whole roller effect has been completed.
Mount View
Instantiate the view you just customized in FirstViewController, set the font, border, background color, Contents, etc., and don't forget that isUserInteractionEnabled is set to false, so that the original event response will not be affected.
Override func viewDidLoad () {super.viewDidLoad () / / Do any additional setup after loading the view. TableView.delegate = self tableView.dataSource = self tableView.register (UITableViewCell.self, forCellReuseIdentifier: "DefaultCell") tableView.rowHeight = 44 wheelView = WheelView (frame: CGRect.zero) wheelView.font = UIFont.systemFont (ofSize: 15, weight: .bold) wheelView.borderWidth = 1 wheelView.backgroundColor = UIColor.white wheelView.contents = data wheelView.isUserInteractionEnabled = false}
Then to mount the view to the previous icon, add code at the bottom of the viewDidLoad () method:
Override func viewDidLoad () {... Guard let parentController = self.parent as? UITabBarController else {return} let controllerIndex = parentController.children.firstIndex (of: self)! Var tabBarButtons = parentController.tabBar.subviews.filter ({type (of: $0). Description (). IsEqual ("UITabBarButton")}) guard! tabBarButtons.isEmpty else {return} let tabBarButton = tabBarButtons [controllerIndex] let swappableImageViews = tabBarButton.subviews.filter ({type (of: $0). Description (). IsEqual ("UITabBarSwappableImageView")} guard! swappableImageViews.isEmpty else {return} let swappableImageView = swappableImageViews.first! TabBarButton.addSubview (wheelView) swappableImageView.isHidden = true NSLayoutConstraint.activate ([wheelView.widthAnchor.constraint (equalToConstant: 25), wheelView.heightAnchor.constraint (equalToConstant: 25), wheelView.centerXAnchor.constraint (equalTo: swappableImageView.centerXAnchor), wheelView.centerYAnchor.constraint (equalTo: swappableImageView.centerYAnchor)])}
The purpose of the above code is to eventually find the view of type UITabBarSwappableImageView in the corresponding tag UITabBarButton and replace it. It looks quite complex, but it avoids unexpected conditions that lead to program exceptions as much as possible. As long as UIkit does not change the types UITabBarButton and UITabBarSwappableImageView and their inclusion relationship in the future, there will be no accidents in the program, which will at most cause custom views not to be mounted. Another benefit is that FirstViewController does not have to worry about how many tags it will be added to the TabBarController. On the whole, this method is not perfect, but there seems to be no better way at present.
You can actually strip out the above code and put it on the default implementation of protocol called TabbarInteractable. ViewController in need can simply declare compliance with the protocol and then call a method in the viewDidLoad method to implement the entire replacement process.
There is only one last step left, and we know that UITableView is a subclass of UIScrollView. As it scrolls, FirsViewController, as the delegate of UITableView, also receives a call to the scrollViewDidScroll method, so it is appropriate to update the progress of scrolling in this method:
/ / MARK: UITableViewDelegateextension FirstViewController: UITableViewDelegate {func scrollViewDidScroll (_ scrollView: UIScrollView) {/ / `rooms` depends on your requirements. The purpose here is to display the two numbers at the bottom of the visible region of `tableview`. Let progress = Float ((scrollView.contentOffset.y + tableView.bounds.height-tableView.rowHeight) / scrollView.contentSize.height) wheelView.progress = progress}}
Run up and have a look at the project, and you will get the effect at the beginning of the article.
Thank you for reading this article carefully. I hope the article "how to use the Tab Bar Icon" shared by the editor will be helpful to everyone. At the same time, I also hope that you will support us and pay attention to the industry information channel. More related knowledge is waiting for you to learn!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.