Before, the company made a page similar to zhihu small round table, but it felt that some parts were not good enough after writing, so I wrote it again with Swift, and welcome you to point out any shortcomings
All you need to do is pass in a title array
Override func viewDidLoad() {super.viewdidLoad () let zeVC = ZEPageViewController() zevc.titlesarr = [" dynamic "," problem "," discussion "] self.addChildViewController(zeVC) self.view.addSubview(zeVC.view) // Do any additional setup after loading the view, typically from a nib. }Copy the code
The principle of
The hierarchical view of the project looks like this
I’m going to create a scrollView at the bottom that’s the same size as viewController.View and then I’m going to add the tableviewController to it Finally will tableviewController. TableView. ContentInset top set to you want the height of the (headerView + menuView) It then proxies the tableviewController’s offset to the main controller, which is used to calculate the movement of the top headerView and menuView Then main controller scrollview proxy method is invoked to calculate tableviewcontroller. ContentOffset
The main difficulty is calculating the contentInset and contentOffset of the three TableViewControllers
code
Take a look at global properties first
/** Screen width height */ let kZEScreenWidth = uiscreen.mainScreen ().bounds.size.width let kZEScreenHight = Uiscreen.mainscreen ().bounds.size.height /** Height of header and menu */ let kZEHeaderHight:CGFloat = 135 let kZEMenuHight:CGFloat = 50 Let KSCrollHorizon Y = kZEMenuHight+kZEHeaderHight let kNavigationHight:CGFloat = 64 /** Offset method operatio enum */ enum HeaderMenuShowType :UInt {case up = 1 // fixed on navigation case butTom = 2 // fixed on navigation} /** button Let COLOR_BUTTON_DEFAULT = uicolor. init(red: 124/255.0, green: 129/255.0, blue: 138/255.0, alpha: 1) let COLOR_BUTTON_SELECT = uicolor. init(red: 0/255.0, green: 127/255.0, blue: 255/255.0, alpha: 1)Copy the code
ZEPageViewController
Create a scrollView
/ * * at the bottom of the create scrollView and tableViewController added to the above * / func layoutBackgroundScrollView () {self. BackgroundScrollView = UIScrollView(frame: self.view.frame) self.backgroundScrollView?.pagingEnabled = true self.backgroundScrollView?.bounces = false self.backgroundScrollView?.delegate = self let floatArrCount = CGFloat(titlesArr.count) self.backgroundScrollView?.contentSize = CGSizeMake(floatArrCount*kZEScreenWidth,self.view.frame.size.height-64) // ScrollY = -kscrollHorizony // The tableView's offset is the opposite of the offset symbol assigned to it for I in 0.. < titlesArr.count { let floatI = CGFloat(i) let tableViewVC = ZETableViewController(style: UITableViewStyle. Plain) / / top tableView outflow HeaderView and position of MenuView tableViewVC tableView. ContentInset = UIEdgeInsetsMake(kScrollHorizY, 0, 0, 0 ) tableViewVC.delegate = self tableViewVC.view.frame = CGRectMake(floatI * kZEScreenWidth,0, self.view.frame.size.width, Self. View. Frame. The size. Height - 64) tableViewVC. Tags = titlesArr [I] / / add tableViewVC into an array of convenient management TableViewArr. Append (tableViewVC) self. AddChildViewController (tableViewVC)} / / when needed to add to the view, avoid started takes too much resources backgroundScrollView?.addSubview(tableViewArr[0].view) self.view.addSubview(backgroundScrollView!) }Copy the code
Create HeaderView MenuView
/** Create HeaderView and MenuView */ func layoutHeaderMenuView() NSBundle.mainBundle().loadNibNamed("ZEHeaderView", owner: self, options: nil).first as! ZEHeaderView headerView.frame = CGRectMake(0, 64, kZEScreenWidth, kZEHeaderHight) self.view .addSubview(headerView) // MenuView menuView = ZEMenuView(frame:CGRectMake(0,CGRectGetMaxY(headerView.frame),kZEScreenWidth,kZEMenuHight)) menuView.delegate = self menuView.setUIWithArr(titlesArr) self.view .addSubview(self.menuView) }Copy the code
And then call those two methods in ViewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
self.automaticallyAdjustsScrollViewInsets = false
layoutBackgroundScrollView()
layoutHeaderMenuView()
}Copy the code
The control is now created
First, in ZETableViewController, set the offset at which the proxy method calls the tableView scroll
override func scrollViewDidScroll(scrollView: UIScrollView) {
self.delegate?.tableViewDidScrollPassY(scrollView.contentOffset.y)
}Copy the code
And then you do it in ZEPageControl
func tableViewDidScrollPassY(tableviewScrollY: CGFloat) {// Calculate each change of value let seleoffSetY = tableviewScrollY - scrollY // synchronize the value of scrollY scrollY = tableviewScrollY // Offset beyond Navigation if scrollY >= -kzemenuhight {headerMenuViewShowType(.up)}else if scrollY <= -kscrollHorizony {// The offset exceeds Navigation. HeaderMenuViewShowType (.butTom)}else{// The only thing left to follow is to change the y value of headerView to the offset headerView.frame.origin.y -= seleoffSetY menuView.frame.origin.y = CGRectGetMaxY(headerView.frame) } } /** Because frequent use the header and the menu is fixed, so declare a method used to lazy * / func headerMenuViewShowType (showType: headerMenuShowType) {switch showType {case .up: menuView.frame.origin.y = kNavigationHight headerView.frame.origin.y = kNavigationHight-kZEHeaderHight break case .buttom: headerView.frame.origin.y = kNavigationHight menuView.frame.origin.y = CGRectGetMaxY(headerView.frame) break } }Copy the code
// Do not look at the lack of code, the previous version of the calculation is super messy… There’s a lot less code after sorting it out…
And then how you slide left to right
func scrollViewDidScroll(scrollView: UIScrollView) {/ / determine whether there are changes in X, here only deals with horizontal sliding if scrollX = = scrollView. ContentOffset. {X return; } if scrollY >= -kzemenuhight {scrollY = -kzemenuhight} for if scrollY = -kzemenuhight} for tableViewVC in tableViewArr { tableViewVC.tableView.contentOffset = CGPointMake(0, ScrollY)} / / used to change the status of menuView let rate = (scrollView. ContentOffset. X/kZEScreenWidth). Self menuView. ScrollToRate (rate) / / Plus 0.7 means that when I slide to 30% I load the next tableView backgroundScrollView, right? AddSubview (tableViewArr [Int (rate + 0.7)]. View) / / record scrollX x = scrollView contentOffset. X}Copy the code
Swiping left and right also involves clicking on the MenuView, so select the agent back in the MenuView
Func menuViewSelectIndex (index: Int) {/ / 0.3 seconds animation in order to appear not too abrupt UIView. AnimateWithDuration (0.3) {self. BackgroundScrollView? .contentOffset = CGPointMake(kZEScreenWidth*CGFloat(index),-kNavigationHight) } }Copy the code
The detailed code of HeaderView and MenuView can be seen in DEM, because they are customized according to different needs. If you want to modify the project for your own use, just change it in the specific View. If you change the height, please change it in the global properties
rendering
github:Github.com/Lafree317/Z…
Please click a few stars if you like