├── .gitignore
├── .travis.yml
├── Example
├── Petral.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ ├── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ │ └── xcuserdata
│ │ │ └── huangzhibin327.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ ├── xcshareddata
│ │ └── xcschemes
│ │ │ └── Petral-Example.xcscheme
│ └── xcuserdata
│ │ └── huangzhibin327.xcuserdatad
│ │ └── xcschemes
│ │ └── xcschememanagement.plist
├── Petral.xcworkspace
│ ├── contents.xcworkspacedata
│ ├── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
│ └── xcuserdata
│ │ └── huangzhibin327.xcuserdatad
│ │ ├── UserInterfaceState.xcuserstate
│ │ └── xcdebugger
│ │ └── Breakpoints_v2.xcbkptlist
├── Petral
│ ├── AppDelegate.swift
│ ├── Base.lproj
│ │ ├── LaunchScreen.xib
│ │ └── Main.storyboard
│ ├── ColumnFlexViewController.swift
│ ├── ColumnFlexViewController.xml
│ ├── DataFlexViewController.swift
│ ├── DataFlexViewController.xml
│ ├── DataListViewController.swift
│ ├── DataListViewController.xml
│ ├── EmbedFlexViewController.swift
│ ├── EmbedFlexViewController.xml
│ ├── Images.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ └── Contents.json
│ │ ├── Contents.json
│ │ ├── head0.imageset
│ │ │ ├── Contents.json
│ │ │ └── head0.png
│ │ ├── head1.imageset
│ │ │ ├── Contents.json
│ │ │ └── head1.png
│ │ ├── head2.imageset
│ │ │ ├── Contents.json
│ │ │ └── head2.png
│ │ ├── setting.imageset
│ │ │ ├── Contents.json
│ │ │ └── setting.png
│ │ └── setting2.imageset
│ │ │ ├── Contents.json
│ │ │ └── setting2.png
│ ├── Info.plist
│ ├── InjectXmlLayoutViewController.swift
│ ├── InjectXmlLayoutViewController.xml
│ ├── LayoutViewController.swift
│ ├── ListViewController.swift
│ ├── ListViewController.xml
│ ├── MyTableView.swift
│ ├── MyTableViewCell.xml
│ ├── MyTableViewController.swift
│ ├── MyTableViewController.xml
│ ├── Petral-Bridging-Header.h
│ ├── RedImageView.swift
│ ├── RowFlexViewController.swift
│ ├── RowFlexViewController.xml
│ ├── SectionListViewController.swift
│ ├── SectionListViewController.xml
│ ├── SimpleListViewController.swift
│ ├── SimpleListViewController.xml
│ ├── UserInfoView.swift
│ ├── UserInfoView.xml
│ ├── UserProfileView.swift
│ ├── UserProfileView.xml
│ ├── ViewController.swift
│ ├── ViewController.xml
│ ├── WrapFlexViewController.swift
│ ├── WrapFlexViewController.xml
│ ├── XmlLayoutViewController.swift
│ ├── XmlLayoutViewController.xml
│ ├── XmlViewController.swift
│ ├── XmlViewController.xml
│ ├── petral-ui.xsd
│ └── test.xml
├── Podfile
├── Podfile.lock
├── Pods
│ ├── Local Podspecs
│ │ └── Petral.podspec.json
│ ├── Manifest.lock
│ ├── Pods.xcodeproj
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ ├── xcshareddata
│ │ │ │ └── IDEWorkspaceChecks.plist
│ │ │ └── xcuserdata
│ │ │ │ └── huangzhibin327.xcuserdatad
│ │ │ │ ├── UserInterfaceState.xcuserstate
│ │ │ │ └── WorkspaceSettings.xcsettings
│ │ └── xcuserdata
│ │ │ └── huangzhibin327.xcuserdatad
│ │ │ └── xcschemes
│ │ │ ├── Petral.xcscheme
│ │ │ ├── Pods-Petral_Example.xcscheme
│ │ │ ├── Pods-Petral_Tests.xcscheme
│ │ │ └── xcschememanagement.plist
│ └── Target Support Files
│ │ ├── Petral
│ │ ├── Petral-Info.plist
│ │ ├── Petral-dummy.m
│ │ ├── Petral-prefix.pch
│ │ ├── Petral-umbrella.h
│ │ ├── Petral.modulemap
│ │ └── Petral.xcconfig
│ │ ├── Pods-Petral_Example
│ │ ├── Pods-Petral_Example-Info.plist
│ │ ├── Pods-Petral_Example-acknowledgements.markdown
│ │ ├── Pods-Petral_Example-acknowledgements.plist
│ │ ├── Pods-Petral_Example-dummy.m
│ │ ├── Pods-Petral_Example-frameworks.sh
│ │ ├── Pods-Petral_Example-umbrella.h
│ │ ├── Pods-Petral_Example.debug.xcconfig
│ │ ├── Pods-Petral_Example.modulemap
│ │ └── Pods-Petral_Example.release.xcconfig
│ │ └── Pods-Petral_Tests
│ │ ├── Pods-Petral_Tests-Info.plist
│ │ ├── Pods-Petral_Tests-acknowledgements.markdown
│ │ ├── Pods-Petral_Tests-acknowledgements.plist
│ │ ├── Pods-Petral_Tests-dummy.m
│ │ ├── Pods-Petral_Tests-umbrella.h
│ │ ├── Pods-Petral_Tests.debug.xcconfig
│ │ ├── Pods-Petral_Tests.modulemap
│ │ └── Pods-Petral_Tests.release.xcconfig
├── Tests
│ ├── Info.plist
│ └── Tests.swift
└── build
│ └── XCBuildData
│ ├── BuildDescriptionCacheIndex-3b2af7ba66cb1d16b8c8cc1f9f59b4e4
│ ├── f57f7d0483b85d8aaca50d9f5640f017-desc.xcbuild
│ └── f57f7d0483b85d8aaca50d9f5640f017-manifest.xcbuild
├── LICENSE
├── Petral-UI.podspec
├── Petral
├── Assets
│ └── .gitkeep
└── Classes
│ ├── .gitkeep
│ ├── PetralAttribute.swift
│ ├── PetralConfig.swift
│ ├── PetralFlexView.swift
│ ├── PetralLoader.swift
│ ├── PetralParser.swift
│ ├── PetralRestraint.swift
│ ├── PetralTableView.swift
│ ├── PetralUtil.swift
│ └── UIView+Petral.swift
├── README.md
├── RestraintAPI.md
└── _Pods.xcodeproj
/.gitignore:
--------------------------------------------------------------------------------
1 | # OS X
2 | .DS_Store
3 |
4 | # Xcode
5 | build/
6 | *.pbxuser
7 | !default.pbxuser
8 | *.mode1v3
9 | !default.mode1v3
10 | *.mode2v3
11 | !default.mode2v3
12 | *.perspectivev3
13 | !default.perspectivev3
14 | xcuserdata/
15 | *.xccheckout
16 | profile
17 | *.moved-aside
18 | DerivedData
19 | *.hmap
20 | *.ipa
21 |
22 | # Bundler
23 | .bundle
24 |
25 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
26 | # Carthage/Checkouts
27 |
28 | Carthage/Build
29 |
30 | # We recommend against adding the Pods directory to your .gitignore. However
31 | # you should judge for yourself, the pros and cons are mentioned at:
32 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
33 | #
34 | # Note: if you ignore the Pods directory, make sure to uncomment
35 | # `pod install` in .travis.yml
36 | #
37 | # Pods/
38 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | # references:
2 | # * https://www.objc.io/issues/6-build-tools/travis-ci/
3 | # * https://github.com/supermarin/xcpretty#usage
4 |
5 | osx_image: xcode7.3
6 | language: objective-c
7 | # cache: cocoapods
8 | # podfile: Example/Podfile
9 | # before_install:
10 | # - gem install cocoapods # Since Travis is not always on latest version
11 | # - pod install --project-directory=Example
12 | script:
13 | - set -o pipefail && xcodebuild test -enableCodeCoverage YES -workspace Example/Petral.xcworkspace -scheme Petral-Example -sdk iphonesimulator9.3 ONLY_ACTIVE_ARCH=NO | xcpretty
14 | - pod lib lint
15 |
--------------------------------------------------------------------------------
/Example/Petral.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Example/Petral.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Example/Petral.xcodeproj/project.xcworkspace/xcuserdata/huangzhibin327.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HuangZhiBin/Petral-UI/6518901c1dcc6968efd5fc78a43fe8fd6a9b4935/Example/Petral.xcodeproj/project.xcworkspace/xcuserdata/huangzhibin327.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Example/Petral.xcodeproj/xcshareddata/xcschemes/Petral-Example.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
38 |
39 |
45 |
46 |
48 |
54 |
55 |
56 |
57 |
58 |
64 |
65 |
66 |
67 |
68 |
69 |
80 |
82 |
88 |
89 |
90 |
91 |
95 |
96 |
97 |
98 |
99 |
100 |
106 |
108 |
114 |
115 |
116 |
117 |
119 |
120 |
123 |
124 |
125 |
--------------------------------------------------------------------------------
/Example/Petral.xcodeproj/xcuserdata/huangzhibin327.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | Petral-Example.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/Example/Petral.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Example/Petral.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Example/Petral.xcworkspace/xcuserdata/huangzhibin327.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HuangZhiBin/Petral-UI/6518901c1dcc6968efd5fc78a43fe8fd6a9b4935/Example/Petral.xcworkspace/xcuserdata/huangzhibin327.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Example/Petral.xcworkspace/xcuserdata/huangzhibin327.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
8 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/Example/Petral/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // Petral
4 | //
5 | // Created by ikrboy@163.com on 06/13/2019.
6 | // Copyright (c) 2019 ikrboy@163.com. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Petral
11 |
12 | @UIApplicationMain
13 | class AppDelegate: UIResponder, UIApplicationDelegate {
14 |
15 | var window: UIWindow?
16 |
17 |
18 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
19 | // Override point for customization after application launch.
20 | let vc = ViewController();
21 | let navigationVC = UINavigationController.init(rootViewController: vc);
22 | self.window?.rootViewController = navigationVC;
23 | self.window?.makeKeyAndVisible();
24 |
25 | // PetralHttpManager.sharedInstance().startServer("/Users/huang/Petral-UI/Example/");
26 | // PetralConfig.shared.reloadUrl = PetralHttpManager.sharedInstance().url;
27 |
28 | return true
29 | }
30 |
31 | func applicationWillResignActive(_ application: UIApplication) {
32 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
33 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
34 | }
35 |
36 | func applicationDidEnterBackground(_ application: UIApplication) {
37 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
38 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
39 | }
40 |
41 | func applicationWillEnterForeground(_ application: UIApplication) {
42 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
43 | }
44 |
45 | func applicationDidBecomeActive(_ application: UIApplication) {
46 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
47 | }
48 |
49 | func applicationWillTerminate(_ application: UIApplication) {
50 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
51 | }
52 |
53 |
54 | }
55 |
56 |
--------------------------------------------------------------------------------
/Example/Petral/Base.lproj/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
24 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/Example/Petral/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 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/Example/Petral/ColumnFlexViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ColumnFlexViewController.swift
3 | // Petral_Example
4 | //
5 | // Created by huangzhibin on 2019/7/29.
6 | // Copyright © 2019 CocoaPods. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Petral
11 |
12 | class ColumnFlexViewController: UIViewController {
13 |
14 | override func viewDidLoad() {
15 | super.viewDidLoad();
16 |
17 | let loader = self.view.petralLoadXmlViews(xmlPath: "ColumnFlexViewController");
18 | let flexview = loader.petralViewById(id: "flexview") as! PetralFlexView;
19 | let scrollview = loader.petralViewById(id: "scrollview") as! UIScrollView;
20 | flexview.itemDisplayAction = {(templateView: PetralFlexTemplateView, index : Int) in
21 | print(index);
22 | let cellImage : UIImageView = loader.petralViewById(id: "cellImage", inView: templateView) as! UIImageView;
23 | cellImage.image = UIImage.init(named: "head" + String(index % 3));
24 |
25 | let cellLabel : UILabel = loader.petralViewById(id: "cellLabel", inView: templateView) as! UILabel;
26 | cellLabel.text = "User " + String(index + 1);
27 | };
28 | flexview.itemClickAction = { (template: PetralFlexTemplateView, index : Int) in
29 | print(index);
30 | }
31 | scrollview.contentSize = flexview.resize();
32 | // Do any additional setup after loading the view.
33 | }
34 |
35 | deinit {
36 | print("deinit");
37 | }
38 |
39 |
40 | /*
41 | // MARK: - Navigation
42 |
43 | // In a storyboard-based application, you will often want to do a little preparation before navigation
44 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
45 | // Get the new view controller using segue.destination.
46 | // Pass the selected object to the new view controller.
47 | }
48 | */
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/Example/Petral/ColumnFlexViewController.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Example/Petral/DataFlexViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DataFlexViewController.swift
3 | // Petral_Example
4 | //
5 | // Created by huangzhibin on 2019/7/29.
6 | // Copyright © 2019 CocoaPods. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Petral
11 |
12 | class DataFlexViewController: UIViewController {
13 |
14 | lazy var users: [UserModel]! = {
15 | return [
16 | UserModel.init(image: "head0", name: "熊熊"),
17 | UserModel.init(image: "head1", name: "天线德德B"),
18 | UserModel.init(image: "head2", name: "小红帽")
19 | ];
20 | }();
21 |
22 | var loader: PetralViewLoader!;
23 |
24 | override func viewDidLoad() {
25 | super.viewDidLoad();
26 |
27 | self.loader = self.view.petralLoadXmlViews(xmlPath: "DataFlexViewController");
28 | let flexview = loader.petralViewById(id: "flexview") as! PetralFlexView;
29 | let scrollview = loader.petralViewById(id: "scrollview") as! UIScrollView;
30 |
31 | flexview.itemWidthAction = { (index: Int) in
32 | return ((CGFloat(index) * 0.1) + 1) * 200;
33 | };
34 | flexview.itemHeightAction = { (index: Int) in
35 | return ((CGFloat(index) * 0.05) + 1) * 80;
36 | };
37 | flexview.itemDisplayAction = {[weak self] (templateView: PetralFlexTemplateView, index : Int) in
38 | print(index);
39 | let cellImage : UIImageView = self?.loader.petralViewById(id: "cellImage", inView: templateView) as! UIImageView;
40 | cellImage.image = UIImage.init(named: (self?.users[index].image)!);
41 |
42 | let cellLabel : UILabel = self?.loader.petralViewById(id: "cellLabel", inView: templateView) as! UILabel;
43 | cellLabel.text = self?.users[index].name;
44 | };
45 | flexview.itemClickAction = { (template: PetralFlexTemplateView, index : Int) in
46 | print(index);
47 | }
48 | flexview.itemCountAction = { [weak self] in
49 | return (self?.users.count)!;
50 | }
51 | scrollview.contentSize = flexview.resize();
52 | // Do any additional setup after loading the view.
53 |
54 | let changeBtn : UIButton = self.loader.petralViewById(id: "changeBtn") as! UIButton;
55 | changeBtn.addTarget(self, action: #selector(self.changeData), for: .touchUpInside);
56 | }
57 |
58 | @objc func changeData() {
59 | self.users = [
60 | UserModel.init(image: "head0", name: "熊熊"),
61 | UserModel.init(image: "head1", name: "天线德德B"),
62 | UserModel.init(image: "head2", name: "小红帽"),
63 | UserModel.init(image: "head0", name: "熊熊2"),
64 | UserModel.init(image: "head1", name: "天线德德B2"),
65 | UserModel.init(image: "head2", name: "小红帽2"),
66 | UserModel.init(image: "head0", name: "熊熊3"),
67 | UserModel.init(image: "head1", name: "天线德德B3"),
68 | UserModel.init(image: "head2", name: "小红帽3")
69 | ];
70 | let flexview = self.loader.petralViewById(id: "flexview") as! PetralFlexView;
71 | let scrollview = loader.petralViewById(id: "scrollview") as! UIScrollView;
72 | flexview.reloadData();
73 | scrollview.contentSize = flexview.resize();
74 | }
75 |
76 | deinit {
77 | print("deinit");
78 | }
79 |
80 |
81 | /*
82 | // MARK: - Navigation
83 |
84 | // In a storyboard-based application, you will often want to do a little preparation before navigation
85 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
86 | // Get the new view controller using segue.destination.
87 | // Pass the selected object to the new view controller.
88 | }
89 | */
90 |
91 | }
92 |
--------------------------------------------------------------------------------
/Example/Petral/DataFlexViewController.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/Example/Petral/DataListViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DataListViewController.swift
3 | // Petral_Example
4 | //
5 | // Created by huangzhibin on 2019/7/22.
6 | // Copyright © 2019 CocoaPods. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Petral
11 |
12 | class DataListViewController: UIViewController {
13 |
14 | lazy var groups: [GroupModel]! = {
15 | return [
16 | GroupModel.init(groupName: "可爱的", users:
17 | [
18 | UserModel.init(image: "head0", name: "熊熊"),
19 | UserModel.init(image: "head1", name: "天线德德B")
20 | ]
21 | ),
22 | GroupModel.init(groupName: "很美的", users:
23 | [
24 | UserModel.init(image: "head2", name: "小红帽")
25 | ]
26 | )
27 | ];
28 | }();
29 |
30 | var loader: PetralViewLoader!;
31 |
32 | override func viewDidLoad() {
33 | super.viewDidLoad();
34 |
35 | self.loader = self.view.petralLoadXmlViews(xmlPath: "DataListViewController");
36 |
37 | let tableView : PetralTableView = self.loader.petralViewById(id: "tableview1") as! PetralTableView;
38 | tableView.tableSectionCountAction = { [weak self] in
39 | return self!.groups.count;
40 | };
41 | tableView.tableCellRowCountAction = { [weak self] (section: Int) in
42 | return (self?.groups[section].users.count)!;
43 | };
44 | tableView.tableCellDisplayAction = { [weak self] (cell: UITableViewCell, indexPath: IndexPath) in
45 | let cellImage : UIImageView = self?.loader.petralViewById(id: "cellImage", inView: cell) as! UIImageView;
46 | cellImage.image = UIImage.init(named: (self?.groups[indexPath.section].users[indexPath.row].image)!);
47 |
48 | let cellLabel : UILabel = self?.loader.petralViewById(id: "cellLabel", inView: cell) as! UILabel;
49 | cellLabel.text = self?.groups[indexPath.section].users[indexPath.row].name;
50 |
51 | cell.selectedBackgroundView = UIView.init(frame: cell.frame);
52 | cell.selectedBackgroundView?.backgroundColor = UIColor.init(red: 250/255.0, green: 250/255.0, blue: 250/255.0, alpha: 1);
53 | };
54 | tableView.tableSectionHeaderDisplayAction = { [weak self] (headerView: UIView, section: Int) in
55 | let sectionHeaderLabel : UILabel = self?.loader.petralViewById(id: "sectionHeaderLabel", inView: headerView) as! UILabel;
56 | sectionHeaderLabel.text = self?.groups[section].groupName;
57 | };
58 | tableView.tableCellClickAction = { (indexPath: IndexPath) in
59 | print(indexPath.row);
60 | };
61 |
62 | let changeBtn : UIButton = loader.petralViewById(id: "changeBtn") as! UIButton;
63 | changeBtn.addTarget(self, action: #selector(self.changeData), for: .touchUpInside);
64 | }
65 |
66 | @objc func changeData() {
67 | self.groups = [
68 | GroupModel.init(groupName: "很酷的", users:
69 | [
70 | UserModel.init(image: "head0", name: "熊熊"),
71 | ]
72 | ),
73 | GroupModel.init(groupName: "可爱的", users:
74 | [
75 | UserModel.init(image: "head1", name: "天线德德B"),
76 | UserModel.init(image: "head2", name: "小红帽")
77 | ]
78 | ),
79 | GroupModel.init(groupName: "很美的", users:
80 | [
81 | UserModel.init(image: "head0", name: "熊熊"),
82 | UserModel.init(image: "head1", name: "天线德德B"),
83 | UserModel.init(image: "head2", name: "小红帽")
84 | ]
85 | )
86 | ];
87 | let tableView : PetralTableView = self.loader.petralViewById(id: "tableview1") as! PetralTableView;
88 | tableView.reloadData();
89 | }
90 |
91 | deinit {
92 | print("deinit");
93 | }
94 |
95 |
96 | /*
97 | // MARK: - Navigation
98 |
99 | // In a storyboard-based application, you will often want to do a little preparation before navigation
100 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
101 | // Get the new view controller using segue.destination.
102 | // Pass the selected object to the new view controller.
103 | }
104 | */
105 |
106 | }
107 |
108 | class GroupModel: NSObject{
109 | var groupName : String!;
110 | var users : [UserModel] = [];
111 |
112 | init(groupName : String, users : [UserModel]) {
113 | self.groupName = groupName;
114 | self.users = users;
115 | }
116 | }
117 |
118 | class UserModel: NSObject{
119 | var image : String!;
120 | var name : String!;
121 |
122 | init(image : String, name : String) {
123 | self.image = image;
124 | self.name = name;
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/Example/Petral/DataListViewController.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/Example/Petral/EmbedFlexViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RowFlexViewController.swift
3 | // Petral_Example
4 | //
5 | // Created by huangzhibin on 2019/7/29.
6 | // Copyright © 2019 CocoaPods. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Petral
11 |
12 | class EmbedFlexViewController: UIViewController {
13 |
14 | override func viewDidLoad() {
15 | super.viewDidLoad();
16 |
17 | let loader = self.view.petralLoadXmlViews(xmlPath: "EmbedFlexViewController");
18 | let flexview = loader.petralViewById(id: "flexview") as! PetralFlexView;
19 | let scrollview = loader.petralViewById(id: "scrollview") as! UIScrollView;
20 | flexview.itemDisplayAction = {(templateView: PetralFlexTemplateView, index : Int) in
21 | print(index);
22 |
23 | let rowLabel : UILabel = loader.petralViewById(id: "rowLabel", inView: templateView) as! UILabel;
24 | rowLabel.text = "row " + String(index + 1);
25 |
26 | let flexview2 : PetralFlexView = loader.petralViewById(id: "flexview2", inView: templateView) as! PetralFlexView;
27 | flexview2.itemDisplayAction = {(templateView2: PetralFlexTemplateView, index2 : Int) in
28 | print(index);
29 | let cellImage : UIImageView = loader.petralViewById(id: "cellImage", inView: templateView2) as! UIImageView;
30 | cellImage.image = UIImage.init(named: "head" + String(index % 3));
31 |
32 | let cellLabel : UILabel = loader.petralViewById(id: "cellLabel", inView: templateView2) as! UILabel;
33 | cellLabel.text = "item " + String(index + 1) + "-" + String(index2 + 1);
34 | };
35 | flexview2.itemClickAction = { (template2: PetralFlexTemplateView, index2 : Int) in
36 | print("item " + String(index + 1) + "-" + String(index2 + 1));
37 | }
38 | };
39 | flexview.itemClickAction = { (template: PetralFlexTemplateView, index : Int) in
40 | print("row" + String(index));
41 | }
42 | scrollview.contentSize = flexview.resize();
43 | // Do any additional setup after loading the view.
44 | }
45 |
46 | deinit {
47 | print("deinit");
48 | }
49 |
50 |
51 | /*
52 | // MARK: - Navigation
53 |
54 | // In a storyboard-based application, you will often want to do a little preparation before navigation
55 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
56 | // Get the new view controller using segue.destination.
57 | // Pass the selected object to the new view controller.
58 | }
59 | */
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/Example/Petral/EmbedFlexViewController.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Example/Petral/Images.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" : "ios-marketing",
45 | "size" : "1024x1024",
46 | "scale" : "1x"
47 | }
48 | ],
49 | "info" : {
50 | "version" : 1,
51 | "author" : "xcode"
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/Example/Petral/Images.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Example/Petral/Images.xcassets/head0.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "head0.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Petral/Images.xcassets/head0.imageset/head0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HuangZhiBin/Petral-UI/6518901c1dcc6968efd5fc78a43fe8fd6a9b4935/Example/Petral/Images.xcassets/head0.imageset/head0.png
--------------------------------------------------------------------------------
/Example/Petral/Images.xcassets/head1.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "head1.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Petral/Images.xcassets/head1.imageset/head1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HuangZhiBin/Petral-UI/6518901c1dcc6968efd5fc78a43fe8fd6a9b4935/Example/Petral/Images.xcassets/head1.imageset/head1.png
--------------------------------------------------------------------------------
/Example/Petral/Images.xcassets/head2.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "head2.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Petral/Images.xcassets/head2.imageset/head2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HuangZhiBin/Petral-UI/6518901c1dcc6968efd5fc78a43fe8fd6a9b4935/Example/Petral/Images.xcassets/head2.imageset/head2.png
--------------------------------------------------------------------------------
/Example/Petral/Images.xcassets/setting.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "setting.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Petral/Images.xcassets/setting.imageset/setting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HuangZhiBin/Petral-UI/6518901c1dcc6968efd5fc78a43fe8fd6a9b4935/Example/Petral/Images.xcassets/setting.imageset/setting.png
--------------------------------------------------------------------------------
/Example/Petral/Images.xcassets/setting2.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "setting2.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Petral/Images.xcassets/setting2.imageset/setting2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HuangZhiBin/Petral-UI/6518901c1dcc6968efd5fc78a43fe8fd6a9b4935/Example/Petral/Images.xcassets/setting2.imageset/setting2.png
--------------------------------------------------------------------------------
/Example/Petral/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UIBackgroundModes
26 |
27 | audio
28 |
29 | UILaunchStoryboardName
30 | LaunchScreen
31 | UIMainStoryboardFile
32 | Main
33 | UIRequiredDeviceCapabilities
34 |
35 | armv7
36 |
37 | UISupportedInterfaceOrientations
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationLandscapeLeft
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/Example/Petral/InjectXmlLayoutViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // InjectXmlLayoutViewController.swift
3 | // Petral_Example
4 | //
5 | // Created by huangzhibin on 2019/7/29.
6 | // Copyright © 2019 CocoaPods. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class InjectXmlLayoutViewController: UIViewController {
12 |
13 | override func viewDidLoad() {
14 | super.viewDidLoad();
15 |
16 | self.view.petralLoadXmlViews(xmlPath: "InjectXmlLayoutViewController", properties: ["text":"这是外层的text","name":"天线德德B","image":"head1"]);
17 |
18 | // Do any additional setup after loading the view.
19 | }
20 |
21 | @objc func resetUI() {
22 | print("resetUI---->>>>>>>\(self.classForCoder)");
23 | // for subview in self.view.subviews {
24 | // subview.removeFromSuperview();
25 | // }
26 |
27 | self.view.petralLoadXmlViews(xmlPath: "InjectXmlLayoutViewController", properties: ["text":"这是外层的text","name":"天线德德B","image":"head1"]);
28 | }
29 |
30 |
31 | /*
32 | // MARK: - Navigation
33 |
34 | // In a storyboard-based application, you will often want to do a little preparation before navigation
35 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
36 | // Get the new view controller using segue.destination.
37 | // Pass the selected object to the new view controller.
38 | }
39 | */
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/Example/Petral/InjectXmlLayoutViewController.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Example/Petral/LayoutViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LayoutViewController.swift
3 | // Petral
4 | //
5 | // Created by bin on 2019/6/9.
6 | // Copyright © 2019年 BinHuang. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Petral
11 |
12 | class LayoutViewController: UIViewController {
13 |
14 | override func viewDidLoad() {
15 | super.viewDidLoad();
16 |
17 | self.view.backgroundColor = UIColor.white;
18 |
19 | let label = UILabel.init();
20 | label.petralize()
21 | .frame(x: 100, y: 100, width: 200, height: 20)
22 | .font(size: 18, bold: true)
23 | .text("label")
24 | .textColor(UIColor.white)
25 | .lines(1)
26 | .align(.center)
27 | .backgroundColor(UIColor.gray)
28 | .borderColor(UIColor.red)
29 | .borderWidth(2)
30 | .cornerRadius(12);
31 | self.view.addSubview(label);
32 | label.petralRestraint
33 | .leftIn(offset: 50)
34 | .width(320)
35 | .height(120);
36 |
37 | let textField = UITextField.init();
38 | textField.petralize()
39 | .frame(x: 0, y: 100, width: 280, height: 50)
40 | .font(size: 18, bold: true)
41 | .text("textField")
42 | .placeholder("this is hint")
43 | .textColor(UIColor.white)
44 | .align(.center)
45 | .keyboardType(.numberPad)
46 | .backgroundColor(UIColor.gray)
47 | .borderColor(UIColor.red)
48 | .borderWidth(2)
49 | .cornerRadius(12);
50 | self.view.addSubview(textField);
51 | textField.petralRestraint
52 | .leftAs(label)
53 | .topTo(label, offset: 10);
54 |
55 | let label2 = UILabel.init();
56 | label2.petralize()
57 | .frame(x: 20, y: 0, width: 120, height: 100)
58 | .backgroundColor(UIColor.blue)
59 | .textColor(UIColor.white)
60 | .text("label2");
61 | self.view.addSubview(label2);
62 | label2.petralRestraint
63 | .leftIn(offset: 30)
64 | .rightIn(offset: 30)
65 | .height(40)
66 | .topTo(textField, offset: 20);
67 |
68 | let label3 = UILabel.init();
69 | label3.petralize()
70 | .frame(x: 20, y: 0, width: 120, height: 100)
71 | .backgroundColor(UIColor.purple)
72 | .textColor(UIColor.white)
73 | .text("label3");
74 | self.view.addSubview(label3);
75 | label3.petralRestraint
76 | .widthAs(label2, offset: 2)
77 | .heightAs(label2, offset: 0)
78 | .topTo(label2, offset: 10)
79 | .leftAs(label2, offset: 0);
80 |
81 | let view = UIView.init();
82 | view.petralize()
83 | .frame(x: 0, y: 360, width: 300, height: 300)
84 | .backgroundColor(UIColor.lightGray)
85 | .borderColor(UIColor.red)
86 | .borderWidth(2)
87 | .cornerRadius(12);
88 | self.view.addSubview(view);
89 | view.petralRestraint
90 | .leftIn(offset: 20)
91 | .rightIn(offset: 20)
92 | .bottomIn(offset: 20);
93 |
94 | let textView = UITextView.init();
95 | textView.petralize()
96 | .frame(x: 0, y: 0, width: 140, height: 50)
97 | .backgroundColor(UIColor.lightGray)
98 | .font(size: 18, bold: true)
99 | .text("textView")
100 | .textColor(UIColor.black)
101 | .align(.center)
102 | .borderColor(UIColor.red)
103 | .borderWidth(2)
104 | .cornerRadius(12);
105 | view.addSubview(textView);
106 | textView.petralRestraint
107 | .centerIn()
108 | .width(200)
109 | .height(100)
110 |
111 | view.petralRestraint.reset();
112 | view.petralRestraint.topTo(label3, offset: 20).leftIn(offset: 50).rightIn(offset: 80).height(200);
113 | view.petralRestraint.updateDependeds();
114 | }
115 |
116 | override func didReceiveMemoryWarning() {
117 | super.didReceiveMemoryWarning()
118 | // Dispose of any resources that can be recreated.
119 | }
120 |
121 | @objc func resetUI() {
122 | print("resetUI---->>>>>>>\(self.classForCoder)");
123 | }
124 |
125 | deinit {
126 | print("deinit");
127 | }
128 | }
129 |
130 |
--------------------------------------------------------------------------------
/Example/Petral/ListViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ListViewController.swift
3 | // Petral_Example
4 | //
5 | // Created by huangzhibin on 2019/7/22.
6 | // Copyright © 2019 CocoaPods. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Petral
11 |
12 | class ListViewController: UIViewController {
13 |
14 | override func viewDidLoad() {
15 | super.viewDidLoad();
16 |
17 | let loader = self.view.petralLoadXmlViews(xmlPath: "ListViewController");
18 |
19 | let tableView : PetralTableView = loader.petralViewById(id: "tableview1") as! PetralTableView;
20 |
21 | let headerLabel : UILabel = loader.petralViewById(id: "headerLabel", inView: tableView.tableHeaderView!) as! UILabel;
22 | headerLabel.text = "Sorry";
23 |
24 | let footerLabel : UILabel = loader.petralViewById(id: "footerLabel", inView: tableView.tableFooterView!) as! UILabel;
25 | footerLabel.text = "Babe";
26 |
27 | tableView.tableCellDisplayAction = { (cell: UITableViewCell, indexPath: IndexPath) in
28 | let cellLabel : UILabel = loader.petralViewById(id: "cellLabel", inView: cell) as! UILabel;
29 | let cellSubLabel : UILabel = loader.petralViewById(id: "cellSubLabel", inView: cell) as! UILabel;
30 | cellLabel.text = "section " + String(indexPath.section);
31 | cellSubLabel.text = "row " + String(indexPath.row);
32 |
33 | cell.selectedBackgroundView = UIView.init(frame: cell.frame);
34 | cell.selectedBackgroundView?.backgroundColor = UIColor.init(red: 250/255.0, green: 250/255.0, blue: 250/255.0, alpha: 1);
35 | };
36 | tableView.tableSectionHeaderDisplayAction = { (headerView: UIView, section: Int) in
37 | let sectionHeaderLabel : UILabel = loader.petralViewById(id: "sectionHeaderLabel", inView: headerView) as! UILabel;
38 | sectionHeaderLabel.text = "section header " + String(section);
39 | };
40 | tableView.tableSectionFooterDisplayAction = { (footerView: UIView, section: Int) in
41 | let sectionFooterLabel : UILabel = loader.petralViewById(id: "sectionFooterLabel", inView: footerView) as! UILabel;
42 | sectionFooterLabel.text = "section footer " + String(section);
43 | };
44 | tableView.tableCellClickAction = { (indexPath: IndexPath) in
45 | print(indexPath.row);
46 | };
47 | // tableView.cellRowCountAction = { (section: Int) in
48 | // if section == 0 {
49 | // return 2;
50 | // }
51 | // return 3;
52 | // };
53 | // tableView.sectionCountAction = {
54 | // return 2;
55 | // };
56 | tableView.tableSectionHeightForHeaderAction = { (section: Int) in
57 | return 60;
58 | }
59 | tableView.tableSectionHeightForFooterAction = { (section: Int) in
60 | return 40;
61 | }
62 | tableView.tableCellRowHeightAction = { (indexPath: IndexPath) in
63 | if indexPath.section == 0 {
64 | return 80;
65 | }
66 | return 120;
67 | };
68 |
69 | }
70 |
71 | deinit {
72 | print("deinit");
73 | }
74 |
75 |
76 | /*
77 | // MARK: - Navigation
78 |
79 | // In a storyboard-based application, you will often want to do a little preparation before navigation
80 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
81 | // Get the new view controller using segue.destination.
82 | // Pass the selected object to the new view controller.
83 | }
84 | */
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/Example/Petral/ListViewController.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | |
19 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Example/Petral/MyTableView.swift:
--------------------------------------------------------------------------------
1 |
2 | //
3 | // MyTableView.swift
4 | // HdParent
5 | //
6 | // Created by huangzhibin on 2019/06/11
7 | //
8 |
9 | import UIKit
10 |
11 | protocol MyTableViewDelegate : NSObjectProtocol{
12 | func didSelectItem(item: MyTableModel);
13 | }
14 |
15 | class MyTableModel: NSObject{
16 | var image: String!;
17 | var name: String!;
18 | var desc: String!;
19 |
20 | init(image: String, name: String, desc: String) {
21 | self.image = image;
22 | self.name = name;
23 | self.desc = desc;
24 | }
25 | }
26 |
27 | class MyTableView: UITableView {
28 |
29 | let CELL_IDENTIFIER = "CELL_IDENTIFIER";
30 |
31 | var items : [MyTableModel] = []{
32 | didSet{
33 | self.reloadData();
34 | }
35 | };
36 |
37 | weak var tbDelegate : MyTableViewDelegate?;
38 |
39 | override init(frame: CGRect, style: UITableViewStyle) {
40 | super.init(frame: frame, style: style);
41 |
42 | let tableView = self;
43 | tableView.backgroundColor = UIColor.green;
44 | tableView.delegate = self;
45 | tableView.dataSource = self;
46 | tableView.separatorStyle = .none;
47 | tableView.transform = CGAffineTransform(rotationAngle: -.pi / 2);
48 | tableView.showsVerticalScrollIndicator = false;
49 | tableView.register(MyTableViewCell.self, forCellReuseIdentifier: CELL_IDENTIFIER);
50 |
51 | if(tableView.responds(to: #selector(setter: UITableView.separatorInset))) {
52 | tableView.separatorInset = UIEdgeInsets.zero;
53 | }
54 | if(tableView.responds(to: #selector(setter: UITableView.layoutMargins))) {
55 | tableView.layoutMargins = UIEdgeInsets.zero;
56 | }
57 | }
58 |
59 | required init?(coder aDecoder: NSCoder) {
60 | fatalError("init(coder:) has not been implemented")
61 | }
62 | }
63 |
64 | extension MyTableView : UITableViewDelegate,UITableViewDataSource{
65 |
66 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
67 | return self.items.count;
68 | }
69 |
70 | func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
71 | return CGFloat.leastNormalMagnitude;
72 | }
73 |
74 | func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
75 | return MyTableViewCell.CELL_WIDTH;
76 | }
77 |
78 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
79 | let cell = tableView.dequeueReusableCell(withIdentifier: CELL_IDENTIFIER, for: indexPath) as! MyTableViewCell;
80 |
81 | let childModel = self.items[indexPath.row];
82 | cell.topImageView.image = UIImage.init(named: childModel.image);
83 | cell.nameLabel.text = childModel.name;
84 | cell.descLabel.text = childModel.desc;
85 |
86 |
87 |
88 | cell.selectedBackgroundView = UIView.init(frame: cell.frame);
89 | cell.selectedBackgroundView?.backgroundColor = UIColor.orange;
90 |
91 | return cell;
92 | }
93 |
94 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
95 | tableView.deselectRow(at: indexPath, animated: false);
96 |
97 | let item = self.items[indexPath.row];
98 | if(self.tbDelegate != nil){
99 | self.tbDelegate?.didSelectItem(item: item);
100 | }
101 | }
102 | }
103 |
104 | class MyTableViewCell: UITableViewCell {
105 |
106 | static let CELL_WIDTH : CGFloat = 100;
107 | static let CELL_HEIGHT : CGFloat = 140;
108 |
109 | var topImageView: UIImageView!;
110 | var nameLabel: UILabel!;
111 | var descLabel: UILabel!;
112 |
113 | override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
114 | super.init(style: style, reuseIdentifier: reuseIdentifier);
115 |
116 | self.initViews();
117 | }
118 |
119 | func initViews(){
120 | //self.contentView.backgroundColor = UIColor.purple;
121 |
122 | let containerView = UIView.init(frame: CGRect.init(x: 0, y: 0, width: MyTableViewCell.CELL_WIDTH, height: MyTableViewCell.CELL_HEIGHT));
123 | containerView.backgroundColor = UIColor.blue;
124 | let loader = containerView.petralLoadXmlViews(xmlPath: "MyTableViewCell");
125 | self.contentView.addSubview(containerView);
126 |
127 | containerView.transform = CGAffineTransform(rotationAngle: .pi / 2);
128 | containerView.petralRestraint.leftIn().topIn();
129 |
130 | self.topImageView = loader.petralViewById(id: "topImageView") as? UIImageView;
131 | self.nameLabel = loader.petralViewById(id: "nameLabel") as? UILabel;
132 | self.descLabel = loader.petralViewById(id: "descLabel") as? UILabel;
133 |
134 | // self.contentView.petralRestraint.rightIn().topIn();
135 | }
136 |
137 | required init?(coder aDecoder: NSCoder) {
138 | fatalError("init(coder:) has not been implemented")
139 | }
140 |
141 | }
142 |
--------------------------------------------------------------------------------
/Example/Petral/MyTableViewCell.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Example/Petral/MyTableViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MyTableViewController.swift
3 | // Petral_Example
4 | //
5 | // Created by huangzhibin on 2019/7/15.
6 | // Copyright © 2019 CocoaPods. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class MyTableViewController: UIViewController {
12 |
13 | override func viewDidLoad() {
14 | super.viewDidLoad()
15 |
16 | self.view.backgroundColor = UIColor.white;
17 |
18 | let loader = self.view.petralLoadXmlViews(xmlPath: "MyTableViewController");
19 |
20 | // Do any additional setup after loading the view.
21 | let tableView : MyTableView = loader.petralViewById(id: "tableView") as! MyTableView;
22 | // tableView.petralRestraint.leftIn().rightIn().topIn().height(200);
23 |
24 | tableView.items = [
25 | MyTableModel.init(image: "setting", name: "name1", desc: "desc1"),
26 | MyTableModel.init(image: "setting2", name: "name2", desc: "desc2"),
27 | MyTableModel.init(image: "setting", name: "name3", desc: "desc3"),
28 | MyTableModel.init(image: "setting2", name: "name4", desc: "desc4"),
29 | MyTableModel.init(image: "setting2", name: "name5", desc: "desc5"),
30 | MyTableModel.init(image: "setting", name: "name6", desc: "desc6")
31 | ];
32 |
33 | let button = loader.petralViewById(id: "button") as! UIButton;
34 | button.addTarget(self, action: #selector(self.back), for: .touchUpInside);
35 | }
36 |
37 | @objc func back(){
38 | self.dismiss(animated: true, completion: nil);
39 | }
40 |
41 |
42 | /*
43 | // MARK: - Navigation
44 |
45 | // In a storyboard-based application, you will often want to do a little preparation before navigation
46 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
47 | // Get the new view controller using segue.destination.
48 | // Pass the selected object to the new view controller.
49 | }
50 | */
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/Example/Petral/MyTableViewController.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Example/Petral/Petral-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | //
2 | // Petral-Bridging-Header.h
3 | // Petral
4 | //
5 | // Created by huangzhibin on 2019/8/6.
6 | // Copyright © 2019 CocoaPods. All rights reserved.
7 | //
8 |
9 | #import "PetralHttpManager.h"
10 |
--------------------------------------------------------------------------------
/Example/Petral/RedImageView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RedImageView.swift
3 | // Petral_Example
4 | //
5 | // Created by huangzhibin on 2019/7/12.
6 | // Copyright © 2019 CocoaPods. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class RedImageView: UIImageView {
12 |
13 | override init(frame: CGRect) {
14 | super.init(frame: frame);
15 |
16 | self.backgroundColor = UIColor.red;
17 | }
18 |
19 | required init?(coder aDecoder: NSCoder) {
20 | fatalError("init(coder:) has not been implemented")
21 | }
22 |
23 | /*
24 | // Only override draw() if you perform custom drawing.
25 | // An empty implementation adversely affects performance during animation.
26 | override func draw(_ rect: CGRect) {
27 | // Drawing code
28 | }
29 | */
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/Example/Petral/RowFlexViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RowFlexViewController.swift
3 | // Petral_Example
4 | //
5 | // Created by huangzhibin on 2019/7/29.
6 | // Copyright © 2019 CocoaPods. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Petral
11 |
12 | class RowFlexViewController: UIViewController {
13 |
14 | override func viewDidLoad() {
15 | super.viewDidLoad();
16 |
17 | let loader = self.view.petralLoadXmlViews(xmlPath: "RowFlexViewController");
18 | let flexview = loader.petralViewById(id: "flexview") as! PetralFlexView;
19 | let scrollview = loader.petralViewById(id: "scrollview") as! UIScrollView;
20 | //itemCountAction为可选方法,固定的count可直接在xml定义p-item-count的值
21 | flexview.itemCountAction = {
22 | return 20;
23 | }
24 | flexview.itemDisplayAction = {(templateView: PetralFlexTemplateView, index : Int) in
25 | print(index);
26 | let cellImage : UIImageView = loader.petralViewById(id: "cellImage", inView: templateView) as! UIImageView;
27 | cellImage.image = UIImage.init(named: "head" + String(index % 3));
28 |
29 | let cellLabel : UILabel = loader.petralViewById(id: "cellLabel", inView: templateView) as! UILabel;
30 | cellLabel.text = "User " + String(index + 1);
31 | };
32 | flexview.itemClickAction = { (template: PetralFlexTemplateView, index : Int) in
33 | print(index);
34 | }
35 | scrollview.contentSize = flexview.resize();
36 | // Do any additional setup after loading the view.
37 | }
38 |
39 | deinit {
40 | print("deinit");
41 | }
42 |
43 |
44 | /*
45 | // MARK: - Navigation
46 |
47 | // In a storyboard-based application, you will often want to do a little preparation before navigation
48 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
49 | // Get the new view controller using segue.destination.
50 | // Pass the selected object to the new view controller.
51 | }
52 | */
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/Example/Petral/RowFlexViewController.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Example/Petral/SectionListViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SectionListViewController.swift
3 | // Petral_Example
4 | //
5 | // Created by huangzhibin on 2019/7/22.
6 | // Copyright © 2019 CocoaPods. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Petral
11 |
12 | class SectionListViewController: UIViewController {
13 |
14 | override func viewDidLoad() {
15 | super.viewDidLoad();
16 |
17 | let loader = self.view.petralLoadXmlViews(xmlPath: "SectionListViewController");
18 |
19 | let tableView : PetralTableView = loader.petralViewById(id: "tableview1") as! PetralTableView;
20 |
21 | let headerLabel : UILabel = loader.petralViewById(id: "headerLabel", inView: tableView.tableHeaderView!) as! UILabel;
22 | headerLabel.text = "Yep, I am header.";
23 |
24 | let footerLabel : UILabel = loader.petralViewById(id: "footerLabel", inView: tableView.tableFooterView!) as! UILabel;
25 | footerLabel.text = "Yep, I am footer.";
26 |
27 | tableView.tableCellDisplayAction = { (cell: UITableViewCell, indexPath: IndexPath) in
28 | let cellImage : UIImageView = loader.petralViewById(id: "cellImage", inView: cell) as! UIImageView;
29 | cellImage.image = UIImage.init(named: "head" + String(indexPath.row % 3));
30 |
31 | let cellLabel : UILabel = loader.petralViewById(id: "cellLabel", inView: cell) as! UILabel;
32 | cellLabel.text = "section " + String(indexPath.section);
33 |
34 | let cellSubLabel : UILabel = loader.petralViewById(id: "cellSubLabel", inView: cell) as! UILabel;
35 | cellSubLabel.text = "row " + String(indexPath.row);
36 |
37 | cell.selectedBackgroundView = UIView.init(frame: cell.frame);
38 | cell.selectedBackgroundView?.backgroundColor = UIColor.init(red: 250/255.0, green: 250/255.0, blue: 250/255.0, alpha: 1);
39 | };
40 | tableView.tableSectionHeaderDisplayAction = { (headerView: UIView, section: Int) in
41 | let sectionHeaderLabel : UILabel = loader.petralViewById(id: "sectionHeaderLabel", inView: headerView) as! UILabel;
42 | sectionHeaderLabel.text = "section header " + String(section);
43 | };
44 | tableView.tableSectionFooterDisplayAction = { (footerView: UIView, section: Int) in
45 | let sectionFooterLabel : UILabel = loader.petralViewById(id: "sectionFooterLabel", inView: footerView) as! UILabel;
46 | sectionFooterLabel.text = "section footer " + String(section);
47 | };
48 | tableView.tableCellClickAction = { (indexPath: IndexPath) in
49 | print(indexPath.row);
50 | };
51 | // tableView.cellRowCountAction = { (section: Int) in
52 | // if section == 0 {
53 | // return 2;
54 | // }
55 | // return 3;
56 | // };
57 | // tableView.sectionCountAction = {
58 | // return 2;
59 | // };
60 | tableView.tableSectionHeightForHeaderAction = { (section: Int) in
61 | return 60;
62 | }
63 | tableView.tableSectionHeightForFooterAction = { (section: Int) in
64 | return 40;
65 | }
66 | tableView.tableCellRowHeightAction = { (indexPath: IndexPath) in
67 | if indexPath.section == 0 {
68 | return 80;
69 | }
70 | return 120;
71 | };
72 |
73 | }
74 |
75 | deinit {
76 | print("deinit");
77 | }
78 |
79 |
80 | /*
81 | // MARK: - Navigation
82 |
83 | // In a storyboard-based application, you will often want to do a little preparation before navigation
84 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
85 | // Get the new view controller using segue.destination.
86 | // Pass the selected object to the new view controller.
87 | }
88 | */
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/Example/Petral/SectionListViewController.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | |
19 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Example/Petral/SimpleListViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SimpleListViewController.swift
3 | // Petral_Example
4 | //
5 | // Created by huangzhibin on 2019/7/22.
6 | // Copyright © 2019 CocoaPods. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Petral
11 |
12 | class SimpleListViewController: UIViewController {
13 |
14 | override func viewDidLoad() {
15 | super.viewDidLoad();
16 |
17 | let loader = self.view.petralLoadXmlViews(xmlPath: "SimpleListViewController");
18 |
19 | let tableView : PetralTableView = loader.petralViewById(id: "tableview1") as! PetralTableView;
20 |
21 | tableView.tableCellDisplayAction = { (cell: UITableViewCell, indexPath: IndexPath) in
22 | let cellImage : UIImageView = loader.petralViewById(id: "cellImage", inView: cell) as! UIImageView;
23 | cellImage.image = UIImage.init(named: "head" + String(indexPath.row % 3));
24 |
25 | let cellLabel : UILabel = loader.petralViewById(id: "cellLabel", inView: cell) as! UILabel;
26 | cellLabel.text = "section " + String(indexPath.section);
27 |
28 | let cellSubLabel : UILabel = loader.petralViewById(id: "cellSubLabel", inView: cell) as! UILabel;
29 | cellSubLabel.text = "row " + String(indexPath.row);
30 |
31 | cell.selectedBackgroundView = UIView.init(frame: cell.frame);
32 | cell.selectedBackgroundView?.backgroundColor = UIColor.init(red: 250/255.0, green: 250/255.0, blue: 250/255.0, alpha: 1);
33 | };
34 | tableView.tableCellClickAction = { (indexPath: IndexPath) in
35 | print(indexPath.row);
36 | };
37 |
38 | }
39 |
40 | deinit {
41 | print("deinit");
42 | }
43 |
44 |
45 | /*
46 | // MARK: - Navigation
47 |
48 | // In a storyboard-based application, you will often want to do a little preparation before navigation
49 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
50 | // Get the new view controller using segue.destination.
51 | // Pass the selected object to the new view controller.
52 | }
53 | */
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/Example/Petral/SimpleListViewController.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Example/Petral/UserInfoView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UserInfoView.swift
3 | // Petral_Example
4 | //
5 | // Created by huangzhibin on 2019/7/12.
6 | // Copyright © 2019 CocoaPods. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class UserInfoView: UIView {
12 |
13 | override init(frame: CGRect) {
14 | super.init(frame: frame);
15 |
16 | self.petralXmlResource = "UserInfoView";
17 | }
18 |
19 | required init?(coder aDecoder: NSCoder) {
20 | super.init(coder: aDecoder);
21 | }
22 |
23 | /*
24 | // Only override draw() if you perform custom drawing.
25 | // An empty implementation adversely affects performance during animation.
26 | override func draw(_ rect: CGRect) {
27 | // Drawing code
28 | }
29 | */
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/Example/Petral/UserInfoView.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
20 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/Example/Petral/UserProfileView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UserProfileView.swift
3 | // Petral_Example
4 | //
5 | // Created by huangzhibin on 2019/7/30.
6 | // Copyright © 2019 CocoaPods. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class UserProfileView: UIView {
12 |
13 | override init(frame: CGRect) {
14 | super.init(frame: frame);
15 | //xml出现的自定义view需要指定petralXmlResource
16 | self.petralXmlResource = "UserProfileView";
17 | }
18 |
19 | required init?(coder aDecoder: NSCoder) {
20 | super.init(coder: aDecoder);
21 | }
22 |
23 | /*
24 | // Only override draw() if you perform custom drawing.
25 | // An empty implementation adversely affects performance during animation.
26 | override func draw(_ rect: CGRect) {
27 | // Drawing code
28 | }
29 | */
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/Example/Petral/UserProfileView.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Example/Petral/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // Petral_Example
4 | //
5 | // Created by huangzhibin on 2019/7/29.
6 | // Copyright © 2019 CocoaPods. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Petral
11 |
12 | class ViewController: UIViewController {
13 |
14 | let SECTIONS = ["基础功能", "XML布局", "UITableView", "FlexView"];
15 |
16 | let CELLS = [
17 | ["属性连续调用+自动布局"],
18 | ["XML布局的例子", "动态变量注入"],
19 | ["基本样式", "丰富样式", "动态数据刷新"],
20 | ["横向Flex", "纵向Flex", "横向平铺Flex", "多层嵌套Flex", "动态数据刷新"]
21 | ];
22 |
23 | let VCS = [
24 | [LayoutViewController.classForCoder()],
25 | [XmlLayoutViewController.classForCoder(), InjectXmlLayoutViewController.classForCoder()],
26 | [SimpleListViewController.classForCoder(), SectionListViewController.classForCoder(), DataListViewController.classForCoder()],
27 | [RowFlexViewController.classForCoder(), ColumnFlexViewController.classForCoder(), WrapFlexViewController.classForCoder(), EmbedFlexViewController.classForCoder(), DataFlexViewController.classForCoder()]
28 | ];
29 |
30 | override func viewDidLoad() {
31 | super.viewDidLoad();
32 |
33 | self.title = "Petral-UI";
34 |
35 | self.initUI();
36 | }
37 |
38 | func initUI() {
39 | let loader = self.view.petralLoadXmlViews(xmlPath: "ViewController");
40 |
41 | let tableView : PetralTableView = loader.petralViewById(id: "tableview1") as! PetralTableView;
42 | tableView.tableCellDisplayAction = { [weak self] (cell: UITableViewCell, indexPath: IndexPath) in
43 | let cellLabel : UILabel = loader.petralViewById(id: "cellLabel", inView: cell) as! UILabel;
44 | cellLabel.text = String(indexPath.row + 1) + ". " + (self?.CELLS[indexPath.section][indexPath.row])!;
45 | cell.selectedBackgroundView = UIView.init(frame: cell.frame);
46 | cell.selectedBackgroundView?.backgroundColor = UIColor.init(red: 230/255.0, green: 230/255.0, blue: 230/255.0, alpha: 1);
47 | };
48 | tableView.tableSectionHeaderDisplayAction = { [weak self] (headerView: UIView, section: Int) in
49 | let sectionHeaderLabel : UILabel = loader.petralViewById(id: "sectionHeaderLabel", inView: headerView) as! UILabel;
50 | sectionHeaderLabel.text = self?.SECTIONS[section];
51 | };
52 | tableView.tableCellRowCountAction = { [weak self] (section: Int) in
53 | return (self?.CELLS[section].count)!;
54 | };
55 | tableView.tableSectionCountAction = { [weak self] in
56 | return self!.SECTIONS.count;
57 | };
58 | tableView.tableCellClickAction = { [weak self] (indexPath: IndexPath) in
59 | print(indexPath.row);
60 | let typeClass : UIViewController.Type = (self?.VCS[indexPath.section][indexPath.row])! as! UIViewController.Type;
61 | self?.show(typeClass.init(), sender: nil);
62 | };
63 | }
64 |
65 | @objc func resetUI() {
66 | print("resetUI---->>>>>>>\(self.classForCoder)");
67 | self.initUI();
68 | }
69 |
70 | /*
71 | // MARK: - Navigation
72 |
73 | // In a storyboard-based application, you will often want to do a little preparation before navigation
74 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
75 | // Get the new view controller using segue.destination.
76 | // Pass the selected object to the new view controller.
77 | }
78 | */
79 |
80 | }
81 |
--------------------------------------------------------------------------------
/Example/Petral/ViewController.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Example/Petral/WrapFlexViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // WrapFlexViewController.swift
3 | // Petral_Example
4 | //
5 | // Created by huangzhibin on 2019/7/29.
6 | // Copyright © 2019 CocoaPods. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Petral
11 |
12 | class WrapFlexViewController: UIViewController {
13 |
14 | override func viewDidLoad() {
15 | super.viewDidLoad();
16 |
17 | let loader = self.view.petralLoadXmlViews(xmlPath: "WrapFlexViewController");
18 | let flexview = loader.petralViewById(id: "flexview") as! PetralFlexView;
19 | let scrollview = loader.petralViewById(id: "scrollview") as! UIScrollView;
20 | flexview.itemDisplayAction = { (templateView: PetralFlexTemplateView, index : Int) in
21 | print(index);
22 | let cellImage : UIImageView = loader.petralViewById(id: "cellImage", inView: templateView) as! UIImageView;
23 | cellImage.image = UIImage.init(named: "head" + String(index % 3));
24 |
25 | let cellLabel : UILabel = loader.petralViewById(id: "cellLabel", inView: templateView) as! UILabel;
26 | cellLabel.text = "User " + String(index + 1);
27 | };
28 | flexview.itemClickAction = { (template: PetralFlexTemplateView, index : Int) in
29 | print(index);
30 | }
31 | scrollview.contentSize = flexview.resize();
32 | // Do any additional setup after loading the view.
33 | }
34 |
35 | deinit {
36 | print("deinit");
37 | }
38 |
39 |
40 | /*
41 | // MARK: - Navigation
42 |
43 | // In a storyboard-based application, you will often want to do a little preparation before navigation
44 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
45 | // Get the new view controller using segue.destination.
46 | // Pass the selected object to the new view controller.
47 | }
48 | */
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/Example/Petral/WrapFlexViewController.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Example/Petral/XmlLayoutViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // XmlLayoutViewController.swift
3 | // Petral_Example
4 | //
5 | // Created by huangzhibin on 2019/7/29.
6 | // Copyright © 2019 CocoaPods. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Petral
11 |
12 | class XmlLayoutViewController: UIViewController {
13 |
14 | override func viewDidLoad() {
15 | super.viewDidLoad();
16 |
17 | self.view.petralLoadXmlViews(xmlPath: "XmlLayoutViewController");
18 |
19 | }
20 |
21 | @objc func resetUI() {
22 | print("resetUI---->>>>>>>\(self.classForCoder)");
23 | self.view.petralLoadXmlViews(xmlPath: "XmlLayoutViewController");
24 | }
25 |
26 |
27 | /*
28 | // MARK: - Navigation
29 |
30 | // In a storyboard-based application, you will often want to do a little preparation before navigation
31 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
32 | // Get the new view controller using segue.destination.
33 | // Pass the selected object to the new view controller.
34 | }
35 | */
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/Example/Petral/XmlLayoutViewController.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Example/Petral/XmlViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // XmlViewController.swift
3 | // Petral_Example
4 | //
5 | // Created by huangzhibin on 2019/7/11.
6 | // Copyright © 2019 CocoaPods. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Petral
11 |
12 | class XmlViewController: UIViewController {
13 |
14 | override func viewDidLoad() {
15 | super.viewDidLoad()
16 |
17 | // Do any additional setup after loading the view.
18 |
19 | let properties = [
20 | "showManyView": String(true),
21 | "time" : "10",
22 | "time2" : "3",
23 | "showRed" : String(true),
24 | "element": "风风雨雨我都不畏惧但求共醉"
25 | ];
26 | let loader = self.view.petralLoadXmlViews(xmlPath: "XmlViewController", properties: properties);
27 |
28 | let imageView = loader.petralViewById(id: "image1") as! UIImageView;
29 | imageView.image = UIImage.init(named: "setting2");
30 |
31 | let userInfoView = loader.petralViewById(id: "userInfoView") as! UserInfoView;
32 | userInfoView.petralRestraint.leftIn(offset: 50).rightIn(offset: 150);
33 | userInfoView.petralRestraint.updateDependeds();
34 |
35 | let button1 = loader.petralViewById(id: "button1") as! UIButton;
36 | button1.addTarget(self, action: #selector(self.back), for: .touchUpInside);
37 |
38 | /*
39 | let flexView1 = loader.petralViewById(id: "flexView1") as! PetralFlexView;
40 | flexView1.itemDisplayAction = { [weak self] (templateView: PetralFlexTemplateView, index : Int) in
41 | print(index);
42 |
43 | let flexView2 = loader.petralViewById(id: "flexView2", inView: templateView) as! PetralFlexView;
44 |
45 | flexView2.itemDisplayAction = { [weak self] (templateView2: PetralFlexTemplateView, index2 : Int) in
46 | let cellImage = loader.petralViewById(id: "cellImage", inView: templateView2) as? UIImageView;
47 | cellImage?.image = UIImage.init(named: "setting2");
48 |
49 | let cellLabel = loader.petralViewById(id: "cellLabel", inView: templateView2) as? UILabel;
50 | cellLabel?.text = "Item" + String(index2 + 1);
51 |
52 | let flexView3 = loader.petralViewById(id: "flexView3", inView: templateView2) as! PetralFlexView;
53 |
54 | flexView3.itemDisplayAction = { [weak self] (templateView3: PetralFlexTemplateView, index3 : Int) in
55 | let subImage = loader.petralViewById(id: "subImage", inView: templateView3) as? UIImageView;
56 | subImage?.image = UIImage.init(named: "setting2");
57 |
58 | let subLabel = loader.petralViewById(id: "subLabel", inView: templateView3) as? UILabel;
59 | subLabel?.text = String(index + 1) + "-" + String(index2 + 1) + "-" + String(index3 + 1);
60 | }
61 | };
62 | }
63 | */
64 | let flexview = loader.petralViewById(id: "flexview") as! PetralFlexView;
65 | flexview.itemWidthAction = { (index: Int) in
66 | return CGFloat(index + 1) * 10;
67 | };
68 | flexview.itemHeightAction = { (index: Int) in
69 | return CGFloat(index + 1) * 12;
70 | };
71 | flexview.itemDisplayAction = { (templateView: PetralFlexTemplateView, index : Int) in
72 | print(index);
73 | let cellImage = loader.petralViewById(id: "cellIcon", inView: templateView) as? UIImageView;
74 | cellImage?.image = UIImage.init(named: "setting2");
75 |
76 | let cellLabel = loader.petralViewById(id: "cellInfo", inView: templateView) as? UILabel;
77 | cellLabel?.text = "Item" + String(index + 1);
78 | };
79 | flexview.itemClickAction = { (template: PetralFlexTemplateView, index : Int) in
80 | print(index);
81 | }
82 |
83 | //self.view.petralLoadXmlViews(xmlPath: "ListViewController");
84 |
85 | let testView = loader.petralViewById(id: "testView");
86 | testView?.frame.size.width = 300;
87 | testView?.frame.size.height = 100;
88 | testView?.petralRestraint.updateDependeds();
89 | }
90 |
91 | @objc func back(){
92 | self.dismiss(animated: true, completion: nil);
93 | }
94 |
95 | deinit {
96 | print("deinit");
97 | }
98 |
99 | /*
100 | // MARK: - Navigation
101 |
102 | // In a storyboard-based application, you will often want to do a little preparation before navigation
103 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
104 | // Get the new view controller using segue.destination.
105 | // Pass the selected object to the new view controller.
106 | }
107 | */
108 |
109 | }
110 |
--------------------------------------------------------------------------------
/Example/Petral/XmlViewController.xml:
--------------------------------------------------------------------------------
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 |
27 |
28 |
29 |
30 |
31 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/Example/Petral/petral-ui.xsd:
--------------------------------------------------------------------------------
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 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
--------------------------------------------------------------------------------
/Example/Petral/test.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
18 |
19 |
31 |
43 |
44 |
52 |
62 |
72 |
83 |
84 |
85 |
86 |
91 |
92 |
101 |
102 |
103 |
110 |
121 |
122 |
126 |
127 |
--------------------------------------------------------------------------------
/Example/Podfile:
--------------------------------------------------------------------------------
1 | use_frameworks!
2 |
3 | target 'Petral_Example' do
4 | pod 'Petral', :path => '../'
5 |
6 | target 'Petral_Tests' do
7 | inherit! :search_paths
8 |
9 |
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/Example/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Petral (0.1.0)
3 |
4 | DEPENDENCIES:
5 | - Petral (from `../`)
6 |
7 | EXTERNAL SOURCES:
8 | Petral:
9 | :path: "../"
10 |
11 | SPEC CHECKSUMS:
12 | Petral: 6aa4cacc2bd0a1c20ca97fc7f8f1e77494405a87
13 |
14 | PODFILE CHECKSUM: c52a46443d0daf816d14cc1f12047dd781b75e53
15 |
16 | COCOAPODS: 1.6.1
17 |
--------------------------------------------------------------------------------
/Example/Pods/Local Podspecs/Petral.podspec.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Petral",
3 | "version": "0.1.0",
4 | "summary": "A short description of Petral.",
5 | "description": "TODO: Add long description of the pod here.",
6 | "homepage": "https://github.com/ikrboy@163.com/Petral",
7 | "license": {
8 | "type": "MIT",
9 | "file": "LICENSE"
10 | },
11 | "authors": {
12 | "ikrboy@163.com": "HUANGZHIBIN327@pingan.com.cn"
13 | },
14 | "source": {
15 | "git": "https://github.com/ikrboy@163.com/Petral.git",
16 | "tag": "0.1.0"
17 | },
18 | "platforms": {
19 | "ios": "8.0"
20 | },
21 | "source_files": "Petral/Classes/**/*"
22 | }
23 |
--------------------------------------------------------------------------------
/Example/Pods/Manifest.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Petral (0.1.0)
3 |
4 | DEPENDENCIES:
5 | - Petral (from `../`)
6 |
7 | EXTERNAL SOURCES:
8 | Petral:
9 | :path: "../"
10 |
11 | SPEC CHECKSUMS:
12 | Petral: 6aa4cacc2bd0a1c20ca97fc7f8f1e77494405a87
13 |
14 | PODFILE CHECKSUM: c52a46443d0daf816d14cc1f12047dd781b75e53
15 |
16 | COCOAPODS: 1.6.1
17 |
--------------------------------------------------------------------------------
/Example/Pods/Pods.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Example/Pods/Pods.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Example/Pods/Pods.xcodeproj/project.xcworkspace/xcuserdata/huangzhibin327.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HuangZhiBin/Petral-UI/6518901c1dcc6968efd5fc78a43fe8fd6a9b4935/Example/Pods/Pods.xcodeproj/project.xcworkspace/xcuserdata/huangzhibin327.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Example/Pods/Pods.xcodeproj/project.xcworkspace/xcuserdata/huangzhibin327.xcuserdatad/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | BuildLocationStyle
6 | UseTargetSettings
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Example/Pods/Pods.xcodeproj/xcuserdata/huangzhibin327.xcuserdatad/xcschemes/Petral.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
44 |
45 |
46 |
52 |
53 |
55 |
56 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/Example/Pods/Pods.xcodeproj/xcuserdata/huangzhibin327.xcuserdatad/xcschemes/Pods-Petral_Example.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
35 |
45 |
46 |
52 |
53 |
54 |
55 |
56 |
57 |
63 |
64 |
66 |
67 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/Example/Pods/Pods.xcodeproj/xcuserdata/huangzhibin327.xcuserdatad/xcschemes/Pods-Petral_Tests.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
35 |
45 |
46 |
52 |
53 |
54 |
55 |
56 |
57 |
63 |
64 |
66 |
67 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/Example/Pods/Pods.xcodeproj/xcuserdata/huangzhibin327.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | Petral.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 1
11 |
12 | Pods-Petral_Example.xcscheme_^#shared#^_
13 |
14 | orderHint
15 | 2
16 |
17 | Pods-Petral_Tests.xcscheme_^#shared#^_
18 |
19 | orderHint
20 | 3
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Petral/Petral-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 0.1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Petral/Petral-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Petral : NSObject
3 | @end
4 | @implementation PodsDummy_Petral
5 | @end
6 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Petral/Petral-prefix.pch:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Petral/Petral-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
14 | FOUNDATION_EXPORT double PetralVersionNumber;
15 | FOUNDATION_EXPORT const unsigned char PetralVersionString[];
16 |
17 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Petral/Petral.modulemap:
--------------------------------------------------------------------------------
1 | framework module Petral {
2 | umbrella header "Petral-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Petral/Petral.xcconfig:
--------------------------------------------------------------------------------
1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Petral
2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
3 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
4 | PODS_BUILD_DIR = ${BUILD_DIR}
5 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
6 | PODS_ROOT = ${SRCROOT}
7 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../..
8 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
9 | SKIP_INSTALL = YES
10 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-Petral_Example/Pods-Petral_Example-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-Petral_Example/Pods-Petral_Example-acknowledgements.markdown:
--------------------------------------------------------------------------------
1 | # Acknowledgements
2 | This application makes use of the following third party libraries:
3 |
4 | ## Petral
5 |
6 | Copyright (c) 2019 ikrboy@163.com
7 |
8 | Permission is hereby granted, free of charge, to any person obtaining a copy
9 | of this software and associated documentation files (the "Software"), to deal
10 | in the Software without restriction, including without limitation the rights
11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | copies of the Software, and to permit persons to whom the Software is
13 | furnished to do so, subject to the following conditions:
14 |
15 | The above copyright notice and this permission notice shall be included in
16 | all copies or substantial portions of the Software.
17 |
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | THE SOFTWARE.
25 |
26 | Generated by CocoaPods - https://cocoapods.org
27 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-Petral_Example/Pods-Petral_Example-acknowledgements.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreferenceSpecifiers
6 |
7 |
8 | FooterText
9 | This application makes use of the following third party libraries:
10 | Title
11 | Acknowledgements
12 | Type
13 | PSGroupSpecifier
14 |
15 |
16 | FooterText
17 | Copyright (c) 2019 ikrboy@163.com <BinHuang>
18 |
19 | Permission is hereby granted, free of charge, to any person obtaining a copy
20 | of this software and associated documentation files (the "Software"), to deal
21 | in the Software without restriction, including without limitation the rights
22 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
23 | copies of the Software, and to permit persons to whom the Software is
24 | furnished to do so, subject to the following conditions:
25 |
26 | The above copyright notice and this permission notice shall be included in
27 | all copies or substantial portions of the Software.
28 |
29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
34 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
35 | THE SOFTWARE.
36 |
37 | License
38 | MIT
39 | Title
40 | Petral
41 | Type
42 | PSGroupSpecifier
43 |
44 |
45 | FooterText
46 | Generated by CocoaPods - https://cocoapods.org
47 | Title
48 |
49 | Type
50 | PSGroupSpecifier
51 |
52 |
53 | StringsTable
54 | Acknowledgements
55 | Title
56 | Acknowledgements
57 |
58 |
59 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-Petral_Example/Pods-Petral_Example-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Pods_Petral_Example : NSObject
3 | @end
4 | @implementation PodsDummy_Pods_Petral_Example
5 | @end
6 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-Petral_Example/Pods-Petral_Example-frameworks.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -e
3 | set -u
4 | set -o pipefail
5 |
6 | function on_error {
7 | echo "$(realpath -mq "${0}"):$1: error: Unexpected failure"
8 | }
9 | trap 'on_error $LINENO' ERR
10 |
11 | if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then
12 | # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy
13 | # frameworks to, so exit 0 (signalling the script phase was successful).
14 | exit 0
15 | fi
16 |
17 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
18 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
19 |
20 | COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}"
21 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}"
22 |
23 | # Used as a return value for each invocation of `strip_invalid_archs` function.
24 | STRIP_BINARY_RETVAL=0
25 |
26 | # This protects against multiple targets copying the same framework dependency at the same time. The solution
27 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html
28 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????")
29 |
30 | # Copies and strips a vendored framework
31 | install_framework()
32 | {
33 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then
34 | local source="${BUILT_PRODUCTS_DIR}/$1"
35 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then
36 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")"
37 | elif [ -r "$1" ]; then
38 | local source="$1"
39 | fi
40 |
41 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
42 |
43 | if [ -L "${source}" ]; then
44 | echo "Symlinked..."
45 | source="$(readlink "${source}")"
46 | fi
47 |
48 | # Use filter instead of exclude so missing patterns don't throw errors.
49 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\""
50 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}"
51 |
52 | local basename
53 | basename="$(basename -s .framework "$1")"
54 | binary="${destination}/${basename}.framework/${basename}"
55 |
56 | if ! [ -r "$binary" ]; then
57 | binary="${destination}/${basename}"
58 | elif [ -L "${binary}" ]; then
59 | echo "Destination binary is symlinked..."
60 | dirname="$(dirname "${binary}")"
61 | binary="${dirname}/$(readlink "${binary}")"
62 | fi
63 |
64 | # Strip invalid architectures so "fat" simulator / device frameworks work on device
65 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then
66 | strip_invalid_archs "$binary"
67 | fi
68 |
69 | # Resign the code if required by the build settings to avoid unstable apps
70 | code_sign_if_enabled "${destination}/$(basename "$1")"
71 |
72 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7.
73 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then
74 | local swift_runtime_libs
75 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u)
76 | for lib in $swift_runtime_libs; do
77 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\""
78 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}"
79 | code_sign_if_enabled "${destination}/${lib}"
80 | done
81 | fi
82 | }
83 |
84 | # Copies and strips a vendored dSYM
85 | install_dsym() {
86 | local source="$1"
87 | if [ -r "$source" ]; then
88 | # Copy the dSYM into a the targets temp dir.
89 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\""
90 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}"
91 |
92 | local basename
93 | basename="$(basename -s .framework.dSYM "$source")"
94 | binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}"
95 |
96 | # Strip invalid architectures so "fat" simulator / device frameworks work on device
97 | if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then
98 | strip_invalid_archs "$binary"
99 | fi
100 |
101 | if [[ $STRIP_BINARY_RETVAL == 1 ]]; then
102 | # Move the stripped file into its final destination.
103 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\""
104 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}"
105 | else
106 | # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing.
107 | touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM"
108 | fi
109 | fi
110 | }
111 |
112 | # Signs a framework with the provided identity
113 | code_sign_if_enabled() {
114 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY:-}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then
115 | # Use the current code_sign_identity
116 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}"
117 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'"
118 |
119 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then
120 | code_sign_cmd="$code_sign_cmd &"
121 | fi
122 | echo "$code_sign_cmd"
123 | eval "$code_sign_cmd"
124 | fi
125 | }
126 |
127 | # Strip invalid architectures
128 | strip_invalid_archs() {
129 | binary="$1"
130 | # Get architectures for current target binary
131 | binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)"
132 | # Intersect them with the architectures we are building for
133 | intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)"
134 | # If there are no archs supported by this binary then warn the user
135 | if [[ -z "$intersected_archs" ]]; then
136 | echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)."
137 | STRIP_BINARY_RETVAL=0
138 | return
139 | fi
140 | stripped=""
141 | for arch in $binary_archs; do
142 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then
143 | # Strip non-valid architectures in-place
144 | lipo -remove "$arch" -output "$binary" "$binary"
145 | stripped="$stripped $arch"
146 | fi
147 | done
148 | if [[ "$stripped" ]]; then
149 | echo "Stripped $binary of architectures:$stripped"
150 | fi
151 | STRIP_BINARY_RETVAL=1
152 | }
153 |
154 |
155 | if [[ "$CONFIGURATION" == "Debug" ]]; then
156 | install_framework "${BUILT_PRODUCTS_DIR}/Petral/Petral.framework"
157 | fi
158 | if [[ "$CONFIGURATION" == "Release" ]]; then
159 | install_framework "${BUILT_PRODUCTS_DIR}/Petral/Petral.framework"
160 | fi
161 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then
162 | wait
163 | fi
164 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-Petral_Example/Pods-Petral_Example-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
14 | FOUNDATION_EXPORT double Pods_Petral_ExampleVersionNumber;
15 | FOUNDATION_EXPORT const unsigned char Pods_Petral_ExampleVersionString[];
16 |
17 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-Petral_Example/Pods-Petral_Example.debug.xcconfig:
--------------------------------------------------------------------------------
1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Petral"
3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Petral/Petral.framework/Headers"
5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
6 | OTHER_LDFLAGS = $(inherited) -framework "Petral"
7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
8 | PODS_BUILD_DIR = ${BUILD_DIR}
9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
11 | PODS_ROOT = ${SRCROOT}/Pods
12 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-Petral_Example/Pods-Petral_Example.modulemap:
--------------------------------------------------------------------------------
1 | framework module Pods_Petral_Example {
2 | umbrella header "Pods-Petral_Example-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-Petral_Example/Pods-Petral_Example.release.xcconfig:
--------------------------------------------------------------------------------
1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Petral"
3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Petral/Petral.framework/Headers"
5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
6 | OTHER_LDFLAGS = $(inherited) -framework "Petral"
7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
8 | PODS_BUILD_DIR = ${BUILD_DIR}
9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
11 | PODS_ROOT = ${SRCROOT}/Pods
12 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-Petral_Tests/Pods-Petral_Tests-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-Petral_Tests/Pods-Petral_Tests-acknowledgements.markdown:
--------------------------------------------------------------------------------
1 | # Acknowledgements
2 | This application makes use of the following third party libraries:
3 | Generated by CocoaPods - https://cocoapods.org
4 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-Petral_Tests/Pods-Petral_Tests-acknowledgements.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreferenceSpecifiers
6 |
7 |
8 | FooterText
9 | This application makes use of the following third party libraries:
10 | Title
11 | Acknowledgements
12 | Type
13 | PSGroupSpecifier
14 |
15 |
16 | FooterText
17 | Generated by CocoaPods - https://cocoapods.org
18 | Title
19 |
20 | Type
21 | PSGroupSpecifier
22 |
23 |
24 | StringsTable
25 | Acknowledgements
26 | Title
27 | Acknowledgements
28 |
29 |
30 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-Petral_Tests/Pods-Petral_Tests-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Pods_Petral_Tests : NSObject
3 | @end
4 | @implementation PodsDummy_Pods_Petral_Tests
5 | @end
6 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-Petral_Tests/Pods-Petral_Tests-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
14 | FOUNDATION_EXPORT double Pods_Petral_TestsVersionNumber;
15 | FOUNDATION_EXPORT const unsigned char Pods_Petral_TestsVersionString[];
16 |
17 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-Petral_Tests/Pods-Petral_Tests.debug.xcconfig:
--------------------------------------------------------------------------------
1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Petral"
2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
3 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Petral/Petral.framework/Headers"
4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
5 | OTHER_LDFLAGS = $(inherited) -framework "Petral"
6 | PODS_BUILD_DIR = ${BUILD_DIR}
7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
8 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
9 | PODS_ROOT = ${SRCROOT}/Pods
10 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-Petral_Tests/Pods-Petral_Tests.modulemap:
--------------------------------------------------------------------------------
1 | framework module Pods_Petral_Tests {
2 | umbrella header "Pods-Petral_Tests-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-Petral_Tests/Pods-Petral_Tests.release.xcconfig:
--------------------------------------------------------------------------------
1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Petral"
2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
3 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Petral/Petral.framework/Headers"
4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
5 | OTHER_LDFLAGS = $(inherited) -framework "Petral"
6 | PODS_BUILD_DIR = ${BUILD_DIR}
7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
8 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
9 | PODS_ROOT = ${SRCROOT}/Pods
10 |
--------------------------------------------------------------------------------
/Example/Tests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Example/Tests/Tests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | import Petral
3 |
4 | class Tests: XCTestCase {
5 |
6 | override func setUp() {
7 | super.setUp()
8 | // Put setup code here. This method is called before the invocation of each test method in the class.
9 | }
10 |
11 | override func tearDown() {
12 | // Put teardown code here. This method is called after the invocation of each test method in the class.
13 | super.tearDown()
14 | }
15 |
16 | func testExample() {
17 | // This is an example of a functional test case.
18 | XCTAssert(true, "Pass")
19 | }
20 |
21 | func testPerformanceExample() {
22 | // This is an example of a performance test case.
23 | self.measure() {
24 | // Put the code you want to measure the time of here.
25 | }
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/Example/build/XCBuildData/BuildDescriptionCacheIndex-3b2af7ba66cb1d16b8c8cc1f9f59b4e4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HuangZhiBin/Petral-UI/6518901c1dcc6968efd5fc78a43fe8fd6a9b4935/Example/build/XCBuildData/BuildDescriptionCacheIndex-3b2af7ba66cb1d16b8c8cc1f9f59b4e4
--------------------------------------------------------------------------------
/Example/build/XCBuildData/f57f7d0483b85d8aaca50d9f5640f017-desc.xcbuild:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HuangZhiBin/Petral-UI/6518901c1dcc6968efd5fc78a43fe8fd6a9b4935/Example/build/XCBuildData/f57f7d0483b85d8aaca50d9f5640f017-desc.xcbuild
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2019 ikrboy@163.com
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/Petral-UI.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # Be sure to run `pod lib lint Petral.podspec' to ensure this is a
3 | # valid spec before submitting.
4 | #
5 | # Any lines starting with a # are optional, but their use is encouraged
6 | # To learn more about a Podspec see https://guides.cocoapods.org/syntax/podspec.html
7 | #
8 |
9 | Pod::Spec.new do |s|
10 | s.name = 'Petral-UI'
11 | s.version = '2.1.0'
12 | s.summary = '以Swift实现的 UI布局框架,以最少的代码,实现UI的搭建、属性设置以及布局控制'
13 |
14 | # This description is used to generate tags and improve search results.
15 | # * Think: What does it do? Why did you write it? What is the focus?
16 | # * Try to keep it short, snappy and to the point.
17 | # * Write the description between the DESC delimiters below.
18 | # * Finally, don't worry about the indent, CocoaPods strips it!
19 |
20 | s.description = <<-DESC
21 | Petral-UI是一个以Swift实现的 UI布局框架,以最少的代码,实现UI的搭建、属性设置以及布局控制。
22 | DESC
23 |
24 | s.homepage = 'https://github.com/HuangZhiBin/Petral-UI'
25 | # s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2'
26 | s.license = { :type => 'MIT', :file => 'LICENSE' }
27 | s.author = { 'ikrboy@163.com' => 'BinHuang' }
28 | s.source = { :git => 'https://github.com/HuangZhiBin/Petral-UI.git', :tag => s.version }
29 | # s.social_media_url = 'https://twitter.com/'
30 |
31 | s.ios.deployment_target = '8.0'
32 | s.swift_version = '4.0'
33 |
34 | s.source_files = 'Petral/Classes/**/*'
35 |
36 | # s.resource_bundles = {
37 | # 'Petral' => ['Petral/Assets/*.png']
38 | # }
39 |
40 | # s.public_header_files = 'Pod/Classes/**/*.h'
41 | # s.frameworks = 'UIKit', 'MapKit'
42 | # s.dependency 'AFNetworking', '~> 2.3'
43 | end
44 |
--------------------------------------------------------------------------------
/Petral/Assets/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HuangZhiBin/Petral-UI/6518901c1dcc6968efd5fc78a43fe8fd6a9b4935/Petral/Assets/.gitkeep
--------------------------------------------------------------------------------
/Petral/Classes/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HuangZhiBin/Petral-UI/6518901c1dcc6968efd5fc78a43fe8fd6a9b4935/Petral/Classes/.gitkeep
--------------------------------------------------------------------------------
/Petral/Classes/PetralConfig.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PetralConfig.swift
3 | // Petral_Example
4 | //
5 | // Created by huangzhibin on 2019/8/6.
6 | // Copyright © 2019 CocoaPods. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public class PetralConfig: NSObject {
12 |
13 | public static let shared = PetralConfig();
14 |
15 | public var reloadUrl: String?;
16 |
17 | override init() {
18 | super.init();
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/Petral/Classes/PetralFlexView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PetralFlexView.swift
3 | // Petral_Example
4 | //
5 | // Created by huangzhibin on 2019/7/17.
6 | // Copyright © 2019 CocoaPods. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | enum PetralFlexDirectionType{
12 | case row
13 | case column
14 | case wrap
15 | }
16 |
17 | let PETRAL_FLEX_VIEW_NAME = "flexview";
18 |
19 | let PETRAL_ATTRIBUTE_ITEM_COUNT = "p-item-count";
20 | let PETRAL_ATTRIBUTE_DIRECTION = "p-direction";
21 | let PETRAL_ATTRIBUTE_PADDING = "p-padding";
22 | let PETRAL_ATTRIBUTE_ITEM_SPACE_X = "p-item-space-x";
23 | let PETRAL_ATTRIBUTE_ITEM_SPACE_Y = "p-item-space-y";
24 |
25 | let PETRAL_ATTRIBUTE_TEMPLATE = "template";
26 |
27 | public typealias PetralFlexViewItemCountAction = () -> Int;
28 | public typealias PetralFlexViewItemWidthAction = (_ index: Int) -> CGFloat;
29 | public typealias PetralFlexViewItemHeightAction = (_ index: Int) -> CGFloat;
30 | public typealias PetralFlexViewItemDisplayAction = (_ templateView : PetralFlexTemplateView, _ index: Int) -> Void;
31 | public typealias PetralFlexViewItemClickAction = (_ templateView : PetralFlexTemplateView, _ index: Int) -> Void;
32 |
33 | class PetralTapGestureRecognizer : UITapGestureRecognizer{
34 | var itemIndex: Int = -1;
35 | init(target: Any?, action: Selector?, itemIndex: Int) {
36 | super.init(target: target, action: action);
37 | self.itemIndex = itemIndex;
38 | }
39 | }
40 |
41 | public class PetralFlexView: UIView {
42 |
43 | public override init(frame: CGRect) {
44 | super.init(frame: frame);
45 | }
46 |
47 | required init?(coder aDecoder: NSCoder) {
48 | super.init(coder: aDecoder);
49 | }
50 |
51 | var elementCount : Int = 0;
52 |
53 | var direction: PetralFlexDirectionType! = .row;
54 | var padding: UIEdgeInsets! = UIEdgeInsets.init(top: 0, left: 0, bottom: 0, right: 0);
55 | var itemSpaceX: CGFloat = 0;
56 | var itemSpaceY: CGFloat = 0;
57 |
58 | // var templateView: PetralFlexTemplateView!;
59 | var templateView: PetralFlexTemplateView!{
60 | didSet{
61 | self.reloadData();
62 | }
63 | }
64 |
65 | public var itemCountAction: PetralFlexViewItemCountAction? {
66 | didSet{
67 | self.reloadData();
68 | }
69 | }
70 |
71 | public var itemWidthAction: PetralFlexViewItemWidthAction? {
72 | didSet{
73 | self.refreshRectForItems();
74 | }
75 | }
76 |
77 | public var itemHeightAction: PetralFlexViewItemHeightAction? {
78 | didSet{
79 | self.refreshRectForItems();
80 | }
81 | }
82 |
83 | public var itemDisplayAction: PetralFlexViewItemDisplayAction? {
84 | didSet{
85 | for (index,item) in self.items.enumerated() {
86 | self.itemDisplayAction!(item, index);
87 | }
88 | }
89 | }
90 |
91 | public var itemClickAction: PetralFlexViewItemClickAction? {
92 | didSet{
93 | for (index,item) in self.items.enumerated() {
94 | item.removeGestureRecognizer(PetralTapGestureRecognizer.init(target: self, action: #selector(self.clickActionForIndex(recognizer:)),itemIndex: index));
95 | item.addGestureRecognizer(PetralTapGestureRecognizer.init(target: self, action: #selector(self.clickActionForIndex(recognizer:)),itemIndex: index));
96 | }
97 | }
98 | }
99 |
100 | var items: [PetralFlexTemplateView] {
101 | get{
102 | var templates: [PetralFlexTemplateView] = [];
103 | if self.subviews.count > 0 {
104 | for templateView in self.subviews {
105 | templates.append(templateView as! PetralFlexTemplateView);
106 | }
107 | }
108 | return templates;
109 | }
110 | }
111 |
112 | @discardableResult
113 | public func resize() -> CGSize {
114 | if self.items.count > 0 {
115 | let lastItem = self.items.last;
116 | self.frame.size.width = (lastItem?.frame.size.width)! + (lastItem?.frame.origin.x)! + self.padding.right;
117 | self.frame.size.height = (lastItem?.frame.size.height)! + (lastItem?.frame.origin.y)! + self.padding.bottom;
118 | }
119 | return self.frame.size;
120 | }
121 |
122 | public func reloadData() {
123 | if self.itemCountAction != nil {
124 | self.elementCount = self.itemCountAction!();
125 | }
126 |
127 | self.reinitItems();
128 | self.refreshRectForItems();
129 |
130 | for (index,item) in self.items.enumerated() {
131 | if self.itemDisplayAction != nil {
132 | self.itemDisplayAction!(item, index);
133 | }
134 |
135 | if self.itemClickAction != nil {
136 | item.removeGestureRecognizer(PetralTapGestureRecognizer.init(target: self, action: #selector(self.clickActionForIndex(recognizer:)),itemIndex: index));
137 | item.addGestureRecognizer(PetralTapGestureRecognizer.init(target: self, action: #selector(self.clickActionForIndex(recognizer:)),itemIndex: index));
138 | }
139 | }
140 | }
141 |
142 | func reinitItems(){
143 | for item in self.items {
144 | item.removeFromSuperview();
145 | }
146 |
147 | if self.elementCount > 0 {
148 | for _ in 0 ... self.elementCount - 1 {
149 | let copyView : PetralFlexTemplateView = PetralUtil.duplicateView(view: self.templateView) as! PetralFlexTemplateView;
150 | PetralUtil.duplicateRestraints(sourceView: templateView, toView: copyView);
151 | self.saveSubTemplates(templateView: self.templateView, copiedView: copyView);
152 | self.addSubview(copyView);
153 | copyView.flexView = self;
154 | }
155 | self.refreshRectForItems();
156 | }
157 | }
158 |
159 | func saveSubTemplates(templateView: PetralFlexTemplateView, copiedView: PetralFlexTemplateView) {
160 | for (index,subview) in templateView.subviews.enumerated() {
161 | if subview.isKind(of: PetralFlexView.classForCoder()){
162 | let copiedFlexView : PetralFlexView = copiedView.subviews[index] as! PetralFlexView;
163 | copiedFlexView.elementCount = (subview as? PetralFlexView)!.elementCount;
164 | copiedFlexView.direction = (subview as? PetralFlexView)?.direction;
165 | copiedFlexView.padding = (subview as? PetralFlexView)?.padding;
166 | copiedFlexView.itemSpaceX = (subview as? PetralFlexView)!.itemSpaceX;
167 | copiedFlexView.itemSpaceY = (subview as? PetralFlexView)!.itemSpaceY;
168 | copiedFlexView.templateView = (subview as? PetralFlexView)?.templateView;
169 | }
170 | }
171 | }
172 |
173 | @objc func clickActionForIndex(recognizer: PetralTapGestureRecognizer) {
174 | self.itemClickAction!(recognizer.view as! PetralFlexTemplateView, recognizer.itemIndex);
175 | }
176 |
177 | func refreshRectForItems() {
178 | for (index,view) in self.items.enumerated() {
179 | var needUpdate = false;
180 | if self.itemWidthAction != nil {
181 | needUpdate = true;
182 | view.frame.size.width = self.itemWidthAction!(index);
183 | }
184 | if self.itemHeightAction != nil {
185 | needUpdate = true;
186 | view.frame.size.height = self.itemHeightAction!(index);
187 | }
188 | if needUpdate {
189 | view.petralRestraint.updateDependeds();
190 | }
191 |
192 | if index == 0 {
193 | view.frame.origin.x = self.padding.left;
194 | view.frame.origin.y = self.padding.top;
195 | continue;
196 | }
197 | let prevView = self.items[index - 1];
198 | if self.direction == .row {
199 | view.frame.origin.x = prevView.frame.origin.x + prevView.frame.size.width + self.itemSpaceX;
200 | view.frame.origin.y = prevView.frame.origin.y;
201 | }
202 | else if self.direction == .column {
203 | view.frame.origin.x = prevView.frame.origin.x;
204 | view.frame.origin.y = prevView.frame.origin.y + prevView.frame.size.height + self.itemSpaceY;
205 | }
206 | else if self.direction == .wrap {
207 | let realContainerWidth = self.frame.size.width - padding.left - padding.right;
208 | var x = prevView.frame.origin.x + prevView.frame.size.width + self.itemSpaceX;
209 |
210 | if x + view.frame.size.width > realContainerWidth {
211 | x = self.padding.left;
212 | let y = prevView.frame.origin.y + prevView.frame.size.height + self.itemSpaceY;
213 | view.frame.origin = CGPoint.init(x: x, y: y);
214 | }
215 | else {
216 | view.frame.origin = CGPoint.init(x: x, y: prevView.frame.origin.y);
217 | }
218 | }
219 | }
220 | }
221 |
222 | func viewForIndex(index: Int) -> PetralFlexTemplateView {
223 | return self.subviews[index] as! PetralFlexTemplateView;
224 | }
225 |
226 | /*
227 | func positionForItem(view: PetralFlexTemplateView, index: Int) -> CGPoint {
228 | if self.direction == .row {
229 | return CGPoint.init(x: (view.frame.size.width + self.itemSpaceX) * CGFloat(index), y: 0);
230 | }
231 | else if self.direction == .column {
232 | return CGPoint.init(x: 0, y: (view.frame.size.height + self.itemSpaceY) * CGFloat(index));
233 | }
234 | else if self.direction == .wrap {
235 | let realContainerWidth = self.containerView.frame.size.width;
236 | let itemsCountEachLine : Int = Int((realContainerWidth + self.itemSpaceX) / (view.frame.size.width + self.itemSpaceX));
237 | if itemsCountEachLine == 0 {
238 | return CGPoint.init(x: 0, y: 0);
239 | }
240 | let lineIndex : Int = index / itemsCountEachLine;
241 | let columnIndex : Int = index % itemsCountEachLine;
242 | return CGPoint.init(x: (view.frame.size.width + self.itemSpaceX) * CGFloat(columnIndex), y: (view.frame.size.height + self.itemSpaceY) * CGFloat(lineIndex));
243 | }
244 | return CGPoint.zero;
245 | }
246 | */
247 |
248 | func setXmlParam(attributeName: String, attributeValue: String) {
249 | switch attributeName {
250 | case PETRAL_ATTRIBUTE_ITEM_COUNT:
251 | self.elementCount = PetralParser.parseInt(attributeValue);
252 | break;
253 | case PETRAL_ATTRIBUTE_PADDING:
254 | self.padding = PetralParser.parseInset(attributeValue);
255 | break;
256 | case PETRAL_ATTRIBUTE_DIRECTION:
257 | self.direction = PetralParser.parseDirection(attributeValue);
258 | break;
259 | case PETRAL_ATTRIBUTE_ITEM_SPACE_X:
260 | self.itemSpaceX = PetralParser.parseFloat(attributeValue);
261 | break;
262 | case PETRAL_ATTRIBUTE_ITEM_SPACE_Y:
263 | self.itemSpaceY = PetralParser.parseFloat(attributeValue);
264 | break;
265 | default:
266 | break;
267 | }
268 | }
269 |
270 | }
271 |
272 | public class PetralFlexTemplateView: UIView {
273 |
274 | weak var flexView: PetralFlexView!;
275 |
276 | public override init(frame: CGRect) {
277 | super.init(frame: frame);
278 | // self.clipsToBounds = true;等价功能
279 | // self.layer.masksToBounds = false;
280 | }
281 |
282 | required init?(coder aDecoder: NSCoder) {
283 | super.init(coder: aDecoder);
284 | }
285 |
286 | }
287 |
--------------------------------------------------------------------------------
/Petral/Classes/PetralTableView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PetralTableView.swift
3 | // Petral_Example
4 | //
5 | // Created by huangzhibin on 2019/7/23.
6 | // Copyright © 2019 CocoaPods. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | let PETRAL_ELEMENT_HEADER = "header";
12 | let PETRAL_ELEMENT_FOOTER = "footer";
13 | let PETRAL_ELEMENT_CELL = "cell";
14 | let PETRAL_ELEMENT_SECTION_HEADER = "section-header";
15 | let PETRAL_ELEMENT_SECTION_FOOTER = "section-footer";
16 |
17 | let PETRAL_ATTRIBUTE_ROWS = "p-rows";
18 | let PETRAL_ATTRIBUTE_SECTIONS = "p-sections";
19 |
20 | public typealias PetralTableViewCellDisplayAction = (_ cell: UITableViewCell, _ indexPath: IndexPath) -> Void;
21 | public typealias PetralTableViewSectionHeaderDisplayAction = (_ headerView: UIView, _ section : Int) -> Void;
22 | public typealias PetralTableViewSectionFooterDisplayAction = (_ footerView: UIView, _ section : Int) -> Void;
23 | public typealias PetralTableViewCellRowCountAction = (_ section: Int) -> Int;
24 | public typealias PetralTableViewCellSectionCountAction = () -> Int;
25 | public typealias PetralTableViewCellClickAction = (_ indexPath: IndexPath) -> Void;
26 | public typealias PetralTableViewCellRowHeightAction = (_ indexPath: IndexPath) -> CGFloat;
27 | public typealias PetralTableViewSectionHeaderHeightAction = (_ section: Int) -> CGFloat;
28 | public typealias PetralTableViewSectionFooterHeightAction = (_ section: Int) -> CGFloat;
29 |
30 | private var identifierMitTemplate: [String: UIView] = [:];
31 |
32 | public class PetralTableView: UITableView {
33 |
34 | var CELL_IDENTIFIER = "";
35 |
36 | public var tableCellDisplayAction: PetralTableViewCellDisplayAction?;
37 | public var tableSectionHeaderDisplayAction: PetralTableViewSectionHeaderDisplayAction?;
38 | public var tableSectionFooterDisplayAction: PetralTableViewSectionFooterDisplayAction?;
39 | public var tableCellRowCountAction: PetralTableViewCellRowCountAction?;
40 | public var tableSectionCountAction: PetralTableViewCellSectionCountAction?;
41 | public var tableCellClickAction: PetralTableViewCellClickAction?;
42 | public var tableCellRowHeightAction: PetralTableViewCellRowHeightAction?;
43 | public var tableSectionHeightForHeaderAction: PetralTableViewSectionHeaderHeightAction?;
44 | public var tableSectionHeightForFooterAction: PetralTableViewSectionFooterHeightAction?;
45 |
46 | var cellHeight: CGFloat = 0;
47 | var sectionHeightHeader: CGFloat = CGFloat.leastNormalMagnitude;
48 | var sectionHeightFooter: CGFloat = CGFloat.leastNormalMagnitude;
49 |
50 | var cellView: UIView? {
51 | didSet{
52 | self.CELL_IDENTIFIER = "CELL_IDENTIFIER_" + String(self.hash);
53 | identifierMitTemplate[self.CELL_IDENTIFIER] = self.cellView;
54 | self.register(PetralTableViewCell.self, forCellReuseIdentifier: self.CELL_IDENTIFIER);
55 | self.delegate = self;
56 | self.dataSource = self;
57 | }
58 | }
59 |
60 | var sectionHeaderView: UIView?;
61 |
62 | var sectionFooterView: UIView?;
63 |
64 | override init(frame: CGRect, style: UITableViewStyle) {
65 | super.init(frame: frame, style: style);
66 |
67 | // let tableView = self;
68 |
69 | // if(tableView.responds(to: #selector(setter: UITableView.separatorInset))) {
70 | // tableView.separatorInset = UIEdgeInsets.zero;
71 | // }
72 | // if(tableView.responds(to: #selector(setter: UITableView.layoutMargins))) {
73 | // tableView.layoutMargins = UIEdgeInsets.zero;
74 | // }
75 | }
76 |
77 | required init?(coder aDecoder: NSCoder) {
78 | super.init(coder: aDecoder);
79 | }
80 |
81 | func setXmlParam(attributeName: String, attributeValue: String) {
82 | switch attributeName {
83 | case PETRAL_ATTRIBUTE_ROWS:
84 | self.tableCellRowCountAction = { (section: Int) in
85 | return PetralParser.parseInt(attributeValue);
86 | };
87 | break;
88 | case PETRAL_ATTRIBUTE_SECTIONS:
89 | self.tableSectionCountAction = {
90 | return PetralParser.parseInt(attributeValue);
91 | };
92 | break;
93 | default:
94 | break;
95 | }
96 | }
97 |
98 | deinit {
99 | print("tableview deinit");
100 | if identifierMitTemplate.keys.contains(self.CELL_IDENTIFIER) {
101 | identifierMitTemplate.removeValue(forKey: self.CELL_IDENTIFIER);
102 | }
103 | }
104 |
105 |
106 | }
107 |
108 | extension PetralTableView : UITableViewDelegate,UITableViewDataSource{
109 |
110 | public func numberOfSections(in tableView: UITableView) -> Int {
111 | if self.tableSectionCountAction != nil {
112 | return self.tableSectionCountAction!();
113 | }
114 | return 1;
115 | }
116 |
117 | public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
118 | if self.tableCellRowCountAction != nil {
119 | return self.tableCellRowCountAction!(section);
120 | }
121 | return 0;
122 | }
123 |
124 | public func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
125 | if self.sectionHeaderView == nil {
126 | return nil;
127 | }
128 | let headerView = PetralUtil.duplicateView(view: self.sectionHeaderView!);
129 | PetralUtil.duplicateRestraints(sourceView: self.sectionHeaderView!, toView: headerView);
130 |
131 | if self.tableSectionHeightForHeaderAction != nil {
132 | headerView.frame.size.height = self.tableSectionHeightForHeaderAction!(section);
133 | headerView.petralRestraint.updateDependeds();
134 | }
135 |
136 | if self.tableSectionHeaderDisplayAction != nil {
137 | self.tableSectionHeaderDisplayAction!(headerView, section);
138 | }
139 |
140 | return headerView;
141 | }
142 |
143 | public func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
144 | if self.sectionFooterView == nil {
145 | return nil;
146 | }
147 |
148 | let footerView = PetralUtil.duplicateView(view: self.sectionFooterView!);
149 | PetralUtil.duplicateRestraints(sourceView: self.sectionFooterView!, toView: footerView);
150 |
151 | if self.tableSectionHeightForFooterAction != nil {
152 | footerView.frame.size.height = self.tableSectionHeightForFooterAction!(section);
153 | footerView.petralRestraint.updateDependeds();
154 | }
155 |
156 | if self.tableSectionFooterDisplayAction != nil {
157 | self.tableSectionFooterDisplayAction!(footerView, section);
158 | }
159 |
160 | return footerView;
161 | }
162 |
163 | public func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
164 | if self.tableSectionHeightForHeaderAction != nil {
165 | return self.tableSectionHeightForHeaderAction!(section);
166 | }
167 |
168 | return self.sectionHeightHeader;
169 | }
170 |
171 | public func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
172 | if self.tableSectionHeightForFooterAction != nil {
173 | return self.tableSectionHeightForFooterAction!(section);
174 | }
175 | return self.sectionHeightFooter;
176 | }
177 |
178 | public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
179 | if self.tableCellRowHeightAction != nil {
180 | return self.tableCellRowHeightAction!(indexPath);
181 | }
182 | return self.cellHeight;
183 | }
184 |
185 | public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
186 | let cell = tableView.dequeueReusableCell(withIdentifier: CELL_IDENTIFIER, for: indexPath) as! PetralTableViewCell;
187 | cell.contentView.petralRestraint.updateDependeds();
188 | if self.tableCellDisplayAction != nil {
189 | self.tableCellDisplayAction!(cell, indexPath);
190 | }
191 | return cell;
192 | }
193 |
194 | public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
195 | tableView.deselectRow(at: indexPath, animated: false);
196 |
197 | if self.tableCellClickAction != nil {
198 | self.tableCellClickAction!(indexPath);
199 | }
200 | }
201 |
202 |
203 | }
204 |
205 | class PetralTableViewCell: UITableViewCell {
206 |
207 | // static let CELL_WIDTH : CGFloat = UIScreen.main.bounds.width;
208 | // static let CELL_HEIGHT : CGFloat = 0;
209 |
210 | var viewIdTagDict : [String: Int]! = [:];
211 | var cellInnerView: UIView!;
212 |
213 | override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
214 | super.init(style: style, reuseIdentifier: reuseIdentifier);
215 | print("cell init -->" + self.reuseIdentifier!);
216 |
217 | let template : UIView = identifierMitTemplate[self.reuseIdentifier!]!;
218 |
219 | self.cellInnerView = PetralUtil.duplicateView(view: template);
220 | PetralUtil.duplicateRestraints(sourceView: template, toView: self.cellInnerView);
221 |
222 | let copyViewSubs = PetralUtil.getSubViews(view: self.cellInnerView);
223 | for (index,subview) in PetralUtil.getSubViews(view: template).enumerated() {
224 | if subview.isKind(of: PetralFlexView.classForCoder()) {
225 | self.saveSubTemplates(templateView: (subview as! PetralFlexView), copiedView: copyViewSubs[index] as! PetralFlexView);
226 | }
227 | }
228 |
229 | self.contentView.addSubview(self.cellInnerView);
230 |
231 | self.cellInnerView.petralRestraint.reset();
232 | self.cellInnerView.petralRestraint.leftIn().rightIn().topIn().bottomIn();
233 | }
234 |
235 | func saveSubTemplates(templateView: PetralFlexView, copiedView: PetralFlexView) {
236 | copiedView.elementCount = templateView.elementCount;
237 | copiedView.direction = templateView.direction;
238 | copiedView.padding = templateView.padding;
239 | copiedView.itemSpaceX = templateView.itemSpaceX;
240 | copiedView.itemSpaceY = templateView.itemSpaceY;
241 | copiedView.templateView = templateView.templateView;
242 | }
243 |
244 | required init?(coder aDecoder: NSCoder) {
245 | super.init(coder: aDecoder);
246 | }
247 | }
248 |
249 | class PetralTableHeaderView: UIView {
250 |
251 | }
252 |
253 | class PetralTableFooterView: UIView {
254 |
255 | }
256 |
257 | class PetralTableSectionHeaderView: UIView {
258 |
259 | }
260 |
261 | class PetralTableSectionFooterView: UIView {
262 |
263 | }
264 |
265 | class PetralTableCellView: UIView {
266 |
267 | }
268 |
269 |
--------------------------------------------------------------------------------
/Petral/Classes/PetralUtil.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PetralUtil.swift
3 | // Petral_Example
4 | //
5 | // Created by huangzhibin on 2019/7/30.
6 | // Copyright © 2019 CocoaPods. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class PetralUtil: NSObject {
12 |
13 | static func duplicateView(view: UIView) -> UIView {
14 | let data = NSKeyedArchiver.archivedData(withRootObject: view);
15 | let duplicateView = NSKeyedUnarchiver.unarchiveObject(with: data);
16 | self.copyLayer(sourceView: view, toView: (duplicateView as! UIView));
17 |
18 | //复制layer配置
19 | let subviews = self.getSubViews(view: (duplicateView as! UIView));
20 | let sourceSubviews = self.getSubViews(view: view);
21 | for (index,subview) in subviews.enumerated() {
22 | self.copyLayer(sourceView: sourceSubviews[index], toView: subview);
23 | }
24 |
25 | return duplicateView as! UIView;
26 | }
27 |
28 | static func copyLayer(sourceView: UIView, toView: UIView){
29 | toView.layer.masksToBounds = sourceView.layer.masksToBounds;
30 | toView.layer.cornerRadius = sourceView.layer.cornerRadius;
31 | toView.layer.borderColor = sourceView.layer.borderColor;
32 | toView.layer.borderWidth = sourceView.layer.borderWidth;
33 | toView.layer.shadowColor = sourceView.layer.shadowColor;
34 | toView.layer.shadowOffset = sourceView.layer.shadowOffset;
35 | toView.layer.shadowRadius = sourceView.layer.shadowRadius;
36 | toView.layer.shadowOpacity = sourceView.layer.shadowOpacity;
37 | }
38 |
39 | static func duplicateRestraints(sourceView: UIView, toView: UIView) {
40 | let subViews = getSubViews(view: sourceView);
41 | toView.petralRestraint.restraints = [];
42 | toView.petralRestraint.attachedView = toView;
43 | toView.petralRestraint.dependings = sourceView.petralRestraint.dependings;
44 | for subView in subViews {
45 | if subView.tag > 0 {
46 | let sameView : UIView = toView.viewWithTag(subView.tag)!;
47 | sameView.petralRestraint.restraints = subView.petralRestraint.restraints;
48 | sameView.petralRestraint.dependings = subView.petralRestraint.dependings;
49 | sameView.petralRestraint.attachedView = sameView;
50 | }
51 | }
52 | }
53 |
54 | static func getSubViews(view: UIView) -> [UIView] {
55 | var subViews : [UIView] = [];
56 | for subView in view.subviews {
57 | subViews.append(subView);
58 | if subView.subviews.count > 0 {
59 | let subSubViews = getSubViews(view: subView);
60 | for subSubView in subSubViews {
61 | subViews.append(subSubView);
62 | }
63 | }
64 | }
65 | return subViews;
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/Petral/Classes/UIView+Petral.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIView+Petral.swift
3 | // Petral
4 | //
5 | // Created by bin on 2019/6/9.
6 | // Copyright © 2019年 BinHuang. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | typealias PetralExcuteBlock = () -> Void;
12 | func PETRAL(_ block: PetralExcuteBlock){
13 | block();
14 | }
15 |
16 | var PETRAL_RESTRAINT = 1;
17 | var PETRAL_ATTRIBUTE = 2;
18 | var PETRAL_XML_RESOURCE = 3;
19 | var PETRAL_XML_LOADER = 4;
20 | var PETRAL_XML_VIEW_ID = 5;
21 |
22 | extension UIView {
23 |
24 | public var petralRestraint: PetralRestraint {
25 | get{
26 | let result = objc_getAssociatedObject(self, &PETRAL_RESTRAINT) as? PetralRestraint
27 | if result == nil {
28 | //print("==1==");
29 | let restraint = PetralRestraint.init(self);
30 | self.petralRestraint = restraint;
31 | return restraint;
32 | }
33 | else{
34 | //print("==2==");
35 | }
36 | return result!
37 | }
38 | set{
39 | objc_setAssociatedObject(self, &PETRAL_RESTRAINT, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN);
40 | }
41 | }
42 |
43 | var petralAttribute: PetralAttribute {
44 | get{
45 | let result = objc_getAssociatedObject(self, &PETRAL_ATTRIBUTE) as? PetralAttribute
46 | if result == nil {
47 | //print("==1==");
48 | var attribute : PetralAttribute;
49 | if(self.isKind(of: UIButton.self)){
50 | attribute = PetralAttributeUIButton.init(self);
51 | }
52 | else if(self.isKind(of: UIImageView.self)){
53 | attribute = PetralAttributeUIImageView.init(self);
54 | }
55 | else if(self.isKind(of: UILabel.self)){
56 | attribute = PetralAttributeUILabel.init(self);
57 | }
58 | else if(self.isKind(of: UITextField.self)){
59 | attribute = PetralAttributeUITextField.init(self);
60 | }
61 | else if(self.isKind(of: UITextView.self)){
62 | attribute = PetralAttributeUITextView.init(self);
63 | }
64 | //subclass should come first than superclass,e.g. UITableView->UIScrollView
65 | else if(self.isKind(of: UITableView.self)){
66 | attribute = PetralAttributeUITableView.init(self);
67 | }
68 | else if(self.isKind(of: UIScrollView.self)){
69 | attribute = PetralAttributeUIScrollView.init(self);
70 | }
71 | else{
72 | attribute = PetralAttribute.init(self);
73 | }
74 | self.petralAttribute = attribute;
75 | return attribute;
76 | }
77 | else{
78 | //print("==2==");
79 | }
80 | return result!
81 | }
82 | set{
83 | objc_setAssociatedObject(self, &PETRAL_ATTRIBUTE, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN);
84 | }
85 | }
86 |
87 | var petralXmlViewId: String? {
88 | get{
89 | let result = objc_getAssociatedObject(self, &PETRAL_XML_VIEW_ID) as? String;
90 | return result
91 | }
92 | set{
93 | objc_setAssociatedObject(self, &PETRAL_XML_VIEW_ID, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN);
94 | }
95 | }
96 |
97 | public var petralXmlResource: String? {
98 | get{
99 | let result = objc_getAssociatedObject(self, &PETRAL_XML_RESOURCE) as? String;
100 | return result
101 | }
102 | set{
103 | objc_setAssociatedObject(self, &PETRAL_XML_RESOURCE, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN);
104 | }
105 | }
106 |
107 | var petralXmlLoader: PetralLoader? {
108 | get{
109 | let result = objc_getAssociatedObject(self, &PETRAL_XML_LOADER) as? PetralLoader;
110 | return result
111 | }
112 | set{
113 | objc_setAssociatedObject(self, &PETRAL_XML_LOADER, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN);
114 | }
115 | }
116 |
117 | @discardableResult
118 | @objc public func petralLoadXmlViews(xmlPath: String, properties: [String: String]? = nil) -> PetralViewLoader {
119 | for subview in self.subviews{
120 | subview.removeFromSuperview();
121 | }
122 | self.petralXmlResource = xmlPath;
123 | self.petralXmlLoader = PetralLoader.init(xmlFileName: self.petralXmlResource!, properties: properties);
124 | self.petralXmlLoader!.injectViews(toView: self);
125 | return PetralViewLoader.init(petralXmlLoader: self.petralXmlLoader);
126 | }
127 |
128 | // @objc public func petralViewById(id: String) -> UIView? {
129 | // return self.petralXmlLoader?.findViewById(id: id);
130 | // }
131 | //
132 | // @objc public func petralViewById(id: String, template: UIView) -> UIView? {
133 | // return self.petralXmlLoader?.findViewById(id: id, template: template);
134 | // }
135 |
136 | @objc public func petralize() -> PetralAttribute {
137 | return self.petralAttribute;
138 | }
139 |
140 | }
141 |
142 | public class PetralViewLoader: NSObject {
143 |
144 | weak var petralXmlLoader: PetralLoader?;
145 |
146 | init(petralXmlLoader: PetralLoader?) {
147 | super.init();
148 | self.petralXmlLoader = petralXmlLoader;
149 | }
150 |
151 | public func petralViewById(id: String) -> UIView? {
152 | return self.petralXmlLoader?.findViewById(id: id);
153 | }
154 |
155 | public func petralViewById(id: String, inView: UIView) -> UIView? {
156 | return self.petralXmlLoader?.findViewById(id: id, template: inView);
157 | }
158 |
159 | }
160 |
161 |
162 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | **Petral-UI**基于 Swift 实现的 UI 框架,功能包括:
4 |
5 | - 1.UI 控件方法的连续调用
6 | - 2.自动布局
7 | - 3.解析 XML 布局(重点推荐)
8 |
9 | ## 功能演示
10 |
11 |
12 |
13 |
14 | ## 接入条件
15 |
16 | ```
17 | swift.version >= 4.0
18 | ```
19 |
20 | ## 接入方式
21 |
22 | ```Cocoapods
23 | pod 'Petral-UI'
24 | ```
25 |
26 | Petral-UI 主要是下面两个部分:
27 |
28 | ## 1.UI 控件方法的连续调用
29 |
30 | 连续设置 UIView 的属性,例如
31 |
32 | ```swift
33 | let nameLabel = UILabel.init();
34 | nameLabel.petralize()
35 | .frame(x: 0, y: 0, width: 80, height: 20)
36 | .text("姓名")
37 | .font(size: 14, bold: true)
38 | .textColor(UIColor.init(hexString: "#1f1f1f"));
39 | ```
40 |
41 | 通过直接调用.为前缀的方法,直接连续设置 View 的 UI 属性,与调用系统方法的 API 类似。可实现对 View 的连续设置,减少代码。
42 | 现有的 API 可以基本满足 UI 设置,大家可以根据实际需要自行添加更多的 API 方法。
43 |
44 | ## 2.自动布局
45 |
46 | 通过最少的代码,实现类似 AutoLayout/Masory 自动布局的功能,但代码量远少于这两个框架。
47 |
48 | 自动布局的使用步骤:
49 |
50 | 1. View 初始化后,通过 addSubview()方法添加到当前页面。必须先执行 addSubview()方法,才能使用 Petral-UI 进行自动布局的设置。
51 |
52 | ```swift
53 | self.view.addSubview(nameLabel);
54 | ```
55 |
56 | 2.访问 View 的 petralRestraint 属性的方法设置布局。
57 |
58 | ```swift
59 | nameLabel.petralRestraint
60 | .topIn(offset: 10) // View的顶部与父View的距离为10
61 | .leftIn(offset: 20);// View的左边与父View的距离为20
62 | ```
63 |
64 | ---
65 |
66 | ### (1) 自动布局的API
67 |
68 | 请参考:自动布局的API
69 |
70 | ### (2) 布局的级联更新
71 |
72 | - **updateDependeds()**
73 |
74 | View b 的位置受到 View a 的制约,View c 的位置受到 View b 的制约,若 View a 的位置或者大小发生改变,要保持之前的制约条件(Restraint),需要手动调用 API 方法 a.petralRestraint.updateDependeds();进行更新,使 View b 和 View c 的位置和大小发生改变。不手动调用该方法,将不主动实现 UI 的级联更新。
75 |
76 | ```swift
77 | a.petralRestraint.updateDependeds();
78 | ```
79 |
80 | 
81 |
82 | 
83 |
84 | ### (3) 布局冲突的情况
85 |
86 | 以下的情形会发生布局冲突,运行时抛出 fatalError:
87 |
88 | - 同时设置 view 的 left、right 和 width 约束
89 | - 同时设置 view 的 top、bottom 和 height 约束
90 | - 同时设置 view 的 left、xCenter 约束
91 | - 同时设置 view 的 right、xCenter 约束
92 | - 同时设置 view 的 top、yCenter 约束
93 | - 同时设置 view 的 bottom、yCenter 约束
94 |
95 | 运行时发现 fatalError 的情形,请通过下面的方法解决冲突。
96 |
97 | ### (4) 解决布局冲突的办法
98 |
99 | 根据 fatalError 的说明,首先应了解冲突发生的具体规则,然后选择下面的其中一个方法解决冲突。
100 |
101 | - 1.修改已有的约束条件(即改动已有的代码,重新修改约束条件)
102 | - 2.**reset()** 重置布局
103 | - 3.**remove(type: PetralRestraintType)** 删除冲突的约束条件
104 |
105 | **PetralRestraintType**的类型:
106 |
107 | | 类型 | 说明 |
108 | | ------- | -------- |
109 | | left | 左约束 |
110 | | right | 右约束 |
111 | | bottom | 底约束 |
112 | | top | 顶约束 |
113 | | xCenter | 水平居中 |
114 | | yCenter | 垂直居中 |
115 | | width | 宽度约束 |
116 | | height | 高度约束 |
117 |
118 | ## 3.解析 XML 布局
119 |
120 | 通过新建 XML 的布局文件,实现 UI 控件的创建、属性设置、自动布局,实现 UI 层级的结构化,提高编辑及修改 UI 的效率。
121 |
122 | ### (1) 新建 XML 布局文件
123 |
124 | ```XML
125 |
126 |
127 |
138 |
139 | ```
140 |
141 | #### 1.XML 布局文件的结构
142 |
143 | XML 布局文件,即 iOS 代码在运行时动态地解析项目中指定的 XML 文件,实现 UI 的搭建与设置。
144 |
145 | #### 2.必须遵循的原则
146 |
147 | XML 布局代码的编写有一定的规范:
148 |
149 | - 有且只有一个**views**根节点
150 | - 指定 xsi(只需要复制上面的 xsi 配置,不作任何改动。xsd 文件提供了 XML 代码提示和校验的功能。)
151 | - 任意子节点的id属性必须唯一
152 |
153 | 综上所述,XML 布局需保持以下的格式:
154 |
155 | ```XML
156 |
157 |
158 |
159 |
160 | ```
161 |
162 | #### 3.XML 代码提示
163 |
164 | - 推荐 Mac 软件:**Oxygen XML Editor**
165 |
166 | 
167 |
168 | - 属性值的类型可参考:PetralParser.swift
169 |
170 | ##### [1] 控件属性的值类型
171 |
172 | | 控件属性类型 | 值格式 1 | 值格式 2 | 值格式 3 | 值格式 4 | 值格式 5 |
173 | | --------------- | --------------------- | ------------ | ---------------- | ------------------ | -------- |
174 | | NSTextAlignment | left | right | center | justified | natural |
175 | | | 居左 | 居右 | 居中 | | |
176 | | UIFont | 12 | 12+ | | | |
177 | | | 系统 12 | 系统 12 加粗 | | | |
178 | | UIEdgeInsets | 10,20.0,30,40 | 10,20 |10 | | |
179 | | | top,left,bottom,right |top/bottom,left/right |top,left,bottom,right | | |
180 | | CGSize | 10,20.4 | | | | |
181 | | | width,height | | | | |
182 | | CGPoint | 10,20.4 | | | | |
183 | | | x,y | | | | |
184 | | Bool | true | false | | | |
185 | | | 真 | 假 | | | |
186 | | CGRect | 0 | 100.0,200 | 10.0,20,100,200 | | |
187 | | | CGRect.zero | width,height | x,y,width,height | | |
188 | | UIColor | #d7d7d7 | d7d7d7 | rgb(100,200,231) | rgba(10,20,30,0.5) | red |
189 | | | HEX 值 | HEX 值 | RGB 值 | RGBA 值 | 颜色名 |
190 |
191 | ##### [2] 布局属性的值类型
192 |
193 | | 布局属性类型 | 值格式 1 | 值格式 2 | 值格式 3 | 值格式 4 |
194 | | ------------ | ----------------------- | ------------------ | ------------------------------------ | ---------------------- |
195 | | left | 0 | label1 | label1,100 | label1;20 |
196 | | | 左边与 superView 距离 0 | 左边与 label1 相同 | 左边与 label1 偏离 100 | 左边与 label1 距离 100 |
197 | | right | 0 | label1 | label1,100 | label1;20 |
198 | | | 右边与 superView 距离 0 | 右边与 label1 相同 | 右边与 label1 偏离 100 | 右边与 label1 距离 100 |
199 | | top | 0 | label1 | label1,100 | label1;20 |
200 | | | 顶部与 superView 距离 0 | 顶部与 label1 相同 | 顶部与 label1 偏离 100 | 顶部与 label1 距离 100 |
201 | | bottom | 0 | label1 | label1,100 | label1;20 |
202 | | | 底部与 superView 距离 0 | 底部与 label1 相同 | 底部与 label1 偏离 100 | 底部与 label1 距离 100 |
203 | | xCenter | 0 | label1 | label1,100 | |
204 | | | x 与 superView 居中 | x 与 label1 居中 | x 与 label1 居中并偏离 100 | |
205 | | yCenter | 0 | label1 | label1,100 | |
206 | | | y 与 superView 居中 | y 与 label1 居中 | y 与 label1 居中并偏离 100 | |
207 | | center | 0 | label1 | label1,20,30 | |
208 | | | 与 superView 居中 | 与 label1 居中 | 与 label1 居中,x 偏离 20,y 偏离 30 | |
209 | | width | 0 | label1 | label1,100 |100% |
210 | | | 宽度为 0 | 宽度与 label1 相同 | 宽度与 label1 一致并偏离 100 |占据superView宽度的100% |
211 | | height | 0 | label1 | label1,100 |100% |
212 | | | 高度为 0 | 高度与 label1 相同 | 高度与 label1 一致并偏离 100 |占据superView高度的100% |
213 |
214 | #### 4.控件的设置
215 |
216 | XML 布局支持大部分可静态配置的 UI 控件,例如:UIView、UIButton、UIImageView 等。其中 UIView 可缩写成全部小写的 view,具体类型如下:
217 |
218 | | 类型 | 缩写 |
219 | | ------------------ | ---------------- |
220 | | UIView | view |
221 | | UIButton | button |
222 | | UIImageView | imageview |
223 | | UILabel | label |
224 | | UIScrollView | scrollview |
225 | | UITableView | tableview |
226 | | UITextField | textfield |
227 | | UITextView | textview |
228 | | UICollectionView | collectionview |
229 | | UIDatePicker | datepicker |
230 | | UIPickerView | pickerview |
231 | | UIProgressView | progressview |
232 | | UISearchBar | searchbar |
233 | | UISegmentedControl | segmentedcontrol |
234 | | UISlider | slider |
235 | | UIStepper | stepper |
236 | | UISwitch | switch |
237 | | UIWebView | webview |
238 |
239 | 除了上面的控件之外,还支持自定义控件,控件名称为对应的 class 类型,例如 RedImageView 是一个继承 UIImageView 的自定义类:
240 |
241 | ```XML
242 |
243 |
244 |
248 |
249 | ```
250 |
251 | RedImageView 类可通用父类的属性,例如 image 属性
252 |
253 | #### 5.控件的互相嵌套
254 |
255 | 全面支持系统和自定义控件之间的互相嵌套
256 |
257 | ```XML
258 |
259 |
260 |
267 |
271 |
272 |
273 | ```
274 |
275 | ### (2) iOS 引用 XML 布局
276 |
277 | #### 1.XML 控件的加载
278 |
279 | ```Swift
280 | let loader = self.view.petralLoadXmlViews(xmlPath: "XmlViewController");
281 | ```
282 |
283 | 上面的代码表示 self.view 加载 XmlViewController.xml 的布局文件
284 |
285 | #### 2.通过 id 访问指定的控件
286 |
287 | ```Swift
288 | let userInfoView = loader.petralViewById(id: "userInfoView") as! UserInfoView;
289 | ```
290 |
291 | 上面的代码表示 userInfoView 是 XmlViewController 里 id 属性为"userInfoView"的控件。
292 |
293 | #### 3.代码注入XML
294 |
295 | ##### [1] 变量动态注入XML
296 |
297 | ```Swift
298 | let properties = [
299 | "showManyView": String(true),
300 | "time" : "10",
301 | "time2" : "3",
302 | "showRed" : String(true),
303 | "element": "风风雨雨我都不畏惧但求共醉"
304 | ];
305 | self.view.petralLoadXmlViews(xmlPath: "XmlViewController", properties: properties);
306 | ```
307 |
308 | ```xml
309 |
310 | ```
311 |
312 | 注入xml格式为{变量名},不支持表达式,但支持字符串拼接,例如:
313 |
314 | ```xml
315 |
316 | ```
317 |
318 | ##### [2] 外部变量注入自定义View的XML
319 |
320 | 通过data注入json字符串
321 |
322 | ```xml
323 |
324 | ```
325 |
326 | #### 4.XML的控件显示控制
327 |
328 | ##### **p-show**属性
329 |
330 | true表示加载该view,false则不加载
331 |
332 | ```xml
333 |
334 | ```
335 |
336 | #### 5.**flexview**视图
337 |
338 | 可以按照template重复生成item view的视图类。
339 |
340 | | 属性 | 说明 |
341 | | ------- | -------- |
342 | | **p-item-count** | 重复次数 |
343 | | **p-direction** | row(横向)、column(纵向)、wrap(自动换行) |
344 | | **p-padding** | manyview的内间距 |
345 | | **p-item-space-x** | 横向item间距 |
346 | | **p-item-space-y** | 纵向item间距 |
347 |
348 | ##### XML示例
349 |
350 | ```xml
351 |
352 |
353 |
354 |
355 |
356 |
357 | ```
358 |
359 | ##### 代码中访问flexview
360 |
361 | ```Swift
362 | let loader = self.view.petralLoadXmlViews(xmlPath: "ColumnFlexViewController");
363 | let flexview = loader.petralViewById(id: "flexview") as! PetralFlexView;
364 | ```
365 |
366 | ##### flexview的action方法
367 |
368 | | 属性 | 类型 | 说明 |
369 | | ------- | -------- | -------- |
370 | | **itemCountAction** | PetralFlexViewItemCountAction | item的数量 |
371 | | **itemWidthAction** | PetralFlexViewItemWidthAction | item的宽度 |
372 | | **itemHeightAction** | PetralFlexViewItemHeightAction | item的高度 |
373 | | **itemDisplayAction** | PetralFlexViewItemDisplayAction | item的UI展示 |
374 | | **itemClickAction** | PetralFlexViewItemClickAction | item的点击事件 |
375 |
376 | ### (3) XML的即时UI调试,不需重新编译app
377 |
378 | #### 1.引入调试工具Petral-UI-Updator
379 |
380 | ```Swift
381 | pod 'Petral-UI-Updator'
382 | ```
383 |
384 | #### 2.增加调试代码
385 |
386 | ```Swift
387 | #if DEBUG
388 | PetralHttpManager.sharedInstance().startServer("/Users/huang/MyProject/");//当前项目的绝对路径
389 | PetralConfig.shared.reloadUrl = PetralHttpManager.sharedInstance().url;
390 | #endif
391 | ```
392 |
393 | #### 3.ViewController实现resetUI()
394 |
395 | ViewController的resetUI方法提供重新渲染XML文件的功能,在此处添加刷新XML的UI。
396 |
397 | ```Swift
398 | @objc func resetUI() {
399 | self.view.petralLoadXmlViews(xmlPath: "MyXmlFileName");
400 | }
401 | ```
402 |
403 | 注:重复petralLoadXmlViews方法,重复的一次执行前,view的所有subview将会自动移除。
404 |
405 | #### 4.启动App
406 |
407 | 配置成功后,App出现悬浮的橙色球(配置不成功则不出现),点击即可执行当前的ViewController的resetUI方法。
408 |
409 | 仅支持**Xcode模拟器**调试。
410 |
411 | 
412 |
413 | ### 微信讨论群
414 |
415 | 二维码若过期,请加微信 ikrboy,请注明 petral 或者 github。
416 |
417 |
418 |
--------------------------------------------------------------------------------
/RestraintAPI.md:
--------------------------------------------------------------------------------
1 | ### 自动布局的 API
2 |
3 | #### 1.同级间 View 的约束
4 |
5 | View a 与 View b 是属于同一层级的两个 View,View b 的位置可以由 View a 决定。
6 |
7 | **注意:如果 a 与 b 不是属于同一层级,调用以下方法将报错。**
8 |
9 | ##### (1)to 方法
10 |
11 | - **leftTo()**
12 |
13 | View b 的左边与 View a 的距离是 n
14 |
15 | ```swift
16 | b.petralRestraint.leftTo(a, offset: n)
17 | ```
18 |
19 | 
20 |
21 | ---
22 |
23 | - **rightTo()**
24 |
25 | View b 的右边与 View a 的距离是 n
26 |
27 | ```swift
28 | b.petralRestraint.rightTo(a, offset: n)
29 | ```
30 |
31 | 
32 |
33 | ---
34 |
35 | - **topTo()**
36 |
37 | View b 的顶部与 View a 的距离是 n
38 |
39 | ```swift
40 | b.petralRestraint.topTo(a, offset: n)
41 | ```
42 |
43 | 
44 |
45 | ---
46 |
47 | - **bottomTo()**
48 |
49 | View b 的底部与 View a 的距离是 n
50 |
51 | ```swift
52 | b.petralRestraint.bottomTo(a, offset: n)
53 | ```
54 |
55 | 
56 |
57 | ##### (2)as 方法
58 |
59 | - **leftAs**
60 |
61 | View b 的左边与 View a 的左边的水平位置一致(可偏离 n)
62 |
63 | ```swift
64 | b.petralRestraint.leftAs(a, offset: n)
65 | ```
66 |
67 | 
68 |
69 | ---
70 |
71 | - **rightAs**
72 |
73 | View b 的右边与 View a 的右边的水平位置一致(可偏离 n)
74 |
75 | ```swift
76 | b.petralRestraint.rightAs(a, offset: n)
77 | ```
78 |
79 | 
80 |
81 | ---
82 |
83 | - **topAs**
84 |
85 | View b 的顶部与 View a 的顶部的水平位置一致(可偏离 n)
86 |
87 | ```swift
88 | b.petralRestraint.topAs(a, offset: n)
89 | ```
90 |
91 | 
92 |
93 | ---
94 |
95 | - **bottomAs**
96 |
97 | View b 的底部与 View a 的底部的水平位置一致(可偏离 n)
98 |
99 | ```swift
100 | b.petralRestraint.bottomAs(a, offset: n)
101 | ```
102 |
103 | 
104 |
105 | ---
106 |
107 | - **xCenterAs**
108 |
109 | ```swift
110 | b.petralRestraint.xCenterAs(a, offset: n)
111 | ```
112 |
113 | View b 的中间水平位置与 View a 的中间水平位置一致(可偏离 n)
114 |
115 | 
116 |
117 | ---
118 |
119 | - **yCenterAs**
120 |
121 | ```swift
122 | b.petralRestraint.yCenterAs(a, offset: n)
123 | ```
124 |
125 | View b 的中间垂直位置与 View a 的中间垂直位置一致(可偏离 n)
126 |
127 | 
128 |
129 | ---
130 |
131 | - **centerAs**
132 |
133 | ```swift
134 | b.petralRestraint.centerAs(a, xOffset: m, yOffset: n)
135 | ```
136 |
137 | View b 的中间点与 View a 的中间点位置一致(x 可偏离 m,y 可偏离 n)
138 |
139 | 
140 |
141 | #### 2.父子间 View 的约束
142 |
143 | View a 与 View b 的父 View,View b 的位置可以由 View a 决定。
144 |
145 | **注意:如果 a 不是 b 的父 View,调用以下方法将报错。**
146 |
147 | - **leftIn()**
148 |
149 | View b 的左边与父 View 的左边的距离为 n
150 |
151 | ```swift
152 | b.petralRestraint.leftIn(offset: n)
153 | ```
154 |
155 | 
156 |
157 | ---
158 |
159 | - **rightIn()**
160 |
161 | View b 的右边与父 View 的 y 右边的距离为 n
162 |
163 | ```swift
164 | b.petralRestraint.rightIn(offset: n)
165 | ```
166 |
167 | 
168 |
169 | ---
170 |
171 | - **topIn()**
172 |
173 | View b 的顶部与父 View 的顶部的距离为 n
174 |
175 | ```swift
176 | b.petralRestraint.topIn(offset: n)
177 | ```
178 |
179 | 
180 |
181 | ---
182 |
183 | - **bottomIn()**
184 |
185 | View b 的底部与父 View 的底部的距离为 n
186 |
187 | ```swift
188 | b.petralRestraint.bottomIn(offset: n)
189 | ```
190 |
191 | 
192 |
193 | ---
194 |
195 | - **xCenterIn()**
196 |
197 | View b 的水平位置位于父 View 的中间
198 |
199 | ```swift
200 | b.petralRestraint.xCenterIn()
201 | ```
202 |
203 | 
204 |
205 | ---
206 |
207 | - **yCenterIn()**
208 |
209 | View b 的垂直位置位于父 View 的中间
210 |
211 | ```swift
212 | b.petralRestraint.yCenterIn()
213 | ```
214 |
215 | 
216 |
217 | ---
218 |
219 | - **centerIn()**
220 |
221 | View b 的水平和垂直位置位于父 View 的中间
222 |
223 | ```swift
224 | b.petralRestraint.centerIn()
225 | ```
226 |
227 | 
228 |
229 | #### 3.指定 View 的固定宽高
230 |
231 | - **width()**
232 |
233 | View b 的固定宽度为 n
234 |
235 | ```swift
236 | b.petralRestraint.width(n)
237 | ```
238 |
239 | 
240 |
241 | ---
242 |
243 | - **height()**
244 |
245 | View b 的固定高度为 n
246 |
247 | ```swift
248 | b.petralRestraint.height(n)
249 | ```
250 |
251 | 
252 |
--------------------------------------------------------------------------------
/_Pods.xcodeproj:
--------------------------------------------------------------------------------
1 | Example/Pods/Pods.xcodeproj
--------------------------------------------------------------------------------