简体   繁体   English

SwiftUI:如何正确地允许用户在拖动手势后更改拖动元素的颜色

[英]SwiftUI: How to properly allow user to change dragged element's colour afer drag gesture

I am trying to create app that allows user to drag through the grid, and change colour of each touched cell.我正在尝试创建允许用户在网格中拖动并更改每个触摸单元格颜色的应用程序。 Some kind of pixel art drawing machine, but after making simple example it doesn't work, and I don't know why.某种像素艺术绘图机,但在制作简单示例后它不起作用,我不知道为什么。

Here is my code:这是我的代码:

struct Cell: View, Hashable, Equatable {
    @State var color: Color = .red
    let id = UUID()
    
    static func == (lhs: Cell, rhs: Cell) -> Bool {
        return lhs.color == rhs.color
    }

    func hash(into hasher: inout Hasher) {
        hasher.combine(color)
    }

    var body: some View {
        Rectangle()
            .frame(width: 40, height: 40)
            .foregroundColor(color)
    }
}

struct Grid: View {
    
    @State private var cells: [[Cell]] = (0..<10).map { _ in
        (0..<10).map { _ in Cell() }
    }

    var body: some View {
        VStack(spacing: 0) {
            ForEach(cells, id: \.self) { row in
                HStack(spacing: 0) {
                    ForEach(row, id: \.id) { cell in
                        cell
                    }
                }
            }
        }
        .background(Color.black)
        .gesture(
            DragGesture()
                .onChanged { value in
                    let width = 40
                    let height = 40
                    let x = Int(value.location.x / CGFloat(width))
                    let y = Int(value.location.y / CGFloat(height))
                    // Make sure the indices are within the bounds of the grid
                    if x >= 0 && x < 10 && y >= 0 && y < 10 {
                        self.cells[y][x].color = .green
                    }
                }
        )
    }
}

It's good to create separate models for cells.最好为细胞创建单独的模型。 here is a quick fix.这是一个快速修复。

struct CellView: View {
    var cell: Cell
    
    var body: some View {
        Rectangle()
            .frame(width: 40, height: 40)
            .foregroundColor(cell.color)
    }
}

struct Cell: Identifiable {
    var color: Color = .red
    let id = UUID()
}

struct Grid: View {
    
    @State private var cells: [[Cell]] = (0..<10).map { _ in
        (0..<10).map { _ in Cell() }
    }
    
    var body: some View {
        VStack(spacing: 0) {
            ForEach(cells.indices, id: \.self) { row in
                HStack(spacing: 0) {
                    ForEach(cells[row], id: \.id) { cell in
                        CellView(cell: cell)
                    }
                }
            }
        }
        .background(Color.black)
        .gesture(
            DragGesture()
                .onChanged { value in
                    let width = 40
                    let height = 40
                    let x = Int(value.location.x / CGFloat(width))
                    let y = Int(value.location.y / CGFloat(height))
                    // Make sure the indices are within the bounds of the grid
                    if x >= 0 && x < 10 && y >= 0 && y < 10 {
                        self.cells[y][x].color = .green
                    }
                }
        )
    }
}

在此处输入图像描述

@raja-kishan approach is good but you can just remove @State from @State var color: Color =.red from your Cell Struct like this. @raja-kishan 方法很好,但您可以像这样从 Cell Struct 中删除@State from @State var color: Color =.red

struct Cell: View, Hashable, Equatable {
    var color: Color = .red
    let id = UUID()
    
    static func == (lhs: Cell, rhs: Cell) -> Bool {
        return lhs.color == rhs.color
    }

    func hash(into hasher: inout Hasher) {
        hasher.combine(color)
    }

    var body: some View {
        Rectangle()
            .frame(width: 40, height: 40)
            .foregroundColor(color)
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM