更改Swift中相邻按钮的背景色
当按下任何按钮时,我想更改视图中所有相邻按钮的颜色。最后,我将把它变成一个动画-几乎像一个涟漪效应 我查看了Combine框架,但它似乎有太多与我需要的功能无关的功能。因为用户可以按下任何按钮,我不认为为每个按钮创建一个观察者是一个经济的解决方案。我希望有一种方法可以找到按钮属性的相邻视图,并以某种方式影响它 这个问题有没有一个简单的解决方案,或者我需要构建一个复杂的IF语句矩阵,这是我在任何情况下都准备要做的 所有“我的按钮”都在UIStack视图中(1 x垂直堆栈视图中有8个水平堆栈视图) 下面是我的非理想解决方案:更改Swift中相邻按钮的背景色,swift,uibutton,uistackview,Swift,Uibutton,Uistackview,当按下任何按钮时,我想更改视图中所有相邻按钮的颜色。最后,我将把它变成一个动画-几乎像一个涟漪效应 我查看了Combine框架,但它似乎有太多与我需要的功能无关的功能。因为用户可以按下任何按钮,我不认为为每个按钮创建一个观察者是一个经济的解决方案。我希望有一种方法可以找到按钮属性的相邻视图,并以某种方式影响它 这个问题有没有一个简单的解决方案,或者我需要构建一个复杂的IF语句矩阵,这是我在任何情况下都准备要做的 所有“我的按钮”都在UIStack视图中(1 x垂直堆栈视图中有8个水平堆栈视图)
if sender.tag == 1 then {
view1.layer.backgroundColor = blue
view2.layer.backgroundColor = blue
view3.layer.backgroundColor = blue
} else if sender.tag == 2 then {
view4.layer.backgroundColor = blue
view5.layer.backgroundColor = blue
view6.layer.backgroundColor = blue
}...
通过搜索二维数组,可以找到“相邻”按钮
例如。。。如果您有一个8x8“网格”的按钮,您将有8行8列。点击任何按钮时,搜索各行以查找点击按钮的行和列
假设您在第4行:第4列
找到它,然后要找到相邻的按钮,在每个方向上减去并添加一行和一列:
// arrays are Zero based
// if tapped button is at
array[3][3]
// the button above it is at
array[3 - 1][3]
// the button to the left it is at
array[3][3 - 1]
// the button to the right it is at
array[3][3 + 1]
// the button below it is at
array[3 + 1][3]
如果“相邻”也要包含对角线,则只需为“上方和左侧”/“上方和右侧”/“下方和左侧”/“下方和右侧”/“下方和右侧”再添加一组“+/-”:
下面是一个完整的示例(仅限代码…无@IBOutlet
或@IBAction
连接):
类ViewController:UIViewController{
//用于跟踪按钮的二维阵列
//我们可以使用堆栈视图及其排列的子视图,但是
//这将避免重复展开选项
变量arrayOfButtons:[[UIButton]]=[]
//在网格上方添加重置按钮
让resetBtn=ui按钮()
//添加分段控件以选择完全相邻或对角
设segCtrl=UISegmentedControl(项:[“仅限完整”、“包括对角线”])
重写func viewDidLoad(){
super.viewDidLoad()
//创建一个8x8“网格”按钮
让outerStack=UIStackView()
outerStack.axis=.vertical
outerStack.distribution=.fills
//我们将使用Row:Col作为按钮标签
对于0..Void中的行{
guard let tappedBtn=发送器为?uI按钮其他{
返回
}
//找到点击按钮的行和列
变量行:Int=-1
变量列:Int=-1
对于0..0中的r{
//按上面的按钮
append(arrayOfButtons[row-1][col])
}
如果col>0{
//按左边的按钮
append(arrayOfButtons[row][col-1])
}
如果行0{
//按左上方的按钮
如果col>0{
append(arrayOfButtons[row-1][col-1])
}
//按上面的按钮
append(arrayOfButtons[row-1][col])
//按上面和右边的按钮
如果列0{
//按左边的按钮
append(arrayOfButtons[row][col-1])
}
如果列0{
append(arrayOfButtons[row+1][col-1])
}
//点击下面的按钮
append(arrayOfButtons[row+1][col])
//按下面和右边的按钮
如果列
您是如何定义“相邻”的?换句话说,为什么tag#1会导致1、2、3,而tag#2是4,5,6?公式是什么?在UIStackView中相邻,对不起,我会让它更清楚一点。你知道它们的顺序吗,或者你必须通过比较坐标来确定相邻吗?简短的答案,只是因为我在IB中如何排列它们。我想这是我问题的关键,如何确定哪些按钮与用户按下的按钮相邻。好吧,我已经删除了我的答案,因为它似乎不相关。看起来明智的做法是以逻辑的方式分配它们,这样您就可以知道哪些是相邻的,除非您以后以编程方式移动它们。
class ViewController: UIViewController {
// 2-D array to track the buttons
// we could use the stack views and their arrangedSubviews, but
// this will avoid repeated unwrapping of optionals
var arrayOfButtons: [[UIButton]] = []
// add a reset button above the grid
let resetBtn = UIButton()
// add a segmented control to select fully adjacent or diagonal
let segCtrl = UISegmentedControl(items: ["Full Only", "Include Diagonal"])
override func viewDidLoad() {
super.viewDidLoad()
// create an 8x8 "grid" of buttons
let outerStack = UIStackView()
outerStack.axis = .vertical
outerStack.distribution = .fillEqually
// we'll use Row:Col for the button labels
for row in 0..<8 {
var thisRow: [UIButton] = []
let rowStack = UIStackView()
rowStack.distribution = .fillEqually
for col in 0..<8 {
let b = UIButton()
b.backgroundColor = .blue
b.setTitle("\(row):\(col)", for: [])
b.setTitleColor(.white, for: .normal)
b.setTitleColor(.gray, for: .highlighted)
// add a border so we can see the frames
b.layer.borderWidth = 1.0
b.layer.borderColor = UIColor.yellow.cgColor
// square buttons
b.heightAnchor.constraint(equalTo: b.widthAnchor).isActive = true
// add button to rowStack
rowStack.addArrangedSubview(b)
// add button to 2-D array
thisRow.append(b)
// add target for button
b.addTarget(self, action: #selector(btnTapped(_:)), for: .touchUpInside)
}
// add rowStack to outerStack
outerStack.addArrangedSubview(rowStack)
// add this row of buttons to 2-D array
arrayOfButtons.append(thisRow)
}
// outerStack properties
outerStack.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(outerStack)
// respect safe area
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
// constrain outerStack width
outerStack.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 16.0),
outerStack.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -16.0),
// center vertically
outerStack.centerYAnchor.constraint(equalTo: g.centerYAnchor),
])
resetBtn.backgroundColor = .systemTeal
resetBtn.setTitle("Reset", for: [])
resetBtn.setTitleColor(.white, for: .normal)
resetBtn.setTitleColor(.gray, for: .highlighted)
resetBtn.addTarget(self, action: #selector(resetTapped(_:)), for: .touchUpInside)
[resetBtn, segCtrl].forEach {
$0.translatesAutoresizingMaskIntoConstraints = false
view.addSubview($0)
}
NSLayoutConstraint.activate([
resetBtn.bottomAnchor.constraint(equalTo: outerStack.topAnchor, constant: -20.0),
resetBtn.leadingAnchor.constraint(equalTo: outerStack.leadingAnchor),
resetBtn.trailingAnchor.constraint(equalTo: outerStack.trailingAnchor),
segCtrl.topAnchor.constraint(equalTo: outerStack.bottomAnchor, constant: 20.0),
segCtrl.leadingAnchor.constraint(equalTo: outerStack.leadingAnchor),
segCtrl.trailingAnchor.constraint(equalTo: outerStack.trailingAnchor),
])
segCtrl.selectedSegmentIndex = 0
}
@objc func resetTapped(_ sender: Any?) -> Void {
arrayOfButtons.forEach { thisRow in
thisRow.forEach { btn in
btn.backgroundColor = .blue
}
}
}
@objc func btnTapped(_ sender: Any?) -> Void {
guard let tappedBtn = sender as? UIButton else {
return
}
// find the row and column for the tapped button
var row: Int = -1
var col: Int = -1
for r in 0..<arrayOfButtons.count {
let thisRow = arrayOfButtons[r]
if let c = thisRow.firstIndex(of: tappedBtn) {
// found the tapped button
row = r
col = c
break
}
}
if row == -1 || col == -1 {
// did not find the tapped button in the grid!!!
return
}
// we found the row:col of the tapped button
var adjacentButtons: [UIButton] = [
tappedBtn
]
if segCtrl.selectedSegmentIndex == 0 {
// adjacent means ONLY above, left, right, below
if row > 0 {
// get button above
adjacentButtons.append(arrayOfButtons[row - 1][col])
}
if col > 0 {
// get button to the left
adjacentButtons.append(arrayOfButtons[row][col - 1])
}
if row < arrayOfButtons.count - 1 {
// get button below
adjacentButtons.append(arrayOfButtons[row + 1][col])
}
if col < arrayOfButtons[row].count - 1 {
// get button to the right
adjacentButtons.append(arrayOfButtons[row][col + 1])
}
} else {
// adjacent includes diagonals
if row > 0 {
// get button above and to the left
if col > 0 {
adjacentButtons.append(arrayOfButtons[row - 1][col - 1])
}
// get button above
adjacentButtons.append(arrayOfButtons[row - 1][col])
// get button above and to the right
if col < arrayOfButtons[row].count - 1 {
adjacentButtons.append(arrayOfButtons[row - 1][col + 1])
}
}
if col > 0 {
// get button to the left
adjacentButtons.append(arrayOfButtons[row][col - 1])
}
if col < arrayOfButtons[row].count - 1 {
// get button to the right
adjacentButtons.append(arrayOfButtons[row][col + 1])
}
if row < arrayOfButtons.count - 1 {
// get button below and to the left
if col > 0 {
adjacentButtons.append(arrayOfButtons[row + 1][col - 1])
}
// get button below
adjacentButtons.append(arrayOfButtons[row + 1][col])
// get button below and to the right
if col < arrayOfButtons[row].count - 1 {
adjacentButtons.append(arrayOfButtons[row + 1][col + 1])
}
}
}
adjacentButtons.forEach { btn in
btn.backgroundColor = .red
}
}
}