簡體   English   中英

如果UIButton框架平移,則它不會更改

[英]UIButton frame doesn't change if its panned

這是我嘗試制作的一個簡單APP的圖像

該應用程序具有用於中心紫色按鈕的平移手勢識別器,如果該按鈕與四個橙色按鈕中的任意一個相交,則該按鈕在移動時會移動,該紫色按鈕會進行動畫處理並在與之交界的按鈕范圍內移動,否則會動畫化回到初始起始位置即中心。

第一次平移紫色按鈕時,按鈕的框架會更新,但是如果我第二次嘗試,按鈕的框架將保持不變(當它位於視圖中心時的值)。

我猜想這是我缺少的與“自動版式”相關的內容,因為如果我取消了紫色中心按鈕的約束,則每次平移時幀都會正確更新。

有人可以解釋約束動畫時我要記住的幾點嗎

這是我用於處理平移手勢的代碼:

@objc func handleCenterRectPan(_ pannedView: UIPanGestureRecognizer) {

        let fallBackAnimation = UIViewPropertyAnimator(duration: 0.3, dampingRatio: 0.5) {
                if self.button1.frame.intersects(self.centerRect.frame) {
                    self.centerRect.center = self.button1.center
                } else if self.button2.frame.contains(self.centerRect.frame) {
                    self.centerRect.center = self.button2.center
                } else if self.button3.frame.contains(self.centerRect.frame) {
                    self.centerRect.center = self.button3.center
                } else if self.button4.frame.contains(self.centerRect.frame) {
                    self.centerRect.center = self.button4.center
                } else {
                    // no intersection move to original position
                    self.centerRect.frame = OGValues.oGCenter
                }
        }

        switch pannedView.state {
        case .began:
            self.centerRect.center = pannedView.location(in: self.view)
        case .changed:
            print("Changed")
            self.centerRect.center = pannedView.location(in: self.view)
        case .ended, .cancelled, .failed :
            print("Ended")
            fallBackAnimation.startAnimation();
            //snapTheRectangle()
        default:
            break
        }
    }

首先,如果您的目標是平穩地移動視圖,則不應施加任何限制。 而且,如果您無法抵抗約束,則必須繼續更新約束而不是框架(中心),在您的代碼中,我假設您已給出了紫色按鈕中心約束,然后隨着用戶使用平移手勢。 問題是給您的約束仍然處於活動狀態,並且在布局需要更新時會嘗試立即將其重新設置。

所以你可以做的是

不要給出限制,因為它在用戶拖動時需要自由移動

要么

為約束創建IBoutlet,並在用戶拖動時將.isActive設置為false,如果它不在其他任何按鈕內,則將其設置為true,並更新UpdateLayoutIfNeeded,這樣它將返回到原始位置。 (好的方法)

@IBOutlet var horizontalConstraints: NSLayoutConstraint!            
@IBOutlet var verticalConstraints: NSLayoutConstraint!

//make active false as the user is dragging the view
horizontalConstraints.isActive = false
verticalConstraints.isActive = false
self.view.layoutIfNeeded()

//make it true again if its not inside any of the other views 
horizontalConstraints.isActive = true
verticalConstraints.isActive = true
self.view.layoutIfNeeded()

要么

當用戶移動視圖時,更新constraints.constant以獲取水平和垂直約束(這不是一個好的方法),如果不在其他任何視圖內,請再次將其設為零

//make it true again if its not inside any of the other views 
horizontalConstraints.constant = change in horizontal direction
verticalConstraints..constant =  change in vertical direction
self.view.layoutIfNeeded()

編輯正如你所說的限制是零設置后isActive = false,因為isActive其實做的就是添加和刪除那些約束蘋果的醫生說什么

激活或停用約束將在視圖上調用addConstraint( :)和removeConstraint( :),該視圖是此約束管理的項目的最接近的共同祖先。 使用此屬性,而不是直接調用addConstraint( :)或removeConstraint( :)。

因此,使約束成為強引用確實可以解決問題,但我認為為IBOutelet設置強引用不是一個好主意,而以編程方式添加和刪除約束則更好。 查看此問題解除約束

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM