Skip to content

Commit

Permalink
Removed need to pass selected index when initializing, readme updates
Browse files Browse the repository at this point in the history
  • Loading branch information
NicholasBellucci committed May 12, 2020
1 parent c5f7318 commit f9aa409
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 12 deletions.
3 changes: 1 addition & 2 deletions Example/Example/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@
import SwiftUI

struct ContentView: View {
@State var selectedIndex: Int = 0
@State var badgeValue1: String? = "1"

var body: some View {
StatefulTabView(selectedIndex: $selectedIndex) {
StatefulTabView {
Tab(title: "Tab 1", systemImageName: "circle.fill", badgeValue: $badgeValue1) {
NavigationView {
List {
Expand Down
28 changes: 25 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@ In Xcode 11 or greater, navigate to `File > Swift Packages > Add Package Depende
- [x] TabBarItem custom title and image
- [x] TabBarItem badge value
- [x] State retention from tab to tab
- [x] Pop to root functionality when clicking selected index
- [x] Pop to root functionality when selecting the already selected tab

## Usage

Setting up StatefulTabView is relatively simple and works similar to the native TabView. The main difference is that the content of the tabs is wrapped in a Tab struct. There is no limitation on how many tabs can be used. Once more than 5 are used, the Apple standard more tab will become available. Feel free to check out the example project for the exact usage.

### Basic
```Swift
StatefulTabView(selectedIndex: $selectedIndex) {
StatefulTabView {
Tab(title: "Tab 1", systemImageName: "circle.fill") {
NavigationView {
List {
Expand All @@ -55,14 +55,24 @@ StatefulTabView(selectedIndex: $selectedIndex) {
All appearance modifications can be made by using extensions for the StatefulTabView.

```Swift
StatefulTabView(selectedIndex: $selectedIndex) {
StatefulTabView {
...
}
.barTintColor(.red)
.barBackgroundColor(.yellow)
.barAppearanceConfiguration(.transparent)
```

### Selected Index

The selected index of the StatefulTabView can be set within the initializer. The passed value is a binding.

```Swift
StatefulTabView(selectedIndex: $selectedIndex) {
...
}
```

### BadgeValue

The TabBarItem badge value can be set in the initializer of a Tab. The passed value is a binding.
Expand All @@ -73,6 +83,18 @@ Tab(title: "Tab 1", systemImageName: "circle.fill", badgeValue: $badgeValue) {
}
```

### Single Tab

Due to the limitations of the current `@_functionBuilder` implementation in Swift, to build a StatefulTabView with one tab `BuilderType.individual` should be passed within the initializer.

```Swift
StatefulTabView(.individual) {
Tab(title: "Tab 1", systemImageName: "circle.fill") {
...
}
}
```

## License

StatefulTabView is, and always will be, MIT licensed. See [LICENSE](LICENSE) for details.
30 changes: 23 additions & 7 deletions Sources/StatefulTabView/StatefulTabView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,28 +19,44 @@ public struct StatefulTabView: View {
internal var backgroundColor: UIColor? = nil
internal var tabBarConfiguration: TabBarBackgroundConfiguration? = nil

@Binding internal var selectedIndex: Int
@State private var stateIndex: Int = 0
@Binding private var bindableIndex: Int

public init(selectedIndex: Binding<Int>, _ type: BuilderType, _ content: () -> Tab) {
_selectedIndex = selectedIndex
private var useBindableIndex: Bool = false

public init(selectedIndex: Binding<Int>? = nil, _ type: BuilderType, _ content: () -> Tab) {
if let selectedIndex = selectedIndex {
_bindableIndex = selectedIndex
useBindableIndex = true
} else {
_bindableIndex = .constant(0)
useBindableIndex = false
}

let tabController = UIHostingController(rootView: content().view)
tabController.tabBarItem = content().barItem
viewControllers.append(tabController)
}

public init(selectedIndex: Binding<Int>, @TabBuilder _ content: () -> [Tab]) {
_selectedIndex = selectedIndex
public init(selectedIndex: Binding<Int>? = nil, @TabBuilder _ content: () -> [Tab]) {
if let selectedIndex = selectedIndex {
_bindableIndex = selectedIndex
useBindableIndex = true
} else {
_bindableIndex = .constant(0)
useBindableIndex = false
}

configureViewControllers(with: content())
}

public var body: some View {
TabBarController(controllers: viewControllers,
tabBarItems: tabBarItems,
barTintColor: barTintColor,
backgroundColor: backgroundColor,
tabBarConfiguration: tabBarConfiguration,
selectedIndex: $selectedIndex)
selectedIndex: useBindableIndex ? $bindableIndex : $stateIndex)
.edgesIgnoringSafeArea(.all)
}
}
Expand Down

0 comments on commit f9aa409

Please sign in to comment.