在 Swift 中为操作表在一行中创建多个按钮



我正在编写一个应用程序,用户可以从主页控制多个项目,并可以使用箭头按钮或菜单在它们之间切换。但是,我希望能够让用户通过菜单编辑项目的名称,以便当用户导航到菜单时,每一行都有与该行关联的项目的名称,并且在它的右侧有一个按钮可以拉出一个警报,让用户更改项目的名称。目前我正在使用操作表来生成项目,但我找不到在行上显示多个项目的方法。我生成操作表的代码如下:

@IBAction func tapMGName(_ sender: Any) {
let actionSheetController: UIAlertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
for index in 1...5{
let addMGSelectAction: UIAlertAction = UIAlertAction(title: "Mouthguard (index)", style: .default){action -> Void in
let mainStoryboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let SettingsViewController : UIViewController = mainStoryboard.instantiateViewController(withIdentifier: "SettingsViewController") as UIViewController
self.present(SettingsViewController, animated: false, completion: nil)
}
actionSheetController.addAction(addMGSelectAction)
}
let cancelAction: UIAlertAction = UIAlertAction(title: "Cancel", style: .destructive, handler: { (action) -> Void in })
actionSheetController.addAction(cancelAction)
self.present(actionSheetController, animated: true, completion: nil)
}

我希望菜单看起来像什么

不幸的是,您需要从头开始构建控制器。虽然这看起来令人生畏,但最难的部分是演示逻辑。之后,只需对每个 UI 用例的主类进行子类化,并在构建时为每个子类提供自己的逻辑。

以下是自定义警报控制器的最佳方法: https://gist.github.com/murphman300/4a56ace35d0ccdbf3a0c923b4ec7dc96

您在此处使用类似于此 gist 文件中的主类,请注意每个部分的注释。

然后当你对每种类型进行子类化时

//An example subclass of PopUpAlertController
class SpecificAlertControllerSubclass : PopUpAlertController {
override func set() {
super.set() //Good idea to call the super., since you might want to add basic stuff all the time, in that case you would do this in the original set() method, not here in the subclass' set() override.
//Here you add your own content.. that you instantiate in the subclass. The fact set() is being called in viewDidLoad() means you don't need to worry about calling it later on.
}
}
class TestController : UIViewController, PopUpAlertControllerDelegate {

var popup : SpecificAlertControllerSubclass?

func bringUpPopUp() {
popup = SpecificAlertControllerSubclass()
popup?.delegate = self
present(popup!, animated: true) { 
print("Popup Presented")
}
}

/*
The Delegate methods you will always need to consider when using it.
*/
func popUp(controller: PopUpAlertController, didDismiss withInfo: Any?) {
if let pop = popup, controller == pop {
//checks if the delegated controller is popup..
popup = nil
let info = withInfo != nil ? String(describing: withInfo!) : "unknown"
print("Dismissed PopUp, with reason: (info)")
}
}
func popUp(controller: PopUpAlertController, selected item: [String : Any]?) {
//Here is where you would handle the user selecting one of your options. Dismissing the popup andPresenting another controller. or if you want the popup subclass to handle the logic and the next controller, you don't call this method, but handle it in the subclass object.
}
}

因此,这将以与UIAlertControllers相同的方式弹出一个视图。但是,它的外观完全取决于您。使用此类时要记住的某些事项:

设置
  1. 弹出视图在设置覆盖中的初始位置。
  2. set()覆盖中:始终记住您正在将子视图添加到popUp的观点,不是view.当然,您可以将弹出窗口重命名为 随心所欲..
  3. 如果要更改控制器的表示形式,则需要 以更改子类(而不是主类(中的覆盖和表示变量。那 保持一般方式不变以便快速重复使用,但您的 具体用例仍然是可区分的。
  4. 我发现覆盖viewDidAppear如果在 子类级别,原因与上一点相同。你 可以在那里插入单独的演示方法。
  5. 要更改关闭动画,您必须覆盖 方法本身,无需在重写中调用 super。

第 3 点和第 4 点意味着SpecificAlertControllerSubclass变成这样的东西:

class SpecificAlertControllerSubclass : PopUpAlertController {
override func set() {
super.set() //Good idea to call the super., since you might want to add basic stuff all the time, in that case you would do this in the original set() method, not in the subclasses.
//Here you add your own content..
modalPresentationStyle = //which ever one you want
modalTransitionStyle = //which ever one you want
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .allowAnimatedContent, animations: {
self.view.backgroundColor = UIColor.black.withAlphaComponent(0.5)
self.popUp.alpha = 1
}) { (v) in
}
}
}

就像第二个委托方法的注释所解释的那样,在我看来,您需要决定哪个控制器应处理操作逻辑,具体取决于您在按下这些操作时是否提供新的控制器,或者您是否只是切换 UI。在后面的情况下,可以将PopUpAlertControllerprotocol中的 didSelect 方法设置为可选方法。这里有一个关于代表的好教程。

我还将弹出窗口的alpha设置为0,这是针对您的用例,即中央屏幕淡入效果。当然,如果您希望弹出窗口滑入,您可以在set()覆盖中更改该 alpha 值。如果您还想要动画中的幻灯片,则只需在set()覆盖中设置弹出窗口的初始位置,并将其动画化到您希望它在viewDidAppear覆盖中显示的位置。因此,从这一点来看,这种方法确实需要您跟踪如何在子类中更改主类的属性,但是,当您掌握它的窍门时,这一切的可定制性非常整洁。

从这里,你几乎可以做任何你想做的事情。只需记住在选择操作时处理弹出窗口的 UI 过渡,以确保过渡顺利等。

至于你想要的样子。我认为您最好的方法是使用具有全长边框的UITableViewUICollectionView。您应该委托您在PopUpAlertController中决定的任何一个,使用它们各自的didSelectItemAt方法解释选择方法,并调用PopUpAlertControllerDelegatepopUp(controller: PopUpAlertController, didDismiss withInfo: Any?)。这将允许您为每一行设置自定义图标。

这里有一个关于UICollectionView的很好的教程,以编程方式完成: https://www.youtube.com/watch?v=3Xv1mJvwXok&list=PL0dzCUj1L5JGKdVUtA5xds1zcyzsz7HLj

最新更新