├── animation.gif
├── MyProject
├── Assets.xcassets
│ ├── Contents.json
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── AppDelegate.swift
├── Base.lproj
│ ├── Main.storyboard
│ └── LaunchScreen.storyboard
├── Info.plist
├── SceneDelegate.swift
├── ViewController.swift
└── WOPageControl.swift
├── MyProject.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ ├── xcuserdata
│ │ └── lwx.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
└── project.pbxproj
├── README.md
└── LICENSE
/animation.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wayone/WOPageControl-Swift/HEAD/animation.gif
--------------------------------------------------------------------------------
/MyProject/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/MyProject.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/MyProject.xcodeproj/project.xcworkspace/xcuserdata/lwx.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wayone/WOPageControl-Swift/HEAD/MyProject.xcodeproj/project.xcworkspace/xcuserdata/lwx.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/MyProject.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 小圆点 / PageControl - Swift 版
2 | [点这里 OC 版](https://github.com/wayone/WOPageControl-OC)
3 |
4 | ## ✨支持自定义
5 |
6 | - 形状:圆形、方形。
7 | - 大小。
8 | - 间距。
9 | - 颜色。
10 |
11 | ###### (如果下面的图挂了,请在梯子中添加域名 githubusercontent.com)
12 |
13 | 
14 |
15 | ## ✨示例代码
16 | ```swift
17 | // 添加控件
18 | let pageControl = WOPageControl(frame: CGRect(x:110, y:150, width: 200, height: 20))
19 | view.addSubview(pageControl)
20 |
21 | pageControl.cornerRadius = 5
22 | pageControl.dotHeight = 10
23 | pageControl.dotSpace = 24
24 | pageControl.currentDotWidth = 20
25 | pageControl.otherDotWidth = 10
26 | pageControl.otherDotColor = UIColor(red: 232/255.0, green: 234/255.0, blue: 236/255.0, alpha: 1)
27 | pageControl.currentDotColor = UIColor(red: 34/255.0, green: 34/255.0, blue: 34/255.0, alpha: 1)
28 | pageControl.numberOfPages = 5
29 |
30 | // 修改当前页
31 | pageControl.currentPage = 1
32 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 wayone
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/MyProject/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // MyProject
4 | //
5 | // Created by wayone on 2020/2/16.
6 | // Copyright © 2020 aaa. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 |
15 |
16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
17 | // Override point for customization after application launch.
18 | return true
19 | }
20 |
21 | // MARK: UISceneSession Lifecycle
22 |
23 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
24 | // Called when a new scene session is being created.
25 | // Use this method to select a configuration to create the new scene with.
26 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
27 | }
28 |
29 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) {
30 | // Called when the user discards a scene session.
31 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
32 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
33 | }
34 |
35 |
36 | }
37 |
38 |
--------------------------------------------------------------------------------
/MyProject/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/MyProject/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/MyProject/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "size" : "1024x1024",
91 | "scale" : "1x"
92 | }
93 | ],
94 | "info" : {
95 | "version" : 1,
96 | "author" : "xcode"
97 | }
98 | }
--------------------------------------------------------------------------------
/MyProject/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UIApplicationSceneManifest
24 |
25 | UIApplicationSupportsMultipleScenes
26 |
27 | UISceneConfigurations
28 |
29 | UIWindowSceneSessionRoleApplication
30 |
31 |
32 | UISceneConfigurationName
33 | Default Configuration
34 | UISceneDelegateClassName
35 | $(PRODUCT_MODULE_NAME).SceneDelegate
36 | UISceneStoryboardFile
37 | Main
38 |
39 |
40 |
41 |
42 | UILaunchStoryboardName
43 | LaunchScreen
44 | UIMainStoryboardFile
45 | Main
46 | UIRequiredDeviceCapabilities
47 |
48 | armv7
49 |
50 | UISupportedInterfaceOrientations
51 |
52 | UIInterfaceOrientationPortrait
53 | UIInterfaceOrientationLandscapeLeft
54 | UIInterfaceOrientationLandscapeRight
55 |
56 | UISupportedInterfaceOrientations~ipad
57 |
58 | UIInterfaceOrientationPortrait
59 | UIInterfaceOrientationPortraitUpsideDown
60 | UIInterfaceOrientationLandscapeLeft
61 | UIInterfaceOrientationLandscapeRight
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/MyProject/SceneDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SceneDelegate.swift
3 | // MyProject
4 | //
5 | // Created by wayone on 2020/2/16.
6 | // Copyright © 2020 aaa. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class SceneDelegate: UIResponder, UIWindowSceneDelegate {
12 |
13 | var window: UIWindow?
14 |
15 |
16 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
17 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
18 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
19 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
20 | guard let _ = (scene as? UIWindowScene) else { return }
21 | }
22 |
23 | func sceneDidDisconnect(_ scene: UIScene) {
24 | // Called as the scene is being released by the system.
25 | // This occurs shortly after the scene enters the background, or when its session is discarded.
26 | // Release any resources associated with this scene that can be re-created the next time the scene connects.
27 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
28 | }
29 |
30 | func sceneDidBecomeActive(_ scene: UIScene) {
31 | // Called when the scene has moved from an inactive state to an active state.
32 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
33 | }
34 |
35 | func sceneWillResignActive(_ scene: UIScene) {
36 | // Called when the scene will move from an active state to an inactive state.
37 | // This may occur due to temporary interruptions (ex. an incoming phone call).
38 | }
39 |
40 | func sceneWillEnterForeground(_ scene: UIScene) {
41 | // Called as the scene transitions from the background to the foreground.
42 | // Use this method to undo the changes made on entering the background.
43 | }
44 |
45 | func sceneDidEnterBackground(_ scene: UIScene) {
46 | // Called as the scene transitions from the foreground to the background.
47 | // Use this method to save data, release shared resources, and store enough scene-specific state information
48 | // to restore the scene back to its current state.
49 | }
50 |
51 |
52 | }
53 |
54 |
--------------------------------------------------------------------------------
/MyProject/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // MyProject
4 | //
5 | // Created by wayone on 2020/2/16.
6 | // Copyright © 2020 aaa. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class ViewController: UIViewController {
12 |
13 | var views: [WOPageControl] = [WOPageControl]()
14 |
15 | override func viewDidLoad() {
16 | super.viewDidLoad()
17 | setupUI_1()
18 | setupUI_2()
19 | setupUI_3()
20 | setupUI_4()
21 |
22 | addButton()
23 | }
24 |
25 | func setupUI_1() {
26 | let label = UILabel(frame: CGRect(x:30, y:150, width: 50, height: 20))
27 | self.view.addSubview(label)
28 | label.text = "圆形"
29 |
30 | let pageControl = WOPageControl(frame: CGRect(x:110, y:150, width: 200, height: 20))
31 | view.addSubview(pageControl)
32 | pageControl.center = CGPoint(x: pageControl.superview!.center.x, y: pageControl.center.y)
33 |
34 | pageControl.cornerRadius = 5;
35 | pageControl.dotHeight = 10;
36 | pageControl.dotSpace = 24;
37 | pageControl.currentDotWidth = 20;
38 | pageControl.otherDotWidth = 10;
39 | pageControl.otherDotColor = UIColor(red: 232/255.0, green: 234/255.0, blue: 236/255.0, alpha: 1)
40 | pageControl.currentDotColor = UIColor(red: 34/255.0, green: 34/255.0, blue: 34/255.0, alpha: 1)
41 | pageControl.numberOfPages = 5;
42 |
43 | views.append(pageControl)
44 | }
45 |
46 | func setupUI_2() {
47 | let pageControl = WOPageControl(frame: CGRect(x:110, y:200, width: 200, height: 20))
48 | view.addSubview(pageControl)
49 | pageControl.center = CGPoint(x: pageControl.superview!.center.x, y: pageControl.center.y)
50 |
51 | pageControl.cornerRadius = 5;
52 | pageControl.dotHeight = 10;
53 | pageControl.dotSpace = 10;
54 | pageControl.currentDotWidth = 20;
55 | pageControl.otherDotWidth = 10;
56 | pageControl.otherDotColor = .blue
57 | pageControl.currentDotColor = .red
58 | pageControl.numberOfPages = 5;
59 |
60 | views.append(pageControl)
61 | }
62 |
63 | func setupUI_3() {
64 | let label = UILabel(frame: CGRect(x:30, y:250, width: 50, height: 20))
65 | self.view.addSubview(label)
66 | label.text = "方形"
67 |
68 | let pageControl = WOPageControl(frame: CGRect(x:110, y:250, width: 200, height: 20))
69 | view.addSubview(pageControl)
70 | pageControl.center = CGPoint(x: pageControl.superview!.center.x, y: pageControl.center.y)
71 |
72 | pageControl.cornerRadius = 0;
73 | pageControl.dotHeight = 10;
74 | pageControl.dotSpace = 24;
75 | pageControl.currentDotWidth = 20;
76 | pageControl.otherDotWidth = 10;
77 | pageControl.otherDotColor = .orange
78 | pageControl.currentDotColor = .cyan
79 | pageControl.numberOfPages = 5;
80 |
81 | views.append(pageControl)
82 | }
83 |
84 | func setupUI_4() {
85 | let pageControl = WOPageControl(frame: CGRect(x:110, y:300, width: 200, height: 20))
86 | view.addSubview(pageControl)
87 | pageControl.center = CGPoint(x: pageControl.superview!.center.x, y: pageControl.center.y)
88 |
89 | pageControl.cornerRadius = 0;
90 | pageControl.dotHeight = 10;
91 | pageControl.dotSpace = 10;
92 | pageControl.currentDotWidth = 20;
93 | pageControl.otherDotWidth = 10;
94 | pageControl.otherDotColor = .green
95 | pageControl.currentDotColor = .yellow
96 | pageControl.numberOfPages = 5;
97 |
98 | views.append(pageControl)
99 | }
100 |
101 | func addButton() {
102 | let button1 = UIButton()
103 | self.view.addSubview(button1)
104 | button1.frame = CGRect(x:50, y:380, width: 100, height: 40)
105 | button1.setTitle("前一个", for: .normal)
106 | button1.setTitleColor(.white, for: .normal)
107 | button1.backgroundColor = .gray
108 | button1.addTarget(self, action: #selector(previousOne), for: .touchUpInside)
109 |
110 | let button2 = UIButton()
111 | self.view.addSubview(button2)
112 | button2.frame = CGRect(x:230, y:380, width: 100, height: 40)
113 | button2.setTitle("后一个", for: .normal)
114 | button2.setTitleColor(.white, for: .normal)
115 | button2.backgroundColor = .gray
116 | button2.addTarget(self, action: #selector(nextOne), for: .touchUpInside)
117 | }
118 |
119 | @objc
120 | func previousOne() {
121 | views.forEach {
122 | $0.currentPage = ($0.currentPage - 1 + $0.numberOfPages) % $0.numberOfPages
123 | }
124 | }
125 |
126 | @objc
127 | func nextOne() {
128 | views.forEach {
129 | $0.currentPage = ($0.currentPage + 1 + $0.numberOfPages) % $0.numberOfPages
130 | }
131 | }
132 | }
133 |
134 |
--------------------------------------------------------------------------------
/MyProject/WOPageControl.swift:
--------------------------------------------------------------------------------
1 | //
2 | // WOPageControl.swift
3 | // xx
4 | //
5 | // Created by wayone on 2020/2/16.
6 | //
7 |
8 | import UIKit
9 |
10 | class WOPageControl: UIView {
11 | public var numberOfPages: Int = 0 {
12 | didSet {
13 |
14 | dotViewArrayM.forEach { $0.removeFromSuperview() }
15 | dotViewArrayM.removeAll()
16 |
17 | for _ in 0..= dotViewArrayM.count ||
32 | dotViewArrayM.count == 0 ||
33 | newValue == currentPage ||
34 | inAnimating)
35 | {
36 | return;
37 | }
38 | // 向右
39 | if (newValue > currentPage) {
40 | let currentView = dotViewArrayM[currentPage];
41 | bringSubviewToFront(currentView)
42 | inAnimating = true;
43 | UIView.animate(withDuration: 0.3, animations: {
44 | // 当前选中的圆点,x 不变,宽度增加,增加几个圆点和间隙距离
45 | let x = currentView.frame.origin.x
46 | let y = currentView.frame.origin.y
47 | let w = self.currentDotWidth + (self.dotSpace + self.otherDotWidth) * CGFloat(newValue - self.currentPage)
48 | let h = currentView.frame.size.height
49 | currentView.frame = CGRect(x: x, y: y, width: w, height: h)
50 | }) { (finished) in
51 | let endView = self.dotViewArrayM[newValue]
52 | endView.backgroundColor = currentView.backgroundColor
53 | endView.frame = currentView.frame
54 | self.bringSubviewToFront(endView)
55 |
56 | currentView.backgroundColor = self.otherDotColor
57 |
58 | // 逐个左移 view
59 | let start_X = currentView.frame.origin.x;
60 | for i in 0..<(newValue - self.currentPage) {
61 |
62 | let dotView = self.dotViewArrayM[self.currentPage + i];
63 | // 左移
64 | let x = start_X + (self.otherDotWidth + self.dotSpace) * CGFloat(i)
65 | let y = dotView.frame.origin.y
66 | let w = self.otherDotWidth
67 | let h = self.dotHeight
68 | dotView.frame = CGRect(x: x, y: y, width: w, height: h)
69 | }
70 | UIView.animate(withDuration: 0.3, animations: {
71 | let w = self.currentDotWidth;
72 | let x = endView.frame.maxX - self.currentDotWidth;
73 | let y = endView.frame.origin.y;
74 | let h = endView.frame.size.height;
75 | endView.frame = CGRect(x: x, y: y, width: w, height: h)
76 | }) { (finished) in
77 | self.currentPageInner = newValue;
78 | self.inAnimating = false;
79 | }
80 | }
81 | }
82 | // 向左
83 | else
84 | {
85 | let currentView = self.dotViewArrayM[self.currentPage];
86 | bringSubviewToFront(currentView)
87 | inAnimating = true;
88 |
89 | UIView.animate(withDuration: 0.3, animations: {
90 | // 当前选中的圆点,x 左移,宽度增加,增加几个圆点和间隙距离
91 | let x = currentView.frame.origin.x - (self.dotSpace + self.otherDotWidth) * CGFloat(self.currentPage - newValue);
92 | let y = currentView.frame.origin.y;
93 | let w = self.currentDotWidth + (self.dotSpace + self.otherDotWidth) * CGFloat(self.currentPage - newValue);
94 | let h = currentView.frame.size.height;
95 | currentView.frame = CGRect(x: x, y: y, width: w, height: h)
96 | }) { (_) in
97 | let endView = self.dotViewArrayM[newValue]
98 | endView.backgroundColor = currentView.backgroundColor
99 | endView.frame = currentView.frame
100 | self.bringSubviewToFront(endView)
101 |
102 | currentView.backgroundColor = self.otherDotColor
103 |
104 | // 逐个右移 view
105 | let start_X = currentView.frame.maxX
106 | for i in 0..<(self.currentPage - newValue) {
107 | let dotView = self.dotViewArrayM[self.currentPage - i]
108 | let tempFrame = dotView.frame
109 | // 右移
110 | let x = start_X - self.otherDotWidth - (self.otherDotWidth + self.dotSpace) * CGFloat(i);
111 | let y = tempFrame.origin.y
112 | let w = self.otherDotWidth
113 | let h = tempFrame.size.height
114 | dotView.frame = CGRect(x: x, y: y, width: w, height: h)
115 | }
116 |
117 | UIView.animate(withDuration: 0.3, animations: {
118 | let x = endView.frame.origin.x
119 | let y = endView.frame.origin.y
120 | let w = self.currentDotWidth
121 | let h = endView.frame.size.height
122 | endView.frame = CGRect(x: x, y: y, width: w, height: h)
123 | }) { (_) in
124 | self.currentPageInner = newValue
125 | self.inAnimating = false
126 | }
127 | }
128 | }
129 | }
130 | get{
131 | currentPageInner
132 | }
133 | }
134 | public var currentDotWidth: CGFloat = 0
135 | public var otherDotWidth: CGFloat = 0
136 | public var dotHeight: CGFloat = 0
137 | public var dotSpace: CGFloat = 0
138 | public var cornerRadius: CGFloat = 0
139 | public var currentDotColor: UIColor = .red
140 | public var otherDotColor: UIColor = .lightGray
141 |
142 | private var currentPageInner: Int = 0
143 | private var dotViewArrayM = [UIView]()
144 | private var isInitialize: Bool = false
145 | private var inAnimating: Bool = false
146 |
147 | override init(frame: CGRect) {
148 | super.init(frame: frame)
149 | }
150 |
151 | required init?(coder: NSCoder) {
152 | fatalError("init(coder:) has not been implemented")
153 | }
154 |
155 | override func layoutSubviews() {
156 | super.layoutSubviews()
157 | setupUI()
158 | }
159 |
160 | private func setupUI() {
161 | if dotViewArrayM.count == 0 || isInitialize == false {
162 | return
163 | }
164 | self.isInitialize = false
165 |
166 | let totalWidth = currentDotWidth + (CGFloat)(numberOfPages - 1) * (dotSpace + otherDotWidth)
167 | var currentX = (frame.size.width - totalWidth) / 2
168 |
169 | for i in 0..