Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

want to change TabBar line width #1109

Closed
takehilo opened this issue Jul 2, 2018 · 6 comments
Closed

want to change TabBar line width #1109

takehilo opened this issue Jul 2, 2018 · 6 comments

Comments

@takehilo
Copy link

takehilo commented Jul 2, 2018

I want to change the width of TabBar line.
I tried the following in the subclass of TabsController but it didn't work.
How can I do this?

override func layoutSubviews() {
    super.layoutSubviews()

    var frame = tabBar.line.frame
    frame.size.width = frame.size.width - 100
    tabBar.line.frame = frame
}
@OrkhanAlikhanov
Copy link
Contributor

Hey! I don't know why you want to change tabbar line width, but that does not work because the line width changed via animation:

line.animate(.duration(0.25),
.size(width: tabItem.bounds.width, height: lineHeight),

When you tap a tabItem or swipe the controller, above code is called. Motion works with CoreAnimation which animates view from old values to the new values on presentationLayer and sets the new values back to the actual layer/view when animation is done. So changing tabBar.line.width won't work because what's actually shown on the screen during animation is presentationlayer and after animation is done values of presentationLayer will be passed to the actual layer/view.

@OrkhanAlikhanov
Copy link
Contributor

OrkhanAlikhanov commented Jul 4, 2018

Actually there is hackish way to achieve what you want. Since the frame of the line is calculated from tabItem itself, we can tweak tabItem properties before animation is fired and set it back before layout cycle happens:

class MyTabsController: TabsController, TabBarDelegate {
  override func prepare() {
    super.prepare()
    tabBar.delegate = self
  }
  
  func tabBar(tabBar: TabBar, willSelect tabItem: TabItem) {
    let desiredWidth: CGFloat = 100
    let w = tabItem.frame.width
    let x = tabItem.center.x
   
    tabItem.frame.size.width = desiredWidth
    tabItem.frame.origin.x = x - desiredWidth / 2
    
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
      tabItem.frame.size.width = w
      tabItem.frame.origin.x = x - w / 2
    }
  }

@DanielDahan What do yo think maybe we should add something like:

func tabBar(tabBar: TabBar, lineWidthFor tabItem: TabItem) -> CGFloat

@daniel-jonathan
Copy link
Member

daniel-jonathan commented Jul 5, 2018

I think for the purposes of customization, we can offer an enum that is by default set to auto for line transition changes, and then add a custom enum that accepts a value for the desired width. @OrkhanAlikhanov what do you think?

@OrkhanAlikhanov
Copy link
Contributor

Well, that sounds reasonable. Can tabItems have different widths? If so, then lines can also have different widths based on tabItem's width. So, we need another case accepting closure for dynamic calculation.

enum TabBarLineWidthStyle {
  case auto
  case fixed(CGFloat)
  case custom((TabBarItem) -> CGFloat)
}

Usage:

tabBar.tabBarLineWidthStyle = .auto
tabBar.tabBarLineWidthStyle = .fixed(100)
tabBar.tabBarLineWidthStyle = .custom { tabItem in
    return tabItem.bounds.width - 20
  }

What do you think?

@daniel-jonathan
Copy link
Member

I think the 3 options would solve all cases nicely. Maybe we can rename the enum to TabBarItemsStyle. Not so sure I like the word Width in there. In either case, the naming could be changed on final review when we PR the branch into dev.

@daniel-jonathan
Copy link
Member

Please find the solution for this in Material 2.16.2. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

3 participants