您可以通过搜索二维数组找到“相邻”按钮。
例如...如果您有一个 8x8 的“网格”按钮,那么您将拥有 8 个“列”的 8 个“行”。当您点击任何按钮时,搜索行以找到被点击按钮的行和列。
假设你在Row 4 : Col 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 连接):
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
}
}
}