以编程方式添加更改 Tableview 行的按钮
Programmatically add Buttons that change Tableview row
我的目标是创建显示绿色框的按钮。这个绿框是
@IBOutlet weak var categoryView: UIView!
一个引用的 UIView。我正在尝试添加可以转到如下所示的不同类别的按钮。理想情况下,我希望按钮以绿色 space 为中心,两侧有 10 个约束。当前的“卡片上显示的名称”是一个测试 运行 添加只是为了确保正确应用我的堆栈视图。因此,创建按钮一定有问题。但是,我不确定它是怎么错的。可能我想让这个视图自由形式,如果有很多类别,它可以脱离当前视图。任何建议表示赞赏
最后,我在创建按钮时有一些顾虑,只有一个 onclick 侦听器。但是,这个 onclick 侦听器有不同的指针,例如创建的第一个按钮会将视图更改为 table(附件)的第 0 行,但第二个应该转到 Appetizers,即第 1 行。第三个按钮应该转到第 3 行的沙漠。等等
我正在使用的数据如下所示。但是,这取决于后端检索,每次都可能不同
> [Carte.menu(menu_id: Optional(0), menu_category:
> Optional("Accessories"), menu_food_id: Optional(8023),
> menu_item_title: Optional("Whiskey On the Rock"),
> menu_item_description: Optional("<p>Balvenie Whiskey On the
> Rock</p>\n"), menu_item_imagefilePath:
> Optional("https://carteapp.net/wp-content/uploads/2020/07/whiskey-on-the-rock-1.jpg"),
> menu_item_price: Optional("8"), menu_item_sale: Optional(""),
> menu_item_options:
> Optional([Carte.menu_item_options(menu_item_options_unique_id:
> Optional(0), menu_item_options_id: Optional(0),
> menu_item_options_title: Optional(""),
> menu_item_options_multiple_choice_title: Optional(""),
> menu_item_options_multiple_choice_label: Optional([""]),
> menu_item_result: Optional(0), menu_item_result_multiple_string:
> Optional([""]), menu_item_description: Optional(""), price_update:
> Optional([""]))])), Carte.menu(menu_id: Optional(0), menu_category:
> Optional("Appetizers"), menu_food_id: Optional(6486), menu_item_title:
> Optional("Pizza"), menu_item_description: Optional("<p>Pienapple
> Pizza</p>\n"), menu_item_imagefilePath:
> Optional("https://carteapp.net/wp-content/uploads/2019/12/pizzaimage.jpe"),
> menu_item_price: Optional("10"), menu_item_sale: Optional(""),
> menu_item_options:
> Optional([Carte.menu_item_options(menu_item_options_unique_id:
> Optional(0), menu_item_options_id: Optional(0),
> menu_item_options_title: Optional(""),
> menu_item_options_multiple_choice_title: Optional(""),
> menu_item_options_multiple_choice_label: Optional([""]),
> menu_item_result: Optional(0), menu_item_result_multiple_string:
> Optional([""]), menu_item_description: Optional(""), price_update:
> Optional([""]))])), Carte.menu(menu_id: Optional(0), menu_category:
> Optional("Appetizers"), menu_food_id: Optional(6489), menu_item_title:
> Optional("Sushi"), menu_item_description: Optional("<p>Generic
> Sushi</p>\n"), menu_item_imagefilePath:
> Optional("https://carteapp.net/wp-content/uploads/2019/12/sushi.jpe"),
> menu_item_price: Optional("7"), menu_item_sale: Optional(""),
> menu_item_options:
> Optional([Carte.menu_item_options(menu_item_options_unique_id:
> Optional(0), menu_item_options_id: Optional(0),
> menu_item_options_title: Optional(""),
> menu_item_options_multiple_choice_title: Optional(""),
> menu_item_options_multiple_choice_label: Optional([""]),
> menu_item_result: Optional(0), menu_item_result_multiple_string:
> Optional([""]), menu_item_description: Optional(""), price_update:
> Optional([""]))])), Carte.menu(menu_id: Optional(0), menu_category:
> Optional("Desserts"), menu_food_id: Optional(8021), menu_item_title:
> Optional("Ice Cream"), menu_item_description: Optional("<p>Served with
> hot fudge whipped cream and a cherry</p>\n"), menu_item_imagefilePath:
> Optional("https://carteapp.net/wp-content/uploads/2020/07/ice-ice-cream-ice-cream-sundae-dessert-strawberries-berries-1.jpg"),
> menu_item_price: Optional("7.00"), menu_item_sale: Optional(""),
> menu_item_options:
> Optional([Carte.menu_item_options(menu_item_options_unique_id:
> Optional(0), menu_item_options_id: Optional(0),
> menu_item_options_title: Optional(""),
> menu_item_options_multiple_choice_title: Optional(""),
> menu_item_options_multiple_choice_label: Optional([""]),
> menu_item_result: Optional(0), menu_item_result_multiple_string:
> Optional([""]), menu_item_description: Optional(""), price_update:
> Optional([""]))])), Carte.menu(menu_id: Optional(0), menu_category:
> Optional("Desserts"), menu_food_id: Optional(8026), menu_item_title:
> Optional("Slice of Cake"), menu_item_description:
> Optional("<p>Frosted</p>\n"), menu_item_imagefilePath:
> Optional("https://carteapp.net/wp-content/uploads/2020/07/yummy-birthday-cake-on-platter-1-scaled.jpg"),
> menu_item_price: Optional("5.00"), menu_item_sale: Optional(""),
> menu_item_options:
> Optional([Carte.menu_item_options(menu_item_options_unique_id:
> Optional(0), menu_item_options_id: Optional(0),
> menu_item_options_title: Optional(""),
> menu_item_options_multiple_choice_title: Optional(""),
> menu_item_options_multiple_choice_label: Optional([""]),
> menu_item_result: Optional(0), menu_item_result_multiple_string:
> Optional([""]), menu_item_description: Optional(""), price_update:
> Optional([""]))])), Carte.menu(menu_id: Optional(0), menu_category:
> Optional("Main DIshes"), menu_food_id: Optional(8015),
> menu_item_title: Optional("Salmon"), menu_item_description:
> Optional("<p>Served with rice</p>\n"), menu_item_imagefilePath:
> Optional("https://carteapp.net/wp-content/uploads/2020/07/download-1.jpe"),
> menu_item_price: Optional("22.00"), menu_item_sale: Optional(""),
> menu_item_options:
> Optional([Carte.menu_item_options(menu_item_options_unique_id:
> Optional(0), menu_item_options_id: Optional(0),
> menu_item_options_title: Optional(""),
> menu_item_options_multiple_choice_title: Optional(""),
> menu_item_options_multiple_choice_label: Optional([""]),
> menu_item_result: Optional(0), menu_item_result_multiple_string:
> Optional([""]), menu_item_description: Optional(""), price_update:
> Optional([""]))])), Carte.menu(menu_id: Optional(0), menu_category:
> Optional("Main DIshes"), menu_food_id: Optional(8013),
> menu_item_title: Optional("Steaks 10o"), menu_item_description:
> Optional("<p>Steaks 10O</p>\n"), menu_item_imagefilePath:
> Optional("https://carteapp.net/wp-content/uploads/2020/07/testkitchen_argentinesteak-1.jpg"),
> menu_item_price: Optional("20.00"), menu_item_sale: Optional(""),
> menu_item_options:
> Optional([Carte.menu_item_options(menu_item_options_unique_id:
> Optional(0), menu_item_options_id: Optional(0),
> menu_item_options_title: Optional(""),
> menu_item_options_multiple_choice_title: Optional(""),
> menu_item_options_multiple_choice_label: Optional([""]),
> menu_item_result: Optional(0), menu_item_result_multiple_string:
> Optional([""]), menu_item_description: Optional(""), price_update:
> Optional([""]))])), Carte.menu(menu_id: Optional(0), menu_category:
> Optional("Sides"), menu_food_id: Optional(8017), menu_item_title:
> Optional("Fries"), menu_item_description: Optional("<p>Salted
> Fries</p>\n"), menu_item_imagefilePath:
> Optional("https://carteapp.net/wp-content/uploads/2020/07/Crispy-Oven-Fries-SpendWithPennies-27-480x270-1.jpg"),
> menu_item_price: Optional("9"), menu_item_sale: Optional(""),
> menu_item_options:
> Optional([Carte.menu_item_options(menu_item_options_unique_id:
> Optional(0), menu_item_options_id: Optional(0),
> menu_item_options_title: Optional(""),
> menu_item_options_multiple_choice_title: Optional(""),
> menu_item_options_multiple_choice_label: Optional([""]),
> menu_item_result: Optional(0), menu_item_result_multiple_string:
> Optional([""]), menu_item_description: Optional(""), price_update:
> Optional([""]))])), Carte.menu(menu_id: Optional(0), menu_category:
> Optional("Sides"), menu_food_id: Optional(8019), menu_item_title:
> Optional("Onion Rings"), menu_item_description: Optional("<p>Stacked
> in a tower</p>\n"), menu_item_imagefilePath:
> Optional("https://carteapp.net/wp-content/uploads/2020/07/4566354955_88c4163841_b-1.jpg"),
> menu_item_price: Optional("5.00"), menu_item_sale: Optional(""),
> menu_item_options:
> Optional([Carte.menu_item_options(menu_item_options_unique_id:
> Optional(0), menu_item_options_id: Optional(0),
> menu_item_options_title: Optional(""),
> menu_item_options_multiple_choice_title: Optional(""),
> menu_item_options_multiple_choice_label: Optional([""]),
> menu_item_result: Optional(0)
类别看起来像这样,这里的字符串是类别,这里的整数是它在 table 上的位置。
["Accessories": 0, "Appetizers": 1, "Main DIshes": 5, "Sides": 7, "Desserts": 3]
代码在这里
override func viewDidLoad() {
super.viewDidLoad()
filterMenuFunc()
var count = 0
while(filteredCategorizedMenu.count > count)
{
print(count)
if (Categories == [:])
{
Categories = [filteredCategorizedMenu[count].menu_category : count] as! [String : Int]
currentCategoryName = filteredCategorizedMenu[count].menu_category!
arrayOfButtons.append(CategoryButton(key: filteredCategorizedMenu[count].menu_category!, Row: 0))
print(Categories)
}
else if (filteredCategorizedMenu[count].menu_category != currentCategoryName)
{
print(filteredCategorizedMenu[count].menu_category! + " and " + currentCategoryName)
Categories[filteredCategorizedMenu[count].menu_category!] = count
currentCategoryName = filteredCategorizedMenu[count].menu_category!
arrayOfButtons.append(CategoryButton(key: filteredCategorizedMenu[count].menu_category!, Row: count))
print(Categories)
}
count = count + 1
}
let stackView = UIStackView(arrangedSubviews: arrayOfButtons)
stackView.axis = .horizontal
stackView.spacing = 20
stackView.distribution = .fillProportionally
stackView.translatesAutoresizingMaskIntoConstraints = false
categoryView.addSubview(stackView)
print(arrayOfButtons)
}
func CategoryButton(key: String, Row: Int) -> UIButton
{
let Button = UIButton()
Button.tag = Row
Button.addTarget(self, action: Selector(("buttonCLicked")), for: .touchUpInside )
Button.titleLabel!.textColor = .black
Button.titleLabel!.text = key
Button.titleLabel!.font = UIFont(name: "Avenir-Book", size: 20 )!
Button.frame = CGRect(x: 0, y: 0, width: Button.intrinsicContentSize.width + 18, height: 40)
return Button
}
func buttonClicked( _ sender: UIButton!)
{
let indexPath = IndexPath(row: sender!.tag, section: 0)
menuTableView.scrollToRow(at: indexPath, at: UITableView.ScrollPosition.top, animated: true)
}
按钮打印看起来像这样
[<UIButton: 0x7fbce7d15f70; frame = (0 0; 48 40); opaque = NO; layer = <CALayer: 0x6000038014c0>>, <UIButton: 0x7fbce7d0aec0; frame = (0 0; 48 40); opaque = NO; tag = 1; layer = <CALayer: 0x600003802100>>, <UIButton: 0x7fbce7d150b0; frame = (0 0; 48 40); opaque = NO; tag = 3; layer = <CALayer: 0x600003802680>>, <UIButton: 0x7fbce7d21380; frame = (0 0; 48 40); opaque = NO; tag = 5; layer = <CALayer: 0x600003803460>>, <UIButton: 0x7fbce7d219a0; frame = (0 0; 48 40); opaque = NO; tag = 7; layer = <CALayer: 0x6000038030a0>>]
两件事...
您创建按钮的方式有几个错误。此外,如果您要将它们添加到堆栈视图,请不要设置它们的框架(无论如何都会被堆栈视图覆盖)。
您最好为 table 视图使用多个部分。
按钮太宽放不下,因此您可能希望将堆栈视图放入滚动视图。
无论如何,目前还不清楚您是如何解析和存储数据的,所以我只是模拟了一个示例。这假设您已经设置了绿色 @IBOutlet weak var categoryView: UIView!
:
struct Category {
var title: String = ""
var rowNumber: Int = 0
}
class CategoryTestViewController: UIViewController {
@IBOutlet var categoryView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
// whatever your process is to build this array
let myData = ["Accessories": 0, "Appetizers": 1, "Main DIshes": 5, "Sides": 7, "Desserts": 3]
let categoryData: [Category] = [
Category(title: "Accessories", rowNumber: 0),
Category(title: "Appetizers", rowNumber: 1),
Category(title: "Main Dishes", rowNumber: 5),
Category(title: "Sides", rowNumber: 7),
Category(title: "Desserts", rowNumber: 3),
]
// create a horizontal stack view
let buttonsStack = UIStackView()
buttonsStack.translatesAutoresizingMaskIntoConstraints = false
buttonsStack.axis = .horizontal
buttonsStack.alignment = .fill
buttonsStack.distribution = .fill
buttonsStack.spacing = 20
// for each category, add a button to the stack view
categoryData.forEach { cat in
let btn = CategoryButton(key: cat.title, Row: cat.rowNumber)
buttonsStack.addArrangedSubview(btn)
}
// create a scroll view
let scrollView = UIScrollView()
scrollView.translatesAutoresizingMaskIntoConstraints = false
// add the buttons stack view to the scroll view
scrollView.addSubview(buttonsStack)
// add the scroll view to the "categoryView"
categoryView.addSubview(scrollView)
NSLayoutConstraint.activate([
// constrain scrollView to all 4 sides
scrollView.topAnchor.constraint(equalTo: categoryView.topAnchor),
scrollView.leadingAnchor.constraint(equalTo: categoryView.leadingAnchor),
scrollView.trailingAnchor.constraint(equalTo: categoryView.trailingAnchor),
scrollView.bottomAnchor.constraint(equalTo: categoryView.bottomAnchor),
// constrain stack view Top and Bottom
// Leading and Trailing with 20-pts "padding"
buttonsStack.topAnchor.constraint(equalTo: scrollView.topAnchor),
buttonsStack.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 20),
buttonsStack.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: -20),
buttonsStack.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
// constrain stack view Height to scrollView height
buttonsStack.heightAnchor.constraint(equalTo: scrollView.heightAnchor),
])
}
func CategoryButton(key: String, Row: Int) -> UIButton
{
let Button = UIButton()
Button.tag = Row
Button.addTarget(self, action: #selector(self.buttonClicked(_:)), for: .touchUpInside )
// don't do this
//Button.titleLabel!.textColor = .black
//Button.titleLabel!.text = key
//Button.titleLabel!.font = UIFont(name: "Avenir-Book", size: 20 )!
// don't set a frame
//Button.frame = CGRect(x: 0, y: 0, width: Button.intrinsicContentSize.width + 18, height: 40)
// create the button properly!
Button.setTitle(key, for: [])
Button.setTitleColor(.blue, for: [])
Button.setTitleColor(.lightGray, for: .highlighted)
Button.titleLabel?.font = UIFont(name: "Avenir-Book", size: 20 )
return Button
}
@objc func buttonClicked( _ sender: UIButton!)
{
print("button \(sender.currentTitle) tapped")
let indexPath = IndexPath(row: sender.tag, section: 0)
//menuTableView.scrollToRow(at: indexPath, at: UITableView.ScrollPosition.top, animated: true)
}
}
我的目标是创建显示绿色框的按钮。这个绿框是
@IBOutlet weak var categoryView: UIView!
一个引用的 UIView。我正在尝试添加可以转到如下所示的不同类别的按钮。理想情况下,我希望按钮以绿色 space 为中心,两侧有 10 个约束。当前的“卡片上显示的名称”是一个测试 运行 添加只是为了确保正确应用我的堆栈视图。因此,创建按钮一定有问题。但是,我不确定它是怎么错的。可能我想让这个视图自由形式,如果有很多类别,它可以脱离当前视图。任何建议表示赞赏
最后,我在创建按钮时有一些顾虑,只有一个 onclick 侦听器。但是,这个 onclick 侦听器有不同的指针,例如创建的第一个按钮会将视图更改为 table(附件)的第 0 行,但第二个应该转到 Appetizers,即第 1 行。第三个按钮应该转到第 3 行的沙漠。等等
我正在使用的数据如下所示。但是,这取决于后端检索,每次都可能不同
> [Carte.menu(menu_id: Optional(0), menu_category:
> Optional("Accessories"), menu_food_id: Optional(8023),
> menu_item_title: Optional("Whiskey On the Rock"),
> menu_item_description: Optional("<p>Balvenie Whiskey On the
> Rock</p>\n"), menu_item_imagefilePath:
> Optional("https://carteapp.net/wp-content/uploads/2020/07/whiskey-on-the-rock-1.jpg"),
> menu_item_price: Optional("8"), menu_item_sale: Optional(""),
> menu_item_options:
> Optional([Carte.menu_item_options(menu_item_options_unique_id:
> Optional(0), menu_item_options_id: Optional(0),
> menu_item_options_title: Optional(""),
> menu_item_options_multiple_choice_title: Optional(""),
> menu_item_options_multiple_choice_label: Optional([""]),
> menu_item_result: Optional(0), menu_item_result_multiple_string:
> Optional([""]), menu_item_description: Optional(""), price_update:
> Optional([""]))])), Carte.menu(menu_id: Optional(0), menu_category:
> Optional("Appetizers"), menu_food_id: Optional(6486), menu_item_title:
> Optional("Pizza"), menu_item_description: Optional("<p>Pienapple
> Pizza</p>\n"), menu_item_imagefilePath:
> Optional("https://carteapp.net/wp-content/uploads/2019/12/pizzaimage.jpe"),
> menu_item_price: Optional("10"), menu_item_sale: Optional(""),
> menu_item_options:
> Optional([Carte.menu_item_options(menu_item_options_unique_id:
> Optional(0), menu_item_options_id: Optional(0),
> menu_item_options_title: Optional(""),
> menu_item_options_multiple_choice_title: Optional(""),
> menu_item_options_multiple_choice_label: Optional([""]),
> menu_item_result: Optional(0), menu_item_result_multiple_string:
> Optional([""]), menu_item_description: Optional(""), price_update:
> Optional([""]))])), Carte.menu(menu_id: Optional(0), menu_category:
> Optional("Appetizers"), menu_food_id: Optional(6489), menu_item_title:
> Optional("Sushi"), menu_item_description: Optional("<p>Generic
> Sushi</p>\n"), menu_item_imagefilePath:
> Optional("https://carteapp.net/wp-content/uploads/2019/12/sushi.jpe"),
> menu_item_price: Optional("7"), menu_item_sale: Optional(""),
> menu_item_options:
> Optional([Carte.menu_item_options(menu_item_options_unique_id:
> Optional(0), menu_item_options_id: Optional(0),
> menu_item_options_title: Optional(""),
> menu_item_options_multiple_choice_title: Optional(""),
> menu_item_options_multiple_choice_label: Optional([""]),
> menu_item_result: Optional(0), menu_item_result_multiple_string:
> Optional([""]), menu_item_description: Optional(""), price_update:
> Optional([""]))])), Carte.menu(menu_id: Optional(0), menu_category:
> Optional("Desserts"), menu_food_id: Optional(8021), menu_item_title:
> Optional("Ice Cream"), menu_item_description: Optional("<p>Served with
> hot fudge whipped cream and a cherry</p>\n"), menu_item_imagefilePath:
> Optional("https://carteapp.net/wp-content/uploads/2020/07/ice-ice-cream-ice-cream-sundae-dessert-strawberries-berries-1.jpg"),
> menu_item_price: Optional("7.00"), menu_item_sale: Optional(""),
> menu_item_options:
> Optional([Carte.menu_item_options(menu_item_options_unique_id:
> Optional(0), menu_item_options_id: Optional(0),
> menu_item_options_title: Optional(""),
> menu_item_options_multiple_choice_title: Optional(""),
> menu_item_options_multiple_choice_label: Optional([""]),
> menu_item_result: Optional(0), menu_item_result_multiple_string:
> Optional([""]), menu_item_description: Optional(""), price_update:
> Optional([""]))])), Carte.menu(menu_id: Optional(0), menu_category:
> Optional("Desserts"), menu_food_id: Optional(8026), menu_item_title:
> Optional("Slice of Cake"), menu_item_description:
> Optional("<p>Frosted</p>\n"), menu_item_imagefilePath:
> Optional("https://carteapp.net/wp-content/uploads/2020/07/yummy-birthday-cake-on-platter-1-scaled.jpg"),
> menu_item_price: Optional("5.00"), menu_item_sale: Optional(""),
> menu_item_options:
> Optional([Carte.menu_item_options(menu_item_options_unique_id:
> Optional(0), menu_item_options_id: Optional(0),
> menu_item_options_title: Optional(""),
> menu_item_options_multiple_choice_title: Optional(""),
> menu_item_options_multiple_choice_label: Optional([""]),
> menu_item_result: Optional(0), menu_item_result_multiple_string:
> Optional([""]), menu_item_description: Optional(""), price_update:
> Optional([""]))])), Carte.menu(menu_id: Optional(0), menu_category:
> Optional("Main DIshes"), menu_food_id: Optional(8015),
> menu_item_title: Optional("Salmon"), menu_item_description:
> Optional("<p>Served with rice</p>\n"), menu_item_imagefilePath:
> Optional("https://carteapp.net/wp-content/uploads/2020/07/download-1.jpe"),
> menu_item_price: Optional("22.00"), menu_item_sale: Optional(""),
> menu_item_options:
> Optional([Carte.menu_item_options(menu_item_options_unique_id:
> Optional(0), menu_item_options_id: Optional(0),
> menu_item_options_title: Optional(""),
> menu_item_options_multiple_choice_title: Optional(""),
> menu_item_options_multiple_choice_label: Optional([""]),
> menu_item_result: Optional(0), menu_item_result_multiple_string:
> Optional([""]), menu_item_description: Optional(""), price_update:
> Optional([""]))])), Carte.menu(menu_id: Optional(0), menu_category:
> Optional("Main DIshes"), menu_food_id: Optional(8013),
> menu_item_title: Optional("Steaks 10o"), menu_item_description:
> Optional("<p>Steaks 10O</p>\n"), menu_item_imagefilePath:
> Optional("https://carteapp.net/wp-content/uploads/2020/07/testkitchen_argentinesteak-1.jpg"),
> menu_item_price: Optional("20.00"), menu_item_sale: Optional(""),
> menu_item_options:
> Optional([Carte.menu_item_options(menu_item_options_unique_id:
> Optional(0), menu_item_options_id: Optional(0),
> menu_item_options_title: Optional(""),
> menu_item_options_multiple_choice_title: Optional(""),
> menu_item_options_multiple_choice_label: Optional([""]),
> menu_item_result: Optional(0), menu_item_result_multiple_string:
> Optional([""]), menu_item_description: Optional(""), price_update:
> Optional([""]))])), Carte.menu(menu_id: Optional(0), menu_category:
> Optional("Sides"), menu_food_id: Optional(8017), menu_item_title:
> Optional("Fries"), menu_item_description: Optional("<p>Salted
> Fries</p>\n"), menu_item_imagefilePath:
> Optional("https://carteapp.net/wp-content/uploads/2020/07/Crispy-Oven-Fries-SpendWithPennies-27-480x270-1.jpg"),
> menu_item_price: Optional("9"), menu_item_sale: Optional(""),
> menu_item_options:
> Optional([Carte.menu_item_options(menu_item_options_unique_id:
> Optional(0), menu_item_options_id: Optional(0),
> menu_item_options_title: Optional(""),
> menu_item_options_multiple_choice_title: Optional(""),
> menu_item_options_multiple_choice_label: Optional([""]),
> menu_item_result: Optional(0), menu_item_result_multiple_string:
> Optional([""]), menu_item_description: Optional(""), price_update:
> Optional([""]))])), Carte.menu(menu_id: Optional(0), menu_category:
> Optional("Sides"), menu_food_id: Optional(8019), menu_item_title:
> Optional("Onion Rings"), menu_item_description: Optional("<p>Stacked
> in a tower</p>\n"), menu_item_imagefilePath:
> Optional("https://carteapp.net/wp-content/uploads/2020/07/4566354955_88c4163841_b-1.jpg"),
> menu_item_price: Optional("5.00"), menu_item_sale: Optional(""),
> menu_item_options:
> Optional([Carte.menu_item_options(menu_item_options_unique_id:
> Optional(0), menu_item_options_id: Optional(0),
> menu_item_options_title: Optional(""),
> menu_item_options_multiple_choice_title: Optional(""),
> menu_item_options_multiple_choice_label: Optional([""]),
> menu_item_result: Optional(0)
类别看起来像这样,这里的字符串是类别,这里的整数是它在 table 上的位置。
["Accessories": 0, "Appetizers": 1, "Main DIshes": 5, "Sides": 7, "Desserts": 3]
代码在这里
override func viewDidLoad() {
super.viewDidLoad()
filterMenuFunc()
var count = 0
while(filteredCategorizedMenu.count > count)
{
print(count)
if (Categories == [:])
{
Categories = [filteredCategorizedMenu[count].menu_category : count] as! [String : Int]
currentCategoryName = filteredCategorizedMenu[count].menu_category!
arrayOfButtons.append(CategoryButton(key: filteredCategorizedMenu[count].menu_category!, Row: 0))
print(Categories)
}
else if (filteredCategorizedMenu[count].menu_category != currentCategoryName)
{
print(filteredCategorizedMenu[count].menu_category! + " and " + currentCategoryName)
Categories[filteredCategorizedMenu[count].menu_category!] = count
currentCategoryName = filteredCategorizedMenu[count].menu_category!
arrayOfButtons.append(CategoryButton(key: filteredCategorizedMenu[count].menu_category!, Row: count))
print(Categories)
}
count = count + 1
}
let stackView = UIStackView(arrangedSubviews: arrayOfButtons)
stackView.axis = .horizontal
stackView.spacing = 20
stackView.distribution = .fillProportionally
stackView.translatesAutoresizingMaskIntoConstraints = false
categoryView.addSubview(stackView)
print(arrayOfButtons)
}
func CategoryButton(key: String, Row: Int) -> UIButton
{
let Button = UIButton()
Button.tag = Row
Button.addTarget(self, action: Selector(("buttonCLicked")), for: .touchUpInside )
Button.titleLabel!.textColor = .black
Button.titleLabel!.text = key
Button.titleLabel!.font = UIFont(name: "Avenir-Book", size: 20 )!
Button.frame = CGRect(x: 0, y: 0, width: Button.intrinsicContentSize.width + 18, height: 40)
return Button
}
func buttonClicked( _ sender: UIButton!)
{
let indexPath = IndexPath(row: sender!.tag, section: 0)
menuTableView.scrollToRow(at: indexPath, at: UITableView.ScrollPosition.top, animated: true)
}
按钮打印看起来像这样
[<UIButton: 0x7fbce7d15f70; frame = (0 0; 48 40); opaque = NO; layer = <CALayer: 0x6000038014c0>>, <UIButton: 0x7fbce7d0aec0; frame = (0 0; 48 40); opaque = NO; tag = 1; layer = <CALayer: 0x600003802100>>, <UIButton: 0x7fbce7d150b0; frame = (0 0; 48 40); opaque = NO; tag = 3; layer = <CALayer: 0x600003802680>>, <UIButton: 0x7fbce7d21380; frame = (0 0; 48 40); opaque = NO; tag = 5; layer = <CALayer: 0x600003803460>>, <UIButton: 0x7fbce7d219a0; frame = (0 0; 48 40); opaque = NO; tag = 7; layer = <CALayer: 0x6000038030a0>>]
两件事...
您创建按钮的方式有几个错误。此外,如果您要将它们添加到堆栈视图,请不要设置它们的框架(无论如何都会被堆栈视图覆盖)。
您最好为 table 视图使用多个部分。
按钮太宽放不下,因此您可能希望将堆栈视图放入滚动视图。
无论如何,目前还不清楚您是如何解析和存储数据的,所以我只是模拟了一个示例。这假设您已经设置了绿色 @IBOutlet weak var categoryView: UIView!
:
struct Category {
var title: String = ""
var rowNumber: Int = 0
}
class CategoryTestViewController: UIViewController {
@IBOutlet var categoryView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
// whatever your process is to build this array
let myData = ["Accessories": 0, "Appetizers": 1, "Main DIshes": 5, "Sides": 7, "Desserts": 3]
let categoryData: [Category] = [
Category(title: "Accessories", rowNumber: 0),
Category(title: "Appetizers", rowNumber: 1),
Category(title: "Main Dishes", rowNumber: 5),
Category(title: "Sides", rowNumber: 7),
Category(title: "Desserts", rowNumber: 3),
]
// create a horizontal stack view
let buttonsStack = UIStackView()
buttonsStack.translatesAutoresizingMaskIntoConstraints = false
buttonsStack.axis = .horizontal
buttonsStack.alignment = .fill
buttonsStack.distribution = .fill
buttonsStack.spacing = 20
// for each category, add a button to the stack view
categoryData.forEach { cat in
let btn = CategoryButton(key: cat.title, Row: cat.rowNumber)
buttonsStack.addArrangedSubview(btn)
}
// create a scroll view
let scrollView = UIScrollView()
scrollView.translatesAutoresizingMaskIntoConstraints = false
// add the buttons stack view to the scroll view
scrollView.addSubview(buttonsStack)
// add the scroll view to the "categoryView"
categoryView.addSubview(scrollView)
NSLayoutConstraint.activate([
// constrain scrollView to all 4 sides
scrollView.topAnchor.constraint(equalTo: categoryView.topAnchor),
scrollView.leadingAnchor.constraint(equalTo: categoryView.leadingAnchor),
scrollView.trailingAnchor.constraint(equalTo: categoryView.trailingAnchor),
scrollView.bottomAnchor.constraint(equalTo: categoryView.bottomAnchor),
// constrain stack view Top and Bottom
// Leading and Trailing with 20-pts "padding"
buttonsStack.topAnchor.constraint(equalTo: scrollView.topAnchor),
buttonsStack.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 20),
buttonsStack.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: -20),
buttonsStack.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
// constrain stack view Height to scrollView height
buttonsStack.heightAnchor.constraint(equalTo: scrollView.heightAnchor),
])
}
func CategoryButton(key: String, Row: Int) -> UIButton
{
let Button = UIButton()
Button.tag = Row
Button.addTarget(self, action: #selector(self.buttonClicked(_:)), for: .touchUpInside )
// don't do this
//Button.titleLabel!.textColor = .black
//Button.titleLabel!.text = key
//Button.titleLabel!.font = UIFont(name: "Avenir-Book", size: 20 )!
// don't set a frame
//Button.frame = CGRect(x: 0, y: 0, width: Button.intrinsicContentSize.width + 18, height: 40)
// create the button properly!
Button.setTitle(key, for: [])
Button.setTitleColor(.blue, for: [])
Button.setTitleColor(.lightGray, for: .highlighted)
Button.titleLabel?.font = UIFont(name: "Avenir-Book", size: 20 )
return Button
}
@objc func buttonClicked( _ sender: UIButton!)
{
print("button \(sender.currentTitle) tapped")
let indexPath = IndexPath(row: sender.tag, section: 0)
//menuTableView.scrollToRow(at: indexPath, at: UITableView.ScrollPosition.top, animated: true)
}
}