swift : UIView 的平滑翻译与 iOS 控制面板完全一样(跟随用户手指,使用平移)

Posted

技术标签:

【中文标题】swift : UIView 的平滑翻译与 iOS 控制面板完全一样(跟随用户手指,使用平移)【英文标题】:swift : smoothing translation of UIView exactly as iOS control panel (following user finger, using pan) 【发布时间】:2019-05-10 21:09:25 【问题描述】:

我想用手指从下到上移动 UIView,就像 ios 中的控制中心一样,尤其是与 iOS 中的控制中心“平滑”相同的移动(速度看起来有界,当速度很高时,没有需要用手指走很远才能使 UIView 移动到顶部等)。 我的问题是:我可以使用任何预设或库来代替自己进行自定义而不是精确的计算吗?我不太擅长制作这种“平滑”效果,也许 UIKit 提供了一些可以在 panGestureRecognizer 处理程序中使用的东西来平滑 sender.translation 之后的运动翻译?

现在我的gestureRecognizer处理程序是:

var y = sender.translation(in: view).y
let vy = sender.velocity(in: view).y

// we need to move constraintHeightInfoView.constant
// this is the height of my "ios control panel"

// i noticed the ios control panel move less if user tries 
// to move it out of screen bounds, so i'm first calculating 
// how much we are out of bound, in order to know "how much" 
// we will reduce velocity
var outofbound:CGFloat = 0
if(constraintHeightInfoView.constant < minH)

    outofbound = minH - constraintHeightInfoView.constant

else if(constraintHeightInfoView.constant > maxH)

    outofbound = constraintHeightInfoView.constant - maxH


// velocity target in pt/s
// i noticed the smooth effect in ios control panel includes 
// a velocity bound : if user pulls very fast the control panel, 
// it is not following the user finger, but it's a bit slower : 
// so there is a "vmax". When user release, i guess this vmax is 
// used for the final animation too 
let vtarget:CGFloat = 300 

print("\(y), \(vy), ofb : \(outofbound)")


// Here i'm lost : im trying to say : 
// if velocity above vtarget, reduce y so it match vtarget
if(abs(vy) > vtarget) 
    let dv = abs(vy) - vtarget
    y = // ????






switch sender.state 
    case .began, .changed :
    if case .began = sender.state 
        initialY = constraintHeightInfoView.constant
    

    let newH = (expandInfoViewInitialY ?? minH) - y

    constraintHeightInfoView.constant = newH

    view.layoutIfNeeded()

case .ended :

    let heightTo:CGFloat
    let blurAlpha:CGFloat
    // 250 is the middle between top position and 
    // bottom position : if velocity is high, dont need to pull 
    // a lot to proceed the final release animation
    // if vy is 3000, even very small movement proceed the 
    // animation. Otherwise, if very slow movement, 
    // user needs to go at least at the middle between top and bottom (250)
    if(constraintHeightInfoView.constant > 250 - (-vy/300) * 50)
    
        heightTo = maxH
        blurAlpha = 1
    
    else
    
        heightTo = minH
        blurAlpha = 0
    


    // time of animation depends on remaining distance to bottom/top
    let dy = abs(self.constraintHeightInfoView.constant - heightTo)


    var t = dy / vtarget

    print("end : d:\(dy), t:\(t)")
    UIView.animate(withDuration:TimeInterval(t), delay:0,options:[.curveEaseOut], animations :
        self.constraintHeightInfoView.constant = heightTo
        self.viewInfoBlurEffect.alpha = blurAlpha
        self.view.layoutIfNeeded()
    )

default :
    break

有了这一切,我的过渡仍然远不像 Apple 控制中心的那样......

【问题讨论】:

【参考方案1】:

如果您将其设置为一个从下到上、从上到下的动画,看起来就像您想要的那样,您将获得更令人满意的体验。现在“冻结”它并通过 UIViewPropertyAnimator 从平移手势识别器连接到它。这使它成为一个交互式动画

例如,如果用户拖动超过一定量,这将允许您“完成”动画。您将能够通过同一个动画师同时进行点击关闭和拖动关闭。

【讨论】:

不允许你索要第三方教程或示例,但是一旦你有“交互式动画”的概念,你会发现有很多示例。喜欢这个:github.com/nathangitter/interactive-animations 谢谢,我只是不知道“交互式动画”这个概念。您的链接看起来很棒我试图理解他们的代码。但似乎我仍然需要对大量的数学公式感到满意哈哈..

以上是关于swift : UIView 的平滑翻译与 iOS 控制面板完全一样(跟随用户手指,使用平移)的主要内容,如果未能解决你的问题,请参考以下文章

在 Swift 中平滑扩展 UIView 动画

iOS Swift - 动态增加 UITextView 和父 UIView 的高度

在 Swift 中动画自定义 UIView 属性

如何在 ios Swift 的 UIView 中左右设置阴影?

iOS - UIView操作(SWift)

iOS UIView头文件部分翻译