2
votes

Comment découper une image sur un carré à l'intérieur d'une grille paresseuse? (SwiftUI)

Ce n’est pas un double de cette question .

Ci-dessous, vous verrez une grille de rectangles avec 3 colonnes. J'essaye d'obtenir le même effet mais avec des images. Les images doivent être coupées, mais sinon, ne semblent pas étirées ou déformées.

Voici comment j'ai réalisé la grille rectangulaire ...

Image(item)
    .resizable()
    .aspectRatio(1, contentMode: .fit)

C'est la mise en page que je veux en utilisant des rectangles ...

Image de grille rectangulaire

C'est mon objectif ...

Capture d'écran de l'application Photos

Mise à jour:

Si je fais ça ...

// In my view struct...

private let threeColumnGrid = [
    GridItem(.flexible(minimum: 40)),
    GridItem(.flexible(minimum: 40)),
    GridItem(.flexible(minimum: 40)),
]

// In my body...

LazyVGrid(columns: threeColumnGrid, alignment: .center) {
    ForEach(model.imageNames, id: \.self) { imageName in
        Rectangle()
            .foregroundColor(.red)
            .aspectRatio(1, contentMode: .fit)
    }
}

Les images se déforment si leur rapport hauteur / largeur n'était pas déjà de 1: 1. Par exemple, l'image du cercle dans la capture d'écran ci-dessous doit être un cercle parfait.

Exemple d'échec 1


2 commentaires

L'image a sa propre taille, mais la forme, dans ce cas Rectangle, ne l'est pas, donc la disposition peut différer (avec les mêmes paramètres d'entrée). Voulez-vous montrer d'une manière ou d'une autre ce que vous attendez des images?


J'ai mis à jour ma question avec un exemple de ce que je veux.


4 Réponses :


0
votes

J'ai répliqué du code avec des images aléatoires et j'ai obtenu ce qui suit. Vous n'êtes pas sûr de votre objectif, mais j'espère que cela peut être utile

démo

Testé avec Xcode 12 / iOS 14

struct TestImagesInGrid: View {
    @State private var imageNames: [String]

    private let threeColumnGrid = [
        GridItem(.flexible(minimum: 40)),
        GridItem(.flexible(minimum: 40)),
        GridItem(.flexible(minimum: 40)),
    ]

    init() {
        _imageNames = State(initialValue: (0..<8).map { _ in
            "image_\(Int.random(in: 1...3))"
        })
    }

    var body: some View {
        LazyVGrid(columns: threeColumnGrid, alignment: .center) {
            ForEach(imageNames.indices) { i in
                Image(imageNames[i]).resizable()
                    .aspectRatio(1, contentMode: .fit)
            }
        }
    }
}


1 commentaires

J'ai mis à jour ma question en utilisant votre technique. Cela ne fonctionne que si le rapport hauteur / largeur de l'image était déjà de 1: 1.



3
votes

J'ai trouvé une solution.

Définition du nombre de colonnes ...

LazyVGrid(columns: threeColumnGrid, alignment: .center) {
    ForEach(model.imageNames, id: \.self) { item in
        GeometryReader { gr in
            Image(item)
                .resizable()
                .scaledToFill()
                .frame(height: gr.size.width)
        }
        .clipped()
        .aspectRatio(1, contentMode: .fit)
    }
}

Création de la grille ...

// Somewhere in my view struct
private let threeColumnGrid = [
    GridItem(.flexible(minimum: 40)),
    GridItem(.flexible(minimum: 40)),
    GridItem(.flexible(minimum: 40)),
]


2 commentaires

Cela a résolu le même problème pour moi, mais en changeant le modificateur de cadre en .frame (hauteur: gr.size.width) afin que mon image ait toujours la même largeur et hauteur. Je suis curieux de savoir ce que fait ici la définition de la largeur du cadre sur la largeur proposée par la géométrie.


est-ce moi ou est-ce que cela ne centre pas l'image au milieu du carré?



0
votes

J'ai trouvé que la réponse du DPMitu ne centrait pas l'image (elle était alignée sur le bord d'attaque).

Cela a mieux fonctionné pour moi (ce qui ne nécessite pas non plus GeometryReader):

  LazyVGrid(columns: columns, spacing: 30) {
       ForEach(items) { item in
           Image("IMG_0044")
               .resizable()
               .scaledToFill()
               .frame(minWidth: 0, maxWidth: .infinity)
               .aspectRatio(1, contentMode: .fill)
               .clipped() //Alternatively you can use cornerRadius for the same effect
               //.cornerRadius(10)
       }
  }
    

Je l'ai trouvé ici https://www.appcoda.com/learnswiftui/swiftui-gridlayout.html environ à mi-chemin de la page


0 commentaires

0
votes

Certains demandaient si l'image apparaissait décentrée. Vous pouvez régler cela en ajoutant dans la ligne .position(x: gr.frame(in: .local).midX, y: gr.frame(in: .local).midY) . Donc, le tout serait:

Le nombre de colonnes

LazyVGrid(columns: threeColumnGrid, alignment: .center) {
    ForEach(model.imageNames, id: \.self) { item in
        GeometryReader { gr in
            Image(item)
                .resizable()
                .scaledToFill()
                .frame(height: gr.size.width)
                .position(x: gr.frame(in: .local).midX, y: gr.frame(in: .local).midY)
        }
        .clipped()
        .aspectRatio(1, contentMode: .fit)
    }
}

Créer la grille

// Somewhere in my view struct
private let threeColumnGrid = [
    GridItem(.flexible(minimum: 40)),
    GridItem(.flexible(minimum: 40)),
    GridItem(.flexible(minimum: 40)),
]


0 commentaires