英文:
Swift: How to switch/change button color by selecting another button in CollectionView?
问题
ViewController有两个水平的collectionView和一个tableView。其中一个collectionView应该显示模型(StoriesModel)中按钮中的类别(枚举)。单击按钮选择用户想要在TableView中阅读的文章类别。
当用户单击按钮时,它会更改颜色为.blue。
需要的是,当用户单击下一个按钮(选择新的文章类别)时,按钮会更改颜色为.blue,而上一个按钮(类别)会变为.clear颜色。
现在,当我点击一个按钮时,它会更改颜色,但是当我点击下一个按钮时,它会变为.blue,但不会取消选择以前按钮的颜色为.clear。
CollectionViewCell:
//MARK: CollectionView Stories Buttons Protocol
protocol StoriesCollectionButtonsDelegate: AnyObject {
func didSelectButton(at index: Int)
}
class StoryCategoryCollectionViewCell: UICollectionViewCell {
//MARK: Category Outlets
@IBOutlet weak var categoryButton: UIButton!
//MARK: Static Properties
static let categoryCellIdentifier = "StoryCategoryCollectionViewCell"
//MARK: Properties
var storiesName: StoriesName?
//MARK: Button Delegate
weak var delegateButtons: StoriesCollectionButtonsDelegate?
//MARK: isSelectedButton
var isSelectedButton: Bool = true {
didSet {
categoryButton.backgroundColor = isSelectedButton ? .clear : .blue
}
}
//MARK: Awake From Nib
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
setUpStoryCategory()
categoryButton.addTarget(self, action: #selector(selectedButton), for: .touchUpInside)
}
//MARK: CollectionView Stories Buttons Action
@objc private func selectedButton() {
delegateButtons?.didSelectButton(at: self.tag)
isSelectedButton = !isSelectedButton
}
}
//MARK: Category Private Methods
extension StoryCategoryCollectionViewCell {
private func setUpStoryCategory() {
categoryButton.tintColor = .white
categoryButton.layer.cornerRadius = categoryButton.frame.size.height / 2
categoryButton.clipsToBounds = true
categoryButton.layer.borderColor = UIColor.white.cgColor
categoryButton.layer.borderWidth = 2
}
//MARK: Blue Color Home Button
func setUpCategoryCollectionViewCell(data: StoriesCategory) {
guard let category = StoriesName(rawValue: data.Category ?? 0) else {
return
}
categoryButton.setTitle(category.storiesName, for: .normal)
categoryButton.setTitleColor(.white, for: .normal)
if data.Category == 0 {
categoryButton.backgroundColor = .blue
} else {
categoryButton.backgroundColor = .clear
}
}
}
ViewController:
//MARK: - UICollectionViewDelegate
extension ViewController: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let item = StoriesName.allCases[indexPath.row]
self.selectedCategory = item
switch item {
case .Home:
return()
case .Zabava:
return()
case .Muzika:
return()
case .Životni_stil:
return()
case .Događaj:
return()
case .Sport:
return()
case .Tehnologija:
return()
case .Zdravlje:
return()
}
}
}
//MARK: - UICollectionViewDataSource
extension ViewController: UICollectionViewDataSource {
// ...
}
//MARK: CollectionView Stories Buttons Delegate
extension ViewController: StoriesCollectionButtonsDelegate {
func didSelectButton(at index: Int) {
if let previousIndex = selectedButtonIndex,
let previousCell = storiesCollection.cellForItem(at: IndexPath(item: previousIndex, section: 0)) as? StoryCategoryCollectionViewCell {
previousCell.isSelectedButton = false
switch previousCell.storiesName {
case .Home:
previousCell.categoryButton.backgroundColor = .clear
default:
previousCell.categoryButton.backgroundColor = .clear
}
}
if let currentCell = storiesCollection.cellForItem(at: IndexPath(item: index, section: 0)) as? StoryCategoryCollectionViewCell {
currentCell.isSelectedButton = true
currentCell.categoryButton.backgroundColor = .blue
}
selectedButtonIndex = index
}
}
需要点击类别按钮更改按钮的颜色,以便选择下一个类别取消选择上一个按钮并变为.clear,所选类别按钮变为.blue。
英文:
ViewController has two horizontal collectionViews and tableView. One of the collections should display the categories (enum) in the buttons from the model (StoriesModel). Click the button select the category of articles the user wants to read in the TableView.
When the user clicks the button, it changes color to .blue.
Need when the user clicks on the next button (selecting a new category of articles), the button changes color to .blue, and the previous button (category) becomes .clear color.
Now, when I click a button it changes color, but when I click next button it become .blue, but doesn't deselect the previous button color to .clear
CollectionViewCell:
//MARK: CollectionView Stories Buttons Protocol
protocol StoriesCollectionButtonsDelegate: AnyObject {
func didSelectButton(at index: Int)
}
class StoryCategoryCollectionViewCell: UICollectionViewCell {
//MARK: Category Outlets
@IBOutlet weak var categoryButton: UIButton!
//MARK: Static Properties
static let categoryCellIdentifier = "StoryCategoryCollectionViewCell"
//MARK: Properties
var storiesName: StoriesName?
//MARK: Button Delegate
weak var delegateButtons: StoriesCollectionButtonsDelegate?
//MARK: isSelectedButton
var isSelectedButton: Bool = true {
didSet {
categoryButton.backgroundColor = isSelectedButton ? .clear : .blue
}
}
//MARK: Awake From Nib
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
setUpStoryCategory()
categoryButton.addTarget(self, action: #selector(selectedButton), for: .touchUpInside)
}
//MARK: CollectionView Stories Buttons Action
@objc private func selectedButton() {
delegateButtons?.didSelectButton(at: self.tag)
isSelectedButton = !isSelectedButton
}
}
//MARK: Category Private Methods
extension StoryCategoryCollectionViewCell {
private func setUpStoryCategory() {
categoryButton.tintColor = .white
categoryButton.layer.cornerRadius = categoryButton.frame.size.height / 2
categoryButton.clipsToBounds = true
categoryButton.layer.borderColor = UIColor.white.cgColor
categoryButton.layer.borderWidth = 2
}
//MARK: Blue Color Home Button
func setUpCategoryCollectionViewCell(data: StoriesCategory) {
guard let category = StoriesName(rawValue: data.Category ?? 0) else {
return
}
categoryButton.setTitle(category.storiesName, for: .normal)
categoryButton.setTitleColor(.white, for: .normal)
if data.Category == 0 {
categoryButton.backgroundColor = .blue
} else {
categoryButton.backgroundColor = .clear
}
}
}
ViewController:
//MARK: - UICollectionViewDelegate
extension ViewController: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
//let item = stories[indexPath.row]
let item = StoriesName.allCases[indexPath.row]
self.selectedCategory = item
switch item {
case .Home:
return()
case .Zabava:
return()
case .Muzika:
return()
case .Životni_stil:
return()
case .Događaj:
return()
case .Sport:
return()
case .Tehnologija:
return()
case .Zdravlje:
return()
}
}
}
//MARK: - UICollectionViewDataSource
extension ViewController: UICollectionViewDataSource {
// ...
} else if collectionView == storiesCollection {
guard let categoryCell = collectionView.dequeueReusableCell(withReuseIdentifier: StoryCategoryCollectionViewCell.categoryCellIdentifier, for: indexPath) as? StoryCategoryCollectionViewCell else {
return UICollectionViewCell()
}
let item = stories[indexPath.row]
categoryCell.setUpCategoryCollecti
//MARK: CollectionView Stories Buttons Delegate
extension SeTvPlusViewController: StoriesCollectionButtonsDelegate {
func didSelectButton(at index: Int) {
if let previousIndex = selectedButtonIndex,
let previousCell = storiesCollection.cellForItem(at: IndexPath(item: previousIndex, section: 0)) as? StoryCategoryCollectionViewCell {
previousCell.isSelectedButton = false
switch previousCell.storiesName {
case .Home:
previousCell.categoryButton.backgroundColor = .clear
default:
previousCell.categoryButton.backgroundColor = .clear
}
}
if let currentCell = storiesCollection.cellForItem(at: IndexPath(item: index, section: 0)) as? StoryCategoryCollectionViewCell {
currentCell.isSelectedButton = true
currentCell.categoryButton.backgroundColor = .blue
}
selectedButtonIndex = index
}
}
onViewCell(data: item)
//MARK:
categoryCell.delegateButtons = self
return categoryCell
}
return UICollectionViewCell()
}
}
I define a protocol named StoriesCollectionButtonsDelegate. Declare a weak property named delegateButtons. Declare a property named isSelectedButton to update the background color.
Set a private method selected button that is called when the button inside the cell is tapped.
Declare two properties: selectedButtonIndex, which represents the index of the currently selected button in the collection view, and selectedCategory, which represents the currently selected category of stories.
In the UICollectionViewDelegate protocol. It implements the collectionView(_:didSelectItemAt:) method, which is called when an item (cell) in the collection view is selected.
And extend ViewController with StoriesCollectionButtonsDelegate protocol, which is responsible for handling button selection events in the collection view cells
Need that clicking on a category button changes the color of the button, so that selecting the next category deselects the previous button and becomes. clear and the selected category button becomes .blue
答案1
得分: 0
你可以通过使用一个变量来解决这个问题,用于存储所选的索引,如下所示:
var selectedIndex = 0
这将默认选择索引0,现在在didselectItem方法中更改此变量的值,并在每次重新加载集合时进行如下操作:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
self.selectedIndex = indexPath.row
DispatchQueue.main.async {
self.yourCollectionName.reloadData()
}
}
在cellForItemAt方法中,根据条件设置您的代码如下:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.row == self.selectedIndex {
// 将项目的颜色更改为已选颜色
} else {
// 将项目的颜色更改为未选颜色
}
}
请注意,代码中的注释部分表示需要根据您的需求添加具体的颜色更改代码。
英文:
You can resolve the problem by taking one variable to store the selected Index like :
var selectedIndex = 0
this will by default select the 0 index now change the value of this variable on didselectItem method and reload the collection everytime as:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt
indexPath: IndexPath) {
self.selectedIndex = indexPath.row
DispatchQueue.main.asyn {
self.youCollectionName.reloadData()
}
}
and in cellForItemAt Method, you can set your code under the conditions as :
func collectionView(_ collectionView: UICollectionView, cellForItemAt
indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.row == self.selectedIndex {
//Change the color of items to selected colours
}else {
//Change the color of item to unselected
}
}
答案2
得分: 0
我成功解决了这个任务,我猜这不是唯一的方法。我希望这个解决方案能帮助到别人。
- 集合中的所有按钮只有两种状态,打开和关闭。
- 在打开状态下,按钮是蓝色的,在关闭状态下,按钮是透明的。
- 单击按钮会将按钮的状态从关闭更改为打开,并将其颜色从蓝色更改为透明。
- 当单击处于打开状态的相同按钮第二次时,按钮不会更改其状态,也不会更改其颜色。
- 从打开到关闭的状态只能通过单击集合中的另一个按钮来更改。
- 集合中的每个按钮都可以更改集合中每个按钮的状态。
- 默认情况下,当ViewController打开时,主页按钮处于打开状态,但当点击集合中的任何按钮时,主页按钮应更改为关闭状态。
Cell:
//MARK: CollectionView Stories Buttons Protocol
protocol StoriesCollectionButtonsDelegate: AnyObject {
func didSelectButton(at index: Int)
}
class StoryCategoryCollectionViewCell: UICollectionViewCell {
//MARK: Category Outlets
@IBOutlet weak var categoryButton: UIButton!
//MARK: Static Properties
static let categoryCellIdentifier = "StoryCategoryCollectionViewCell"
//MARK: Properties
var storiesName: StoriesName?
var isSelectedButton: Bool = false {
didSet {
updateButtonAppearance()
}
}
weak var delegateButtons: StoriesCollectionButtonsDelegate?
private func updateButtonAppearance() {
if isSelectedButton {
categoryButton.backgroundColor = .blue
} else {
categoryButton.backgroundColor = .clear
}
}
//MARK: Awake From Nib
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
categoryButton.addTarget(self, action: #selector(selectedButton), for: .touchUpInside)
setUpStoryCategory()
}
//MARK: CollectionView Stories Buttons Action
@objc private func selectedButton() {
if !isSelectedButton {
delegateButtons?.didSelectButton(at: self.tag)
}
}
private func setUpStoryCategory() {
categoryButton.tintColor = .white
categoryButton.layer.cornerRadius = categoryButton.frame.size.height / 2
categoryButton.clipsToBounds = true
categoryButton.layer.borderColor = UIColor.white.cgColor
categoryButton.layer.borderWidth = 2
}
//MARK: Set Up Category Cell
func setUpCategoryCell(data: StoriesCategory, isSelected: Bool) {
guard let category = StoriesName(rawValue: data.Category ?? 0) else {
return
}
storiesName = category
categoryButton.setTitle(category.storiesName, for: .normal)
categoryButton.setTitleColor(.white, for: .normal)
if category == .Home {
categoryButton.isUserInteractionEnabled = false
isSelectedButton = true
} else {
categoryButton.isUserInteractionEnabled = true
isSelectedButton = isSelected
}
}
}
ViewController:
//MARK: Currently Selected Button Property
var selectedButtonIndex: Int?
var selectedCategory: StoriesName = .Home
//MARK: - UICollectionViewDelegate
extension ViewController: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let item = StoriesName.allCases[indexPath.row]
self.selectedCategory = item
collectionView.reloadData()
}
}
//MARK: - UICollectionViewDataSource
extension ViewController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if collectionView == chooseCollection {
return featuredStoryList.count
} else if collectionView == storiesCollection {
return stories.count
}
return 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if collectionView == chooseCollection {
guard let storyCell = collectionView.dequeueReusableCell(withReuseIdentifier: ChooserCollectionViewCell.cellIdentifier, for: indexPath) as? ChooserCollectionViewCell else {
return UICollectionViewCell()
}
let item = featuredStoryList[indexPath.row]
storyCell.setUpStroyDetailCell(data: item)
return storyCell
} else if collectionView == storiesCollection {
guard let categoryCell = collectionView.dequeueReusableCell(withReuseIdentifier: StoryCategoryCollectionViewCell.categoryCellIdentifier, for: indexPath) as? StoryCategoryCollectionViewCell else {
return UICollectionViewCell()
}
let item = stories[indexPath.row]
let isSelected = (selectedCategory.rawValue == item.Category)
categoryCell.setUpCategoryCell(data: item, isSelected: isSelected)
categoryCell.delegateButtons = self
categoryCell.tag = indexPath.row
return categoryCell
}
return UICollectionViewCell()
}
}
//MARK: - StoriesCollectionButtonsDelegate
extension ViewController: StoriesCollectionButtonsDelegate {
func didSelectButton(at index: Int) {
guard let selectedCell = storiesCollection.cellForItem(at: IndexPath(item: index, section: 0)) as? StoryCategoryCollectionViewCell else {
return
}
if let previousIndex = selectedButtonIndex,
let previousCell = storiesCollection.cellForItem(at: IndexPath(item: previousIndex, section: 0)) as? StoryCategoryCollectionViewCell {
previousCell.isSelectedButton = false
}
selectedCell.isSelectedButton.toggle()
selectedButtonIndex = index
if selectedCell.storiesName == .Home {
selectedCell.isSelectedButton = true
for cell in storiesCollection.visibleCells {
if let storyCell = cell as? StoryCategoryCollectionViewCell, storyCell.storiesName != .Home {
storyCell.isSelectedButton = false
}
}
} else if let homeCell = storiesCollection.cellForItem(at: IndexPath(item: 0, section: 0)) as? StoryCategoryCollectionViewCell {
homeCell.isSelectedButton = false
}
}
}
请注意,代码中可能有些符号需要根据上下文进行调整,以确保编译不会出错。
英文:
I managed to solve the task, I guess this is not the only way. I hope this solution will help someone.
- All buttons in the collection have only two states, On and Off
- In the On status, the button is .blue, in the Off status, the button is .clear
- Clicking on the button changes the status of the button from Off to On and changes its color from .blue to .clear
- When the same button that is in On status is clicked a second time, the button does not change its status and does not change its color
- The status from On to Off can only be changed by clicking on another button from the collection
- Each button in the collection can change the state of each button in the collection
- By default, the Home button is in the On status when the ViewContoller is opened, but when any button from collections is clicked the Home button should change status to Off.
Cell:
/MARK: CollectionView Stories Buttons Protocol
protocol StoriesCollectionButtonsDelegate: AnyObject {
func didSelectButton(at index: Int)
}
class StoryCategoryCollectionViewCell: UICollectionViewCell {
//MARK: Category Outlets
@IBOutlet weak var categoryButton: UIButton!
//MARK: Static Properties
static let categoryCellIdentifier = "StoryCategoryCollectionViewCell"
//MARK: Properties
var storiesName: StoriesName?
var isSelectedButton: Bool = false {
didSet {
updateButtonAppearance()
}
}
weak var delegateButtons: StoriesCollectionButtonsDelegate?
private func updateButtonAppearance() {
if isSelectedButton {
categoryButton.backgroundColor = .blue
} else {
categoryButton.backgroundColor = .clear
}
}
//MARK: Awake From Nib
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
categoryButton.addTarget(self, action: #selector(selectedButton), for: .touchUpInside)
setUpStoryCategory()
}
//MARK: CollectionView Stories Buttons Action
@objc private func selectedButton() {
if !isSelectedButton {
delegateButtons?.didSelectButton(at: self.tag)
}
}
private func setUpStoryCategory() {
categoryButton.tintColor = .white
categoryButton.layer.cornerRadius = categoryButton.frame.size.height / 2
categoryButton.clipsToBounds = true
categoryButton.layer.borderColor = UIColor.white.cgColor
categoryButton.layer.borderWidth = 2
}
//MARK: Set Up Category Cell
func setUpCategoryCell(data: StoriesCategory, isSelected: Bool) {
guard let category = StoriesName(rawValue: data.Category ?? 0) else {
return
}
storiesName = category
categoryButton.setTitle(category.storiesName, for: .normal)
categoryButton.setTitleColor(.white, for: .normal)
if category == .Home {
categoryButton.isUserInteractionEnabled = false
isSelectedButton = true
} else {
categoryButton.isUserInteractionEnabled = true
isSelectedButton = isSelected
}
}
}
ViewController:
//MARK: Currently Selected Button Property
var selectedButtonIndex: Int?
var selectedCategory: StoriesName = .Home
//MARK: - UICollectionViewDelegate
extension ViewController: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let item = StoriesName.allCases[indexPath.row]
self.selectedCategory = item
collectionView.reloadData()
}
}
//MARK: - UICollectionViewDataSource
extension ViewController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if collectionView == chooseCollection {
return featuredStoryList.count
} else if collectionView == storiesCollection {
return stories.count
}
return 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if collectionView == chooseCollection {
guard let storyCell = collectionView.dequeueReusableCell(withReuseIdentifier: ChooserCollectionViewCell.cellIdentifier, for: indexPath) as? ChooserCollectionViewCell else {
return UICollectionViewCell()
}
let item = featuredStoryList[indexPath.row]
storyCell.setUpStroyDetailCell(data: item)
return storyCell
} else if collectionView == storiesCollection {
guard let categoryCell = collectionView.dequeueReusableCell(withReuseIdentifier: StoryCategoryCollectionViewCell.categoryCellIdentifier, for: indexPath) as? StoryCategoryCollectionViewCell else {
return UICollectionViewCell()
}
let item = stories[indexPath.row]
let isSelected = (selectedCategory.rawValue == item.Category)
categoryCell.setUpCategoryCell(data: item, isSelected: isSelected)
categoryCell.delegateButtons = self
categoryCell.tag = indexPath.row
return categoryCell
}
return UICollectionViewCell()
}
}
//MARK: - StoriesCollectionButtonsDelegate
extension ViewController: StoriesCollectionButtonsDelegate {
func didSelectButton(at index: Int) {
guard let selectedCell = storiesCollection.cellForItem(at: IndexPath(item: index, section: 0)) as? StoryCategoryCollectionViewCell else {
return
}
if let previousIndex = selectedButtonIndex,
let previousCell = storiesCollection.cellForItem(at: IndexPath(item: previousIndex, section: 0)) as? StoryCategoryCollectionViewCell {
previousCell.isSelectedButton = false
}
selectedCell.isSelectedButton.toggle()
selectedButtonIndex = index
if selectedCell.storiesName == .Home {
selectedCell.isSelectedButton = true
for cell in storiesCollection.visibleCells {
if let storyCell = cell as? StoryCategoryCollectionViewCell, storyCell.storiesName != .Home {
storyCell.isSelectedButton = false
}
}
} else if let homeCell = storiesCollection.cellForItem(at: IndexPath(item: 0, section: 0)) as? StoryCategoryCollectionViewCell {
homeCell.isSelectedButton = false
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论