Je travaille avec SwiftUI et j'essaie de créer une liste de boutons avec .buttonStyle personnalisé dans une vue Liste sur WatchOS, mais je ne parviens pas à le faire fonctionner. Est-ce même actuellement possible, et si oui, comment?
Exemple de projet:
struct Superhero: Identifiable { var id = UUID() var name: String } var superheroes = [ Superhero(name: "Batman"), Superhero(name: "Superman"), Superhero(name: "Wonder Woman"), Superhero(name: "Aquaman"), Superhero(name: "Green Lantern"), Superhero(name: "The Flash") ] struct SuperheroButtonStyle: ButtonStyle { func makeBody(configuration: Self.Configuration) -> some View { configuration.label .frame(minWidth: 0, maxWidth: .infinity) .foregroundColor(.white) .background(configuration.isPressed ? Color.white.opacity(0.95) : .green) .cornerRadius(13.0) } } struct SuperHeroesView: View{ var body: some View { List { ForEach(superheroes) { superhero in Button(action: { print(superhero.name) }){ Text(superhero.name) }.buttonStyle(SuperheroButtonStyle()) } } } }
Ce code produit ceci:
Au lieu de cela, je veux que les boutons ressemblent davantage à ceci:
Dans ce dernier exemple, j'utilise ScrollView au lieu de List, ce qui signifie que je n'obtiens pas la belle animation des lignes qui rétrécissent et disparaissent lors du défilement de la liste.
J'ai essayé de jouer avec un rembourrage négatif, mais cela ne peut pas me donner un plus grand rayon de coin (plus de coins arrondis que la valeur par défaut) et ne semble pas vraiment bon.
Existe-t-il donc un moyen d'appliquer correctement un ButtonStyle aux éléments d'une vue Liste, y compris en ayant un cornerRadius personnalisé?
Ou existe-t-il un autre moyen d'obtenir plus de contrôle sur l'apparence des lignes tout en conservant l'animation fournie avec List?
6 Réponses :
struct SuperHeroesView: View{ var body: some View { List { ForEach(superheroes) { superhero in Button(action: { print(superhero.name) }){ Text(superhero.name) }.buttonStyle(SuperheroButtonStyle()) .listRowInsets(EdgeInsets()) .listRowBackground(Color.clear) }.environment(\.defaultMinListRowHeight, 20) } } }
Je sais que ce n'est pas ainsi que cela est censé être implémenté, mais il semble qu'il y ait un bogue dans SwiftUI empêchant listRowPlatterColor
, listRowBackground
ou même listRowInsets
de faire quoi que ce soit dans la dernière version de watchOS.
Voici comment je l'ai contourné pour l'instant:
ZStack { Color.black MyRowView() } .padding(.horizontal, -8)
Pour avoir l'arrière-plan de la cellule entière dans une certaine couleur, vous devez utiliser le modificateur .listRowBackground
. Vous pouvez utiliser une Capsule
ou un RoundedRectangle
comme arrière-plan selon vos préférences:
struct SuperheroButtonStyle: ButtonStyle { func makeBody(configuration: Self.Configuration) -> some View { configuration.label .frame(minWidth: 0, maxWidth: .infinity) .foregroundColor(configuration.isPressed ? .gray : .white) } }
Vous voudrez probablement également changer le style du bouton, car l'effet de surbrillance d'arrière-plan n'affectera que le bouton, pas la cellule entière:
struct SuperHeroesView: View{ var body: some View { List { ForEach(superheroes) { superhero in Button(action: { print(superhero.name) }){ Text(superhero.name) } .buttonStyle(SuperheroButtonStyle()) } .listRowBackground(Capsule() .fill(Color.green)) // or as an alternative: //.listRowBackground(RoundedRectangle(cornerRadius: 13.0) // .fill(Color.green)) } } }
Je ne sais pas si vous l'avez encore compris ou non, mais j'ai fini par utiliser
.listRowPlatterColor(.clear)
pour étendre les bords de mes boutons jusqu'au bord de la liste comme ceci:
Vous pouvez également ajouter le modificateur
.environment(\.defaultMinListRowHeight, 20)
à la liste elle-même pour permettre à la hauteur des lignes de se réduire à la taille souhaitée. J'ai choisi 20 pour cet exemple:
Et enfin il y a un
List { ForEach(superheroes) { superhero in Button(action: { print(superhero.name) }){ Text(superhero.name) } .buttonStyle(SuperheroButtonStyle()) .listRowInsets(EdgeInsets.init(top: 0, leading: 0, bottom: 0, trailing: 0)) } }
modificateur que vous pouvez utiliser pour changer la couleur d'arrière-plan de la ligne elle-même. J'ai choisi clear pour cet exemple pour masquer les bords qui ne sont pas entièrement couverts par le bouton.
J'ai toujours ce petit peu de gris du style par défaut du bouton laissé sur WatchOS. Me rend fou! Mais merci pour cela, cela a aidé.
.listRowPlatterColor (.clear) M'a donné ce que je cherchais. C'était probablement plus difficile que nécessaire de le trouver.
struct ContentView: View { @State private var EnrouteText = "Enroute" var body: some View { List { Button(action: { self.EnrouteText = getCurrentTime() }) { Text(EnrouteText) } .buttonStyle(BtnStyle(bgColor: .red, fgColor: .white)) .listRowInsets(EdgeInsets.init(top: 0, leading: 0, bottom: 0, trailing: 0)) .listRowPlatterColor(.clear) // The rest of the buttons. } } } // Button Styles struct BtnStyle: ButtonStyle { var bgColor: Color var fgColor: Color func makeBody(configuration: Self.Configuration) -> some View { configuration.label .frame(minWidth: 0, maxWidth: .infinity) .padding() .foregroundColor(fgColor) .background(bgColor) .cornerRadius(32) } }
Selon les directives de l'interface humaine , il est recommandé que les boutons d'une vue défilante (par exemple, List
) ressemblent à un rectangle arrondi (plutôt qu'à une capsule).
Si vous essayez d'utiliser .listRowBackground
, vous obtiendrez un rectangle net (non souhaité):
Si vous utilisez à la place .listRowPlatterColor
, vous obtiendrez exactement ce qu'Apple vous recommande d'utiliser (dans une ligne de code, néanmoins):
Button("Log out") {} .listRowPlatterColor(Color.blue)
J'aimerais aussi savoir s'il existe un moyen de le faire correctement!
J'ai essayé de faire ça aussi. Il y a une propriété que vous pouvez ajouter sur une liste appelée
listStyle
je n'ai pas réussi à faire fonctionner. De plus, j'ai essayé de mettre en œuvre ce que vous avez fait (deux vues avec le marqueur de point en bas) Pouvez-vous peut-être aider?Plutôt que de publier une réponse qui pourrait manquer le point, avez-vous envisagé d'appliquer
.listStyle(CarouselListStyle())
à votreList
?