基于平移手势翻译的滚动scrollview

如何解决基于平移手势翻译的滚动scrollview

我想知道如何将平移手势 y 转换为等效于滚动视图内容 y 的偏移量。

因此,在此我可以通过平移手势转换来滚动我的滚动视图,从而再现自然滚动视图滚动的相同效果。

let scrollYOffset: CGFloat = panGesture.translation(in: view).y

当我这样做时,由于scrollYOffset值从0更改为54,然后在拖动时变为124,因此滚动非常混乱。

我想要的是使用平移手势流畅自然地滚动滚动视图。

您可能会问为什么我不使用自然的滚动视图及其委托-

func scrollViewDidScroll(_ scrollView: UIScrollView)

答案是我正在尝试构建一个应用程序,使用户可以在屏幕上拖动对象,并且其后面的滚动视图应该滚动那么多。

任何人都可以帮助我将平移手势 y 转换为滚动视图 y 内容偏移。

任何帮助将不胜感激。谢谢。

解决方法

方法translation:返回上一次迭代与当前迭代之间的差异,因此您应将翻译添加到现有结果中,诸如此类。

     @objc private func handleGesture(panGestureRecognizer: UIPanGestureRecognizer) {
         switch panGestureRecognizer.state {
         case .begin:
            break
         case .changed:
            let translation = panGestureRecognizer.translation(in: self.view)
            panGestureRecognizer.setTranslation(.zero,in: self.view)

            let newYOffset = currentOffset + translation.y
         case .ended:
            break
         }
     }
,

有多种方法可获取“平滑的可拖动视图” ---但出于您的目的,可能的选择是使用UISlider

enter image description here

如果需要,可以通过设置拇指和轨迹图像来更改滑块的外观。

示例代码(用于该屏幕截图)

class SliderScrollViewController: UIViewController,UIScrollViewDelegate {
    
    let scrollView: UIScrollView = UIScrollView()
    let slider: UISlider = UISlider()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        [scrollView,slider].forEach {
            view.addSubview($0)
            $0.translatesAutoresizingMaskIntoConstraints = false
        }

        // horizontal stack view to hold scroll content
        let stack = UIStackView()
        stack.distribution = .fillEqually
        stack.spacing = 8
        stack.translatesAutoresizingMaskIntoConstraints = false

        // add 20 views to the stack view for horizontal scrolling
        for i in 1...20 {
            let v = UILabel()
            v.textAlignment = .center
            v.backgroundColor = .yellow
            v.text = "View \(i)"
            stack.addArrangedSubview(v)
        }
        stack.arrangedSubviews.first?.widthAnchor.constraint(equalToConstant: 120).isActive = true
        scrollView.addSubview(stack)
        
        let g = view.safeAreaLayoutGuide
        let svCLG = scrollView.contentLayoutGuide
        let svFLG = scrollView.frameLayoutGuide
        
        NSLayoutConstraint.activate([

            scrollView.topAnchor.constraint(equalTo: g.topAnchor,constant: 20.0),scrollView.leadingAnchor.constraint(equalTo: g.leadingAnchor,scrollView.trailingAnchor.constraint(equalTo: g.trailingAnchor,constant: -20.0),scrollView.heightAnchor.constraint(equalToConstant: 120.0),slider.topAnchor.constraint(equalTo: scrollView.bottomAnchor,slider.leadingAnchor.constraint(equalTo: g.leadingAnchor,slider.trailingAnchor.constraint(equalTo: g.trailingAnchor,stack.topAnchor.constraint(equalTo: svCLG.topAnchor,constant: 8.0),stack.leadingAnchor.constraint(equalTo: svCLG.leadingAnchor,stack.trailingAnchor.constraint(equalTo: svCLG.trailingAnchor,constant: -8.0),stack.bottomAnchor.constraint(equalTo: svCLG.bottomAnchor,stack.heightAnchor.constraint(equalTo: svFLG.heightAnchor,constant: -16.0),])
        
        slider.addTarget(self,action: #selector(self.sliderChanged(_:)),for: .valueChanged)
        
        // so we can see the frame of the scroll view
        scrollView.backgroundColor = .green
        
        // set scrollView delegate
        scrollView.delegate = self
    }
    
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        // we need to update the slider position when scroll view is manually scrolled
        let w = scrollView.contentSize.width - scrollView.frame.size.width
        let pct = scrollView.contentOffset.x / w
        slider.value = Float(pct)
    }

    @objc func sliderChanged(_ sender: UISlider) -> Void {
        // set scroll view's content offset x based on position of slider
        let w = scrollView.contentSize.width - scrollView.frame.size.width
        let x = w * CGFloat(sender.value)
        scrollView.contentOffset.x = x
    }
    
}

修改

我想再多做些...本示例以UIImage的形式获取滚动视图的内容,将其用于滑块后面的“背景”图像,并为滑块的拇指:

enter image description here

enter image description here

完整代码:

class SliderScrollViewController: UIViewController,UIScrollViewDelegate {
    
    let scrollView: UIScrollView = UIScrollView()
    let scrollContentView: UIView = UIView()
    let slider: UISlider = UISlider()
    let sliderBKG: UIImageView = UIImageView()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        [scrollView,sliderBKG,slider].forEach {
            view.addSubview($0)
            $0.translatesAutoresizingMaskIntoConstraints = false
        }
        
        // horizontal stack view to hold scroll content
        let stack = UIStackView()
        stack.distribution = .fillEqually
        stack.spacing = 8
        stack.translatesAutoresizingMaskIntoConstraints = false
        
        // add 20 views to the stack view for horizontal scrolling
        for i in 1...20 {
            let v = UILabel()
            v.textAlignment = .center
            v.backgroundColor = UIColor(red: 0.0,green: 1.0,blue: 1.0 - (CGFloat(i) * 0.05),alpha: 1.0)
            v.text = "View \(i)"
            stack.addArrangedSubview(v)
        }
        stack.arrangedSubviews.first?.widthAnchor.constraint(equalToConstant: 120).isActive = true
        
        scrollContentView.translatesAutoresizingMaskIntoConstraints = false
        scrollContentView.addSubview(stack)
        scrollView.addSubview(scrollContentView)
        
        let g = view.safeAreaLayoutGuide
        let svCLG = scrollView.contentLayoutGuide
        let svFLG = scrollView.frameLayoutGuide
        
        NSLayoutConstraint.activate([
            
            scrollView.topAnchor.constraint(equalTo: g.topAnchor,slider.heightAnchor.constraint(equalToConstant: 40.0),sliderBKG.topAnchor.constraint(equalTo: slider.topAnchor,constant: 6.0),sliderBKG.leadingAnchor.constraint(equalTo: slider.leadingAnchor,constant: 0.0),sliderBKG.trailingAnchor.constraint(equalTo: slider.trailingAnchor,sliderBKG.bottomAnchor.constraint(equalTo: slider.bottomAnchor,constant: -6.0),scrollContentView.topAnchor.constraint(equalTo: svCLG.topAnchor,scrollContentView.leadingAnchor.constraint(equalTo: svCLG.leadingAnchor,scrollContentView.trailingAnchor.constraint(equalTo: svCLG.trailingAnchor,scrollContentView.bottomAnchor.constraint(equalTo: svCLG.bottomAnchor,scrollContentView.heightAnchor.constraint(equalTo: svFLG.heightAnchor,stack.topAnchor.constraint(equalTo: scrollContentView.topAnchor,stack.leadingAnchor.constraint(equalTo: scrollContentView.leadingAnchor,stack.trailingAnchor.constraint(equalTo: scrollContentView.trailingAnchor,stack.bottomAnchor.constraint(equalTo: scrollContentView.bottomAnchor,for: .valueChanged)
        
        // set slider images to clear images
        slider.setThumbImage(UIImage(),for: [])
        slider.setMinimumTrackImage(UIImage(),for: [])
        slider.setMaximumTrackImage(UIImage(),for: [])
        
        // so we can see the frame of the scroll view
        scrollView.backgroundColor = .green
        scrollContentView.backgroundColor = .orange
        
        // set scrollView delegate
        scrollView.delegate = self
        
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        // after view has appeared (so we know auto-layout has finished)
        // grab the content of the scroll view as a UIImage
        let img = scvSnapshot()
        // set it to the "background" image view behind the slider
        sliderBKG.image = img
        updateThumbImage()
    }
    override func viewWillTransition(to size: CGSize,with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size,with: coordinator)
        coordinator.animate(alongsideTransition: { _ in
        },completion: {
            _ in
            self.updateThumbImage()
        })
    }
    func updateThumbImage() -> Void {
        // generate a proportional width bordered clear image
        let w = self.scrollView.frame.width * (self.scrollView.frame.width / self.scrollView.contentSize.width)
        let rect = CGRect(origin: .zero,size: CGSize(width: w,height: 40.0))
        let renderer = UIGraphicsImageRenderer(size: rect.size)
        let img = renderer.image { rc in
            rc.cgContext.setFillColor(UIColor.clear.cgColor)
            rc.cgContext.setStrokeColor(UIColor.red.cgColor)
            rc.cgContext.setLineWidth(2)
            rc.cgContext.addRect(rect)
            rc.cgContext.drawPath(using: .fillStroke)
        }
        // set the slider's custom thumb image
        self.slider.setThumbImage(img,for: [])
    }
    func scvSnapshot() -> UIImage {
        let renderer = UIGraphicsImageRenderer(bounds: scrollContentView.bounds)
        return renderer.image { rendererContext in
            scrollContentView.layer.render(in: rendererContext.cgContext)
        }
    }
    
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        // we need to update the slider position when scroll view is manually scrolled
        let w = scrollView.contentSize.width - scrollView.frame.size.width
        let pct = scrollView.contentOffset.x / w
        slider.value = Float(pct)
    }
    
    @objc func sliderChanged(_ sender: UISlider) -> Void {
        // set scroll view's content offset x based on position of slider
        let w = scrollView.contentSize.width - scrollView.frame.size.width
        let x = w * CGFloat(sender.value)
        scrollView.contentOffset.x = x
    }
    
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)> insert overwrite table dwd_trade_cart_add_inc > select data.id, > data.user_id, > data.course_id, > date_format(
错误1 hive (edu)> insert into huanhuan values(1,'haoge'); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive> show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 <configuration> <property> <name>yarn.nodemanager.res