iOS: Custom top segmented control works as expected only when using debugger

懵懂的女人 提交于 2021-01-28 19:02:15

问题


I'm trying to create a custom top swipe menu that has a moving resizing orange bar that denotes which tab is selected. This is an extremely common design and I'm just doing this for practice as I am new to swift. You navigate by either swiping through the bottom collectionView or you can select a tab on the top menu. The top menu is also just a collectionView and is scrollable as well.

As you can see below (first gif), my problem is that when I try to go back to the first tab, whether by swiping the bottom or by selecting the top, the orange bar does not move to the left edge of the screen as expected. Everything else works fine. However, when I turn on the debugger and insert breakpoints (second gif), the orange bar behaves as expected again.

My guess is that this has something to do with the order in which the views are updated or something to do with the timing in which the scrolling animation ends. And it must be affecting the way I am calculating the position of the orange bar. Which is why when the debugger is on and the animation is slowed down, the orange bar behaves as expected. However, since I'm pretty inexperienced, I am not sure how to pinpoint the problem.

My implementation is overriding scrollViewDidScroll of the bottom content view, checking if the user has scrolled past more than half of the current page. If yes, then call topMenu.collectionView.setContentOffset to scroll the top menu to its proper position and also call animateHorizontalBar(index: Int) as shown below, which takes the index of the target page.

FYI: array just contains Strings for the title of each tab. I am using the size of the strings to calculate the size and position of the orange bar.

EDIT: Going to first index is fine when I disabled the feature when the horizontal bar will follow the selected tab when top menu is scrolled (second gif)

Any help will be greatly appreciated. Thanks!

func moveHorizontalBar(index: Int) {
    let horizontalBar = topMenu.horizontalBarView

    var sizeArray: [CGFloat] = []

    for item in array {
        sizeArray.append((ceil(40 + (item as NSString).size(withAttributes: [NSAttributedString.Key.font : UIFont.systemFont(ofSize: 25, weight: UIFont.Weight.medium)]).width)))
    }

    let width = self.view.frame.width
    let ratio = (topMenu.collectionView.contentSize.width - width) / (collectionView.contentSize.width - width)
    let offset = CGFloat(index) * width * ratio

    if index == 0 {
        horizontalBar.frame.origin.x = 0.0
        horizontalBar.frame.size.width = sizeArray[index]
    } else {
        var x: CGFloat = 0.0
        for i in 0..<index {
            x += sizeArray[i]
        }
        topMenu.currentOffset = x
        horizontalBar.frame.origin.x = x - offset
        horizontalBar.frame.size.width = sizeArray[index]
    }
}

func animateHorizontalBar(index: Int, animated: Bool) {
    if animated {
        self.topMenu.isSelectingNewTab = true
        UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
            self.moveHorizontalBar(index: index)
        })
    } else {
        moveHorizontalBar(index: index)
    }
}

来源:https://stackoverflow.com/questions/54357768/ios-custom-top-segmented-control-works-as-expected-only-when-using-debugger

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!