Кнопка swiftUI с шириной: 0 тем не менее активна - PullRequest
1 голос
/ 14 марта 2020

Я установил ширину кнопки SwiftUI на 0, чтобы «деактивировать» ее.
Если для кнопки установлено значение 0, кнопка исчезает, как и ожидалось, но щелчок по левому краю желтого стека активирует Кнопка.
Почему это происходит?
Как мне избежать этого?

struct ContentView: View {
  @State var zeroWidth = false

  var body: some View {
    VStack{
      ButtonLine( leftButtons: [ButtonAttr( label: "LB1",
                                            action: {print("LB1")},
                                            iconSystemName : "person"
                                          )],
                                 zeroWidth: zeroWidth
                  )
      Button("Toggle width \(zeroWidth ? "On" : "Off" ) "){ self.zeroWidth.toggle() }
    }
  }
}

struct ButtonLine: View {
  let leftButtons : [ButtonAttr]
  let zeroWidth : Bool

  var body: some View {

    HStack(spacing: 0) {
      ForEach(leftButtons.indices, id: \.self)
      { i in
        HStack(spacing: 0.0)
        {
          Button(action: { self.leftButtons[i].action() }) {
            ButtonLabel( singleline: false,
                         buttonAttr: self.leftButtons[i]
            )
            .padding(0)
            //.background(Color.green)  // not visible
          }
         .buttonStyle(BorderlessButtonStyle())
            .frame( width: self.zeroWidth ? 0 : 100, height: 50) 
         .background(Color.green)
         .clipped()
         .foregroundColor(Color.white)
         .padding(0)
        }
        // .background(Color.blue)   // not visible
      }
      // .background(Color.blue)   // not visible
      Spacer()
      Text("CONTENT")
      .background(Color.green)
      .onTapGesture {
        print("Content tapped")
      }
      Spacer()
    }
    .background(Color.yellow)
      .onTapGesture {
        print("HS tapped")
    }
  }
}

struct ButtonLabel: View {
  var singleline : Bool
  var buttonAttr : ButtonAttr
  var body: some View {
    VStack (spacing: 0.0) {
      Image(systemName: buttonAttr.iconSystemName).frame(height: singleline ? 0 : 20).clipped()
      .padding(0)
      .background(Color.blue)
      Text(buttonAttr.label)
      .padding(0)
      .background(Color.blue)
    }
    .padding(0)
    .background(Color.red)
  }
}

struct ButtonAttr
{   let label : String
    let action: ()-> Void
    let iconSystemName : String
}

Ответы [ 3 ]

2 голосов
/ 14 марта 2020

Вместо хитрой «деактивации», просто используйте реальное удаление, как показано ниже

    HStack(spacing: 0.0)
    {
        if !self.zeroWidth {
            Button(action: { self.leftButtons[i].action() }) {
                ButtonLabel( singleline: false,
                             buttonAttr: self.leftButtons[i]
                )
                    .padding(0)
                //.background(Color.green)  // not visible
            }
            .buttonStyle(BorderlessButtonStyle())
            .frame(width: 100, height: 50)
            .background(Color.green)
            .clipped()
            .foregroundColor(Color.white)
            .padding(0)
        }
    }.frame(height: 50) // to keep height persistent
2 голосов
/ 14 марта 2020

очень простое объяснение.

попробуйте следующий фрагмент

struct ContentView: View {
    var body: some View {
        Text("Hello").padding().border(Color.yellow).fixedSize().frame(width: 0)
    }
}

enter image description here

Почему?

.frame(..) 

определяется как функция View, которая возвращает другой View, как любой вид модификатора View. Результирующий вид имеет нулевую рамку, как и ожидалось.

Это правда? Давайте проверим это!

struct ContentView: View {
    var body: some View {
        HStack(spacing: 0) {
            Rectangle()
                .fill(Color.orange)
                .frame(width: 100, height: 100)
            Text("Hello")
                .padding()
                .border(Color.black)
                .fixedSize()
                .frame(width: 0, height: 0)
            Rectangle()
                .fill(Color.green)
                .frame(width: 100, height: 100)
                .blendMode(.exclusion)
        }
    }
}

enter image description here

Просто добавьте модификатор .clipped к вашему текстовому представлению

struct ContentView: View {
    var body: some View {
        HStack(spacing: 0) {
            Rectangle()
                .fill(Color.orange)
                .frame(width: 100, height: 100)
            Text("Hello")
                .padding()
                .border(Color.black)
                .fixedSize()
                .frame(width: 0, height: 0)
                .clipped()
            Rectangle()
                .fill(Color.green)
                .frame(width: 100, height: 100)
                .blendMode(.exclusion)
        }
    }
}

и тексту " исчезает enter image description here "...

Он исчезает с экрана, но не из иерархии просмотра !. Измените код еще раз

struct ContentView: View {
    var body: some View {
        HStack(spacing: 0) {
            Rectangle()
                .fill(Color.orange)
                .frame(width: 100, height: 100)
            Text("Hello")
                .padding()
                .border(Color.black)
                .fixedSize().onTapGesture {
                    print("tap")
                }
                .frame(width: 0, height: 0)
                .clipped()
            Rectangle()
                .fill(Color.green)
                .frame(width: 100, height: 100)
                .blendMode(.exclusion)
        }
    }
}

, и вы увидите, что все еще есть некоторая «невидимая» область, чувствительная к жесту касания

enter image description here

1 голос
/ 14 марта 2020

Вы можете отключить кнопку, добавив .disabled(self.zeroWidth)

Button(action: { self.leftButtons[i].action() }) {
    ButtonLabel( singleline: false,
                buttonAttr: self.leftButtons[i]
    )
        .padding(0)
       //.background(Color.green)  // not visible
}
.disabled(self.zeroWidth)
.buttonStyle(BorderlessButtonStyle())
.frame( width: self.zeroWidth ? 0 : 100, height: 50)
.background(Color.green)
.clipped()
.foregroundColor(Color.white)
.padding(0)

enter image description here

Вы можете отладить иерархию представлений, щелкнув этот значок в xcode : enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...