【问题标题】:How to remove previous stack of UIView after adding a new one?添加新的 UIView 后如何删除以前的 UIView 堆栈?
【发布时间】:2019-05-26 05:43:28
【问题描述】:

我想在每次向右滑动时添加一个新的子视图,但是如果我不破坏之前的子视图,它将堆叠很多次。我知道如何删除它,但我正在努力解决如何在我添加一个新的之后才删除它的逻辑。

我试过这个:

    var view1: UIView?
    var view2: UIView?
    var ctrl = false

    override func viewDidLoad() {
        super.viewDidLoad()

        view1?.addSubview(CustomView(frame: self.view.bounds))
    }

    func addView(){
        if let test1 = view1, let test2 = view2 {
            if ctrl == true {
                test1.addSubview(CustomView(frame: self.view.bounds))
                test2.removeFromSuperview()
                ctrl = false
            }else{
                test2.addSubview(CustomView(frame: self.view.bounds))
                test1.removeFromSuperview()
                ctrl = true
            }   
        }
    }

    @IBAction func swipeRight(_ sender: Any) {
        print("Right")
        UIView.animate(withDuration: 1, animations: {
            self.view.layer.backgroundColor = .black
        }){(isFinished) in
            self.addView()
            //I am hoping that after this the view stack before will be removed
        }
    }

CustomView 类是这样的:

var primaryColors: [UIColor] = [
    .red,
    .yellow,
    .blue]

class CustomView: UIView {

    override func draw(_ rect: CGRect) {
        super.draw(rect)
        primaryColors.shuffle()

        let leftRect = CGRect(x: 0, y: 0, width: rect.size.width/2, height: rect.size.height)
        primaryColors[0].set()
        guard let leftContext = UIGraphicsGetCurrentContext() else { return }
        leftContext.fill(leftRect)

        let rightRect = CGRect(x: rect.size.width/2, y: 0, width: rect.size.width/2, height: rect.size.height)
        primaryColors[1].set()
        guard let rightContext = UIGraphicsGetCurrentContext() else { return }
        rightContext.fill(rightRect)
    }
}

【问题讨论】:

  • 我猜你应该在第二个完成处理程序中添加视图,但在第一个完成处理程序中删除以前的视图。试一试。
  • 第二个完成处理程序和第一个完成处理程序是什么意思? @米希尔
  • UIView.animate() 中,您使用了 2 个闭包,或者只是第一个块和第二个块。还请阅读this 文章。它关于完成处理程序。
  • @Mihir 我明白你的建议,但我不知道为什么它不会添加然后删除,它只是不断删除视图,我希望它会先添加一个视图然后删除以前的,但由于视图没有改变,我认为它只是继续删除而不是先添加它。
  • 在您的代码view1?.addSubview(CustomView(frame: self.view.bounds)) 中,这一行将视图添加到 view1 并且您没有引用要添加的视图。您应该首先存储您添加的视图,例如view3 = CustomView(frame: self.view.bounds),以便稍后您可以删除 view3。此外,您的view1 实际上永远不会被添加如果我是对的,因为要添加view1,您需要先添加view.addSubview(view1)

标签: swift xcode uiview stack


【解决方案1】:

好吧,我不擅长 swift,但是在我了解您的问题之前,这应该可以解决。 如果不是这样,我很确定在 swift 方面做得更好的人会以更好的方式回答它。

每个ViewController 都有一个基础view,您可以像view.method() 一样访问它。

您将子视图添加到现有视图。

假设您要添加一个名为 view1 的新 UIView。

首先你像这样初始化它,

view1 = UIView(frame: view.bounds)

现在让它出现在屏幕上,点赞,

view.addSubview(view1)

此行将添加view1 作为view 的子视图。

现在view1 也在view 之上。所以现在当您触摸屏幕时,您正在访问的是view1。 所以下次你向右滑动时,手势识别器应该在view1

let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(swipeRightAction))
        swipeRight.direction = UISwipeGestureRecognizer.Direction.right

view1.addGestureRecognizer(swipeRight)

这就是您将向右滑动手势添加到 view1 的方式。

现在当你在屏幕上向右滑动时,swipeRightAction() 将被调用。

您可以从超级视图中删除此view1,例如,

view1.removeFromSuperView()

现在 view1 消失了,现在您可以通过与添加 view1 类似的过程添加 view2

看下面的代码,可能有关联。

//The old view that has to be replaced
    var viewToBeRemoved : UIView!

    //The new view that will replace the previous one
    var viewToBeAdded   : UIView!

    override func viewDidLoad() {
        super.viewDidLoad()

        replaceWithNewSwipableSubview()


    }


    func replaceWithNewSwipableSubview()
    {
        viewToBeAdded = UIView(frame: view.bounds)

        //New view being added should have a gesture so that next time
        //it need to be replaced we can swipe on it
        let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(swipeRightAction))
        swipeRight.direction = UISwipeGestureRecognizer.Direction.right

        viewToBeAdded.addGestureRecognizer(swipeRight)

        UIView.animate(withDuration: 1, animations: {

            //This will be animated

            if self.viewToBeRemoved != nil{

                //As there is no subview the very first time this func is called

                self.viewToBeRemoved.removeFromSuperview()

            }

            //Because next time it will be the view to be removed
            self.viewToBeRemoved = self.viewToBeAdded


        }) { (isFinished) in

            //This block gets executed only after
            //the block above has completed
            self.view.addSubview(self.viewToBeAdded)


            //view is the default base view of a ViewController

        }
    }



    @objc func swipeRightAction() {

        replaceWithNewSwipableSubview()

    }

在您的代码view1?.addSubview(CustomView(frame: self.view.bounds)) 中,这一行将视图添加到 view1 并且您没有引用您正在添加的视图。您应该首先存储您添加的视图,如 view3 = CustomView(frame: self.view.bounds),以便稍后您可以删除 view3。此外,您的 view1 实际上永远不会被添加如果我是对的,因为要添加 view1,您需要先添加 view.addSubview(view1)

如果您告诉我们您真正想要实现的目标,可能会提出更好的解决方案?

【讨论】:

  • 通过上面代码的视图调整,它确实有效。但现在出现另一个问题,我无法为背景颜色设置动画
  • Animate UIView background color swiftUIView.animate syntax for swift 4。这些将帮助您制作花腔动画。我只能帮助你,如果你通过这样做准确地告诉你想要做什么?你想交换 UIView 每次都获得不同的颜色吗?
【解决方案2】:

它可能无法正常工作。在您使用的 addSubview 方法的 if 条件下: if let test1 = view1, let test2 = view2 检查view1view2 不是nil。 这一定是失败的,因为您只在viewDidLoad() 中初始化了view1view1?.addSubview(CustomView(frame: self.view.bounds))。所以在上面 if 条件 view2 必须为零,因此它将评估为 false

尝试像这样放置你的 if 条件: if let test1 = view1 || let test2 = view2(检查语法是否出错,ll 将在 if 条件下使用 let 出错)。如果它不起作用,请告诉我。试试下面的代码:

if((self.view1 != nil) || (self.view2 != nil){
    if ctrl == true {
        self.view1?.addSubview(CustomView(frame: self.view.bounds))
        self.view2?.removeFromSuperview()
        ctrl = false
    }else{
        self.view2?.addSubview(CustomView(frame: self.view.bounds))
        self.view1?.removeFromSuperview()
        ctrl = true
    }   
 }

【讨论】:

  • 不知道为什么但是不能用"||"在 if 条件下
  • 知道,但我的 MacSystem 还没有。更新答案,试一试。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-10-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多