设置集合视图的初始滚动位置

时间:2017-03-19 15:46:15

标签: ios swift uicollectionview

我尝试了很多解决方案,但没有一个能够解决问题。问题很简单 - 如何在没有视觉(跳跃)效果的viewDidLoadviewWillAppearviewDidAppear期间向下滚动?

我现在拥有的:

public override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    if (!self.layoutFlag) {

        if let lastCell: IndexPath = self.lastCellIndexPath {
            self.collectionView?.scrollToItem(at: lastCell, at: UICollectionViewScrollPosition.bottom, animated: true)
            self.layoutFlag = true
        }
    }
}

4 个答案:

答案 0 :(得分:2)

                <!-- Docs:
                        Maven plugin: http://cxf.apache.org/cxf-xjc-plugin.html
                        XJC: https://javaee.github.io/jaxb-v2/doc/user-guide/ch04.html
                        https://tech.boldare.com/make-jaxb-great-again/
                -->
                <plugin>
                    <groupId>org.apache.cxf</groupId>
                    <artifactId>cxf-xjc-plugin</artifactId>
                    <version>${version.cxf-xjc}</version>
                    <configuration>
                        <sourceRoot>${basedir}/target/generated-sources/main/java</sourceRoot>
                        <xsdOptions>
                            <xsdOption>
                                <extension>true</extension>
                                <xsd>${xsdsBaseDir}/someService/some-soap-service.xsd</xsd>
                                <!-- Args to XJC execution -->
                                <extensionArgs>
                                    <extensionArg>-XautoNameResolution</extensionArg>
                                    <extensionArg>-encoding</extensionArg><extensionArg>UTF-8</extensionArg>
                                </extensionArgs>
                            </xsdOption>
                            <xsdOption>
                                <!-- another XSD... -->
                            </xsdOption>
                        </xsdOptions>

                        <extensions>
                            <extension>org.apache.cxf.xjcplugins:cxf-xjc-wsdlextension:${version.cxf-xjc}</extension>
                            <extension>org.apache.cxf.xjcplugins:cxf-xjc-boolean:${version.cxf-xjc}</extension>
                            <extension>org.apache.cxf.xjcplugins:cxf-xjc-ts:${version.cxf-xjc}</extension>
                            <extension>org.apache.cxf.xjcplugins:cxf-xjc-dv:${version.cxf-xjc}</extension>
                            <extension>org.apache.cxf.xjcplugins:cxf-xjc-bug671:${version.cxf-xjc}</extension>
                            <extension>org.apache.cxf.xjcplugins:cxf-xjc-bug986:${version.cxf-xjc}</extension>
                            <extension>org.apache.cxf.xjcplugins:cxf-xjc-javadoc:${version.cxf-xjc}</extension>
                            <!--
                            -->
                        </extensions>
                    </configuration>
                    <executions>
                        <execution>
                            <id>generate-from-xsds</id><phase>generate-sources</phase><goals><goal>xsdtojava</goal></goals>
                        </execution>
                    </executions>
                </plugin>

只需将override func viewDidLoad() { super.viewDidLoad() DispatchQueue.main.async { self.collectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: false) } } 包装在异步块中即可。它运行完美,没有视觉过渡,易于应用。

它是如何工作的,我只能猜测。同步滚动viewDidLoad中的集合视图将不起作用,因为尚未进行布局。在异步块中提交滚动会将此操作添加到下一个runloop任务中,当下一个runloop执行时(恰好是绘制ui的时间),滚动会立即执行并显示在同一帧中。

以上只是一个猜测,任何人都有我很乐意学习的想法。

答案 1 :(得分:1)

我发现只有一种方法可以设置初始滚动位置:

viewDidLayoutSubviews

中调用我的滚动功能
var isScrolled = false

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    if !isScrolled && levelCollectionView.visibleCells.count > 0 {
        isScrolled = true
        // scroll
    }
}

它看起来不是正确的答案,但它有效

答案 2 :(得分:0)

签入测试项目,在viewWillAppear中工作。我添加了3个屏幕,1-st是干净的,第二个包含collectionView,最后一个是空的。

第二个屏幕的实现如下(viewWillAppear触发UIScrollView扩展方法并滚动内容):

class ViewController: UIViewController {

    @IBOutlet weak var collectionView: UICollectionView!

    override func viewDidLoad() {
        super.viewDidLoad()

        collectionView.dataSource = self
        collectionView.delegate = self
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        collectionView.scrollToBottom(animated: false)
    }
}

extension ViewController: UICollectionViewDelegate,
                          UICollectionViewDataSource {

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 200
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
        return cell
    }
}

这是滚动内容的extension

extension UIScrollView {
    func scrollToTop(animated: Bool) {
        setContentOffset(CGPoint(x: 0, y: -contentInset.top),
                         animated: animated)
    }

    func scrollToBottom(animated: Bool) {
        setContentOffset(CGPoint(x: 0, y: CGFloat.greatestFiniteMagnitude),
                     animated: animated)
    }
}

尝试制作new clean项目并使用它。

答案 3 :(得分:0)

将滚动添加到viewDidAppear(_:)方法的索引路径调用,并将animated参数设置为false

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    if !self.layoutFlag {
        if let lastCell: IndexPath = self.lastCellIndexPath {
            self.collectionView?.scrollToItem(at: lastCell, at: UICollectionViewScrollPosition.bottom, animated: false)
            self.layoutFlag = true
        }
    }
}

在向用户显示视图之前,应该将集合视图滚动到底部,因此没有&#34;跳转&#34;。