22

私は一連のロゴを宣伝している「画像ティッカー」を作成するために UICollectionView を使用しているプロジェクトに取り組んでいます。collectionView は高さ 1 アイテム、長さ 12 アイテムで、一度に 2 ~ 3 アイテムを表示します (表示されるロゴのサイズによって異なります)。

最初のアイテムから最後のアイテムまで、ゆっくりとした自動スクロール アニメーションを作成してから繰り返したいと思います。

誰もこれを機能させることができましたか?を使用してスクロールを機能させることができます

[myCollection scrollToItemAtIndexPath:[NSIndexPath indexPathForRow:(myImages.count -1) inSection:0] atScrollPosition:UICollectionViewScrollPositionRight animated:YES];

しかし、これは速すぎる!

[UIView animateWithDuration:10 delay:2 options:(UIViewAnimationOptionAutoreverse + UIViewAnimationOptionRepeat) animations:^{
    [myCollection scrollToItemAtIndexPath:[NSIndexPath indexPathForRow:(myImages.count -1) inSection:0] atScrollPosition:UICollectionViewScrollPositionRight animated:NO];
} completion:nil];

これにより、必要なスクロール速度が得られますが、シリーズの最後の数セルしか表示されません。それら(および最初の可視セルでさえ)がすぐにキューから取り出されているのではないかと思います。

何かご意見は?

4

5 に答える 5

17

このアプローチを試すことができます:

@property (nonatomic, assign) CGPoint scrollingPoint, endPoint;
@property (nonatomic, strong) NSTimer *scrollingTimer;
@synthesize scrollingPoint, endPoint;
@synthesize scrollingTimer;

- (void)scrollSlowly {
    // Set the point where the scrolling stops.
    self.endPoint = CGPointMake(0, 300);
    // Assuming that you are starting at {0, 0} and scrolling along the x-axis.
    self.scrollingPoint = CGPointMake(0, 0);
    // Change the timer interval for speed regulation. 
    self.scrollingTimer = [NSTimer scheduledTimerWithTimeInterval:0.015 target:self selector:@selector(scrollSlowlyToPoint) userInfo:nil repeats:YES];
}

- (void)scrollSlowlyToPoint {
    self.collectionView.contentOffset = self.scrollingPoint;
    // Here you have to respond to user interactions or else the scrolling will not stop until it reaches the endPoint.
    if (CGPointEqualToPoint(self.scrollingPoint, self.endPoint)) {
        [self.scrollingTimer invalidate];
    }
    // Going one pixel to the right.
    self.scrollingPoint = CGPointMake(self.scrollingPoint.x, self.scrollingPoint.y+1);
}
于 2012-10-29T20:52:37.543 に答える
14

「1 ピクセル オフセット」トリックを使用します。プログラムでスクロールするときは、端contentOffset.xを必要以上に 1 ピクセル多く/少なく設定してください。これは目立たないはずです。そして、完了ブロックで実際の値に設定します。そうすれば、早すぎるセルのデキューの問題を回避し、スムーズなスクロール アニメーションを得ることができます ;)

以下は、右ページへのスクロールの例です (たとえば、1 ページから 2 ページへ)。animations:ブロック内で、実際には 1 ピクセル少なくスクロールすることに注意してください( pageWidth * nextPage - 1)。completion:次に、ブロック内の正しい値を復元します。

CGFloat pageWidth = self.collectionView.frame.size.width;
int currentPage = self.collectionView.contentOffset.x / pageWidth;
int nextPage = currentPage + 1;

[UIView animateWithDuration:1
                      delay:0
                    options:UIViewAnimationOptionCurveEaseOut
                 animations:^{
                     [self.collectionView setContentOffset:CGPointMake(pageWidth * nextPage - 1, 0)];
                 } completion:^(BOOL finished) {
                     [self.collectionView setContentOffset:CGPointMake(pageWidth * nextPage, 0)];
                 }];
于 2014-04-09T17:43:46.247 に答える
10

UICollectionViewインデックスパスからインデックスパスに「ジャンプ」することなく、最後まで「ゆっくり」スクロールすることもできます。TVOSアプリのコレクション ビュー用にこれをすばやく作成しました。

func autoScroll () {
    let co = collectionView.contentOffset.x
    let no = co + 1

    UIView.animateWithDuration(0.001, delay: 0, options: .CurveEaseInOut, animations: { [weak self]() -> Void in
        self?.collectionView.contentOffset = CGPoint(x: no, y: 0)
        }) { [weak self](finished) -> Void in
            self?.autoScroll()
    }
}

で を呼び出すだけautoScroll()viewDidLoad()、あとは自分で処理します。スクロールの速度は、 のアニメーション時間によって決まりUIViewます。0ユーザースクロールで無効にできるように、代わりに秒を指定してNSTimerを追加できます(私は試していません) 。

于 2015-12-09T08:06:32.437 に答える
5

これを見つけた他の人のために、Masa の提案を Swift で動作するように更新し、最後に少し緩和を導入して、元の scrollItemsToIndexPath アニメーション呼び出しのように動作するようにしました。私の視界には何百ものアイテムがあるので、安定したペースは私にとって選択肢ではありませんでした.

var scrollPoint: CGPoint?
var endPoint: CGPoint?
var scrollTimer: NSTimer?
var scrollingUp = false

func scrollToIndexPath(path: NSIndexPath) {
    let atts = self.collectionView!.layoutAttributesForItemAtIndexPath(path)
    self.endPoint = CGPointMake(0, atts!.frame.origin.y - self.collectionView!.contentInset.top)
    self.scrollPoint = self.collectionView!.contentOffset
    self.scrollingUp = self.collectionView!.contentOffset.y > self.endPoint!.y

    self.scrollTimer?.invalidate()
    self.scrollTimer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: "scrollTimerTriggered:", userInfo: nil, repeats: true)
}

func scrollTimerTriggered(timer: NSTimer) {
    let dif = fabs(self.scrollPoint!.y - self.endPoint!.y) / 1000.0
    let modifier: CGFloat = self.scrollingUp ? -30 : 30

    self.scrollPoint = CGPointMake(self.scrollPoint!.x, self.scrollPoint!.y + (modifier * dif))
    self.collectionView?.contentOffset = self.scrollPoint!

    if self.scrollingUp && self.collectionView!.contentOffset.y <= self.endPoint!.y {
        self.collectionView!.contentOffset = self.endPoint!
        timer.invalidate()
    } else if !self.scrollingUp && self.collectionView!.contentOffset.y >= self.endPoint!.y {
        self.collectionView!.contentOffset = self.endPoint!
        timer.invalidate()
    }
}

dif と modifier の値を微調整すると、ほとんどの状況で持続時間/緩和レベルが調整されます。

于 2015-06-12T12:23:40.510 に答える
0

.h ファイルで、このタイマーを宣言します。

NSTimer *Timer;

このタイマーコードを配置し、

  [CollectionView reloadData];
  Timer = [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(AutoScroll) userInfo:nil repeats:YES];

それから、

#pragma mark- Auto scroll image collectionview
-(void)AutoScroll
{
    if (i<[Array count])
    {
        NSIndexPath *IndexPath = [NSIndexPath indexPathForRow:i inSection:0];
        [self.ImageCollectionView scrollToItemAtIndexPath:IndexPath
            atScrollPosition:UICollectionViewScrollPositionRight animated:NO];
        i++;
        if (i==[Array count])
        {
            i=0;
        }
    }
}

それが役に立つことを願っています。

于 2015-01-20T12:32:23.060 に答える