Skip to content

Commit 37e2309

Browse files
authored
Merge pull request #2 from adisve/additions/pills
Additions/pills
2 parents ef6d264 + da05761 commit 37e2309

File tree

5 files changed

+74
-16
lines changed

5 files changed

+74
-16
lines changed

Assets/Showroom_1.png

-8.08 KB
Loading

Assets/Showroom_2.png

-6.78 KB
Loading

Example/PillPickerViewExample/PillPickerViewExample.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ struct ContentView: View {
3636
ExampleBuilder(selectedItems: $selectedGenres, content: {
3737
PillPickerView(items: genres, selectedPills: $selectedGenres)
3838
.pillStackStyle(.wrap)
39+
.pillLeadingIcon(Image(systemName: "popcorn"))
40+
.pillTrailingIcon(Image(systemName: "checkmark"))
41+
.pillTrailingOnlySelected(true)
3942
})
4043
.tag(0)
4144
.navigationTitle("Wrapping pills")
@@ -45,6 +48,9 @@ struct ContentView: View {
4548
ExampleBuilder(selectedItems: $selectedGenres, content: {
4649
PillPickerView(items: genres, selectedPills: $selectedGenres)
4750
.pillStackStyle(.noWrap)
51+
.pillLeadingIcon(Image(systemName: "popcorn"))
52+
.pillTrailingIcon(Image(systemName: "checkmark"))
53+
.pillTrailingOnlySelected(true)
4854
})
4955
.tag(1)
5056
.navigationTitle("Static pills")

README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,12 +219,22 @@ To change the foreground color of a not selected and selected pill, respectively
219219
The height and width of the pills can also be set, but width will be treated as the minimum width of the pills
220220

221221
```swift
222-
.pillWidth(20)
222+
.pillMinWidth(20)
223223
.pillHeight(10)
224224
```
225225

226226
<br>
227227

228+
This adds trailing and leading icons to the view, but only displays the trailing icons when the element has been selected.
229+
230+
```swift
231+
.pillLeadingIcon(Image(systemName: "popcorn"))
232+
.pillTrailingIcon(Image(systemName: "checkmark"))
233+
.pillTrailingOnlySelected(true) /// Only when item is selected
234+
```
235+
236+
<br>
237+
228238
Corner radius and border color can also be changed easily
229239

230240
```swift

Sources/PillPickerView.swift

Lines changed: 57 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,19 @@ public struct PillOptions {
6666
/// Spacing applied horizontally between pills
6767
public var horizontalSpacing: CGFloat = 2
6868

69-
/// Icon displayed in the pill when selected
70-
public var selectedIcon: Image = Image(systemName: "xmark")
69+
/// Trailing icon displayed inside the pills
70+
public var trailingIcon: Image? = nil
71+
72+
/// Leading icon displayed inside the pills
73+
public var leadingIcon: Image? = nil
74+
75+
/// Whether leading icon should only be displayed if
76+
/// the element is selected or not
77+
public var leadingOnlyWhenSelected: Bool = false
78+
79+
/// Whether trailing icon should only be displayed if
80+
/// the element is selected or not
81+
public var trailingOnlyWhenSelected: Bool = false
7182
}
7283

7384
// MARK: - Main view
@@ -221,9 +232,27 @@ public extension PillPickerView {
221232
return view
222233
}
223234

224-
func pillSelectedIcon(_ value: Image) -> PillPickerView {
235+
func pillLeadingIcon(_ value: Image) -> PillPickerView {
236+
var view = self
237+
view.options.leadingIcon = value
238+
return view
239+
}
240+
241+
func pillTrailingIcon(_ value: Image) -> PillPickerView {
242+
var view = self
243+
view.options.trailingIcon = value
244+
return view
245+
}
246+
247+
func pillTrailingOnlySelected(_ value: Bool) -> PillPickerView {
225248
var view = self
226-
view.options.selectedIcon = value
249+
view.options.trailingOnlyWhenSelected = value
250+
return view
251+
}
252+
253+
func pillLeadingOnlySelected(_ value: Bool) -> PillPickerView {
254+
var view = self
255+
view.options.leadingOnlyWhenSelected = value
227256
return view
228257
}
229258

@@ -252,23 +281,20 @@ struct PillView<T: Pill>: View {
252281
withAnimation(options.animation) {
253282
if !isItemSelected() {
254283
selectedPills.append(item)
284+
} else {
285+
selectedPills.removeAll(where: { $0 == item })
255286
}
256287
}
257288
}, label: {
258289
HStack {
290+
if !options.leadingOnlyWhenSelected || isItemSelected() {
291+
leadingIcon
292+
}
259293
Text(item.title)
260294
.font(options.font)
261295
.foregroundColor(pillForegroundColor)
262-
if isItemSelected() {
263-
options.selectedIcon
264-
.font(options.font)
265-
.foregroundColor(pillForegroundColor)
266-
.padding(.leading, 5)
267-
.onTapGesture {
268-
withAnimation(options.animation) {
269-
selectedPills.removeAll(where: { $0 == item })
270-
}
271-
}
296+
if !options.trailingOnlyWhenSelected || isItemSelected() {
297+
trailingIcon
272298
}
273299
}
274300
.padding(options.padding)
@@ -286,6 +312,20 @@ struct PillView<T: Pill>: View {
286312
.padding(.vertical, 2.5)
287313
}
288314

315+
var leadingIcon: some View {
316+
options.leadingIcon
317+
.font(options.font)
318+
.foregroundColor(pillForegroundColor)
319+
.padding(.leading, 5)
320+
}
321+
322+
var trailingIcon: some View {
323+
options.trailingIcon
324+
.font(options.font)
325+
.foregroundColor(pillForegroundColor)
326+
.padding(.leading, 5)
327+
}
328+
289329
// MARK: - Helper Functions
290330

291331
/// Checks if @Binding collection contains
@@ -367,11 +407,13 @@ struct StaticStack<T, V>: View where T: Pill, V: View {
367407
/// Current total height calculated
368408
@State private var totalHeight = CGFloat.zero
369409

410+
/// The calculateChunkSize function determines the optimal number
411+
/// of items per chunk based on the available width of the view.
370412
private func calculateChunkSize(geometry: GeometryProxy) {
371413
let availableWidth = geometry.size.width
372414
let itemWidth: CGFloat = 100
373415

374-
chunkSize = max(Int(availableWidth / (itemWidth + options.horizontalSpacing)), 1)
416+
chunkSize = max(Int(availableWidth / (itemWidth + options.minWidth + options.horizontalSpacing)), 1)
375417
}
376418

377419
// MARK: - Height Calculation

0 commit comments

Comments
 (0)