Программно добавлять кнопки, которые изменяют строку просмотра таблицы - PullRequest
0 голосов
/ 09 июля 2020

Моя цель - создать кнопки, показанные в зеленом поле. Это зеленое поле - это

@IBOutlet weak var categoryView: UIView!

ссылочный UIView. Я пытаюсь добавить кнопки, которые могут go, в разные категории, показанные ниже. В идеале я бы хотел, чтобы кнопки располагались по центру зеленого пространства с 10 ограничениями по бокам. Текущее «имя, как показано на карточке» было добавлено в ходе пробного запуска, чтобы убедиться, что мое представление стека применяется правильно. Следовательно, что-то должно быть не так с созданием кнопок. Однако я не уверен, насколько это неправильно. Потенциально я хотел бы сделать это представление произвольным и чтобы, если было много категорий, оно могло go выйти за пределы текущего представления. Любые советы приветствуются

Наконец, у меня есть несколько проблем при создании кнопки, есть только один прослушиватель onclick. Однако этот прослушиватель onclick имеет разные указатели, например, первая созданная кнопка go изменит представление на строку 0 таблицы (Аксессуары), а вторая должна go на Закуски, которая является строкой 1. и третья кнопка должна go для пустынь в строке 3. Et c.

data Ссылка

Данные, с которыми я работаю, выглядят следующим образом. Однако это зависит от извлечения бэкэнда и может каждый раз отличаться

> [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)

Категории выглядят так: String здесь - это Категории, а int здесь - это место, где оно расположено в таблице.

["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>>]

1 Ответ

1 голос
/ 10 июля 2020

Пара вещей ...

Вы допустили несколько ошибок при создании кнопок. Кроме того, если вы добавляете их в представление стека, не беспокойтесь о настройке их фреймов (которые в любом случае будут переопределены представлением стека).

Возможно, вам лучше использовать несколько разделов для представления таблицы .

Кнопки будут слишком широкими, чтобы уместиться, поэтому вы, вероятно, захотите поместить представление стека в представление прокрутки.

В любом случае, неясно, как вы анализируете и храните свои данные , поэтому я просто придумал пример. Предполагается, что ваш зеленый @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)
    }
    
}
...