4

無限スクロールビューを設定し、コンテンツオフセットが0に達したら、コンテンツオフセットを最大に設定します。その逆も同様です。

すなわち

[scrollView setContentOffset:CGPointMake(0,0) animated:NO];

これは機能しますが、UIScrollViewの減速を停止します。

これを行う方法はありますが、UIScrollViewを減速させ続けますか?

私はこれを試しました...

float declerationRate = scrollView.decelerationRate;
[scrollView setContentOffset:CGPointMake(scrollView.frame.size.width, 0) animated:NO];
scrollView.decelerationRate = declerationRate;

しかし、それは機能しませんでした。

編集

減速率は、減速の遅さ/速さを決定するための設定であることに気づきました。

必要なのは、scrollViewから現在の速度を取得することです。

4

4 に答える 4

2

そうです、私はアイデアを少し微調整する必要がありました。

UIScrollViewの速度を設定しようとするのは難しいことがわかりました...非常に難しいです。

とにかく、私はそれをちょっと微調整しました。

これは、他の人のSOの質問に答えて、自分で解決しようと思った後のミニプロジェクトです。

スワイプして矢印を回転させ、回転してポイントまで減速できるスピナーアプリを作成したいと思います。

私がしたことは、矢印が上を向くようにUIImageViewを設定することでした。

次に、UIImageViewをカバーするのはUIScrollViewです。

次に、コードで...

@interface MyViewController () <UIScrollViewDelegate>

@property (nonatomic, weak) IBOutlet UIScrollView *scrollView;
@property (nonatomic, weak) IBOutlet UIImageView *arrowView;

@end

@implementation MyViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    //make the content size really big so that the targetOffset of the deceleration will never be met.
    self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * 100, self.scrollView.frame.size.height);
    //set the contentOffset of the scroll view to a point in the center of the contentSize.
    [self.scrollView setContentOffset:CGPointMake(self.scrollView.frame.size.width * 50, 0) animated:NO];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)rotateImageView
{
    //Calculate the percentage of one "frame" that is the current offset.

    // each percentage of a "frame" equates to a percentage of 2 PI Rads to rotate
    float minOffset = self.scrollView.frame.size.width * 50;
    float maxOffset = self.scrollView.frame.size.width * 51;

    float offsetDiff = maxOffset - minOffset;

    float currentOffset = self.scrollView.contentOffset.x - minOffset;

    float percentage = currentOffset / offsetDiff;

    self.arrowView.transform = CGAffineTransformMakeRotation(M_PI * 2 * percentage);
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    //the scrollView moved so update the rotation of the image
    [self rotateImageView];
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    //the scrollview stopped moving.
    //set the content offset back to be in the middle
    //but make sure to keep the percentage (used above) the same
    //this ensures the arrow is pointing in the same direction as it ended decelerating

    float diffOffset = scrollView.contentOffset.x;

    while (diffOffset >= scrollView.frame.size.width) {
        diffOffset -= scrollView.frame.size.width;
    }

    [scrollView setContentOffset:CGPointMake(scrollView.frame.size.width * 50 + diffOffset, 0) animated:NO];
}

@end

これにより、Wheel of Fortuneのように、どちらの方向にも無限に回転するスピナーの望ましい効果が得られます。

ただし、欠陥があります。ユーザーが回転を停止せずに回転し続けると、停止する前にどちらの方向にも50回転します。

于 2013-01-31T19:38:17.720 に答える
1

コメントで述べたように、あなたがしている方法は期待される結果を生み出すことです、あなたが望むことをする一つの方法はコンテンツオフセットを一番上に設定することですが、コンテンツサイズの高さと減速値を使用することでアニメーション化できますコンテンツオフセットをもう一度確認してください:https ://stackoverflow.com/a/6086521/662605

正しいと感じる前に、いくつかの数学を試してみる必要がありますが、これは合理的な回避策だと思います。

減速度が小さいほど、アニメーション(時間)が長くなり、アニメーション(距離)が長くなります。どう考えているか教えてください。

あなたが言ったように、減速はおそらくあなたが必要とする唯一のものではありません。したがって、contentOffsetでKVOを試して、0.5秒以上の平均速度を計算し、おそらく速度を把握することができます。

于 2013-01-31T18:45:13.630 に答える
0

これを行うには、おそらくいくつかの異なる方法があります。UIScrollView理想的には、残りの減速物理学をシミュレートしたり、内部を混乱させたりするために、いかなる種類の計算も行う必要はありません。これはエラーが発生しやすく、UIScrollView誰もが慣れている物理学と完全に一致する可能性は低いです。

代わりに、スクロールビューがジェスチャの単なるドライバである場合(つまり、実際には何も表示する必要がない場合)、非常に広いスクロールビューを使用するのが最善だと思います。初期コンテンツオフセットをコンテンツサイズの中央に設定します。でscrollViewDidScroll(_:)、トラバースされた画面幅のパーセンテージを計算します。

let pageWidth = scrollView.frame.width
let percentage = (scrollView.contentOffset.x % pageWidth) / pageWidth

これは基本的に、0.0から1.0(右に移動)またはから1.00.0左に移動)に何度もループします。これらの正規化された値を、それに応答できる他の関数に転送して、おそらくアニメーションを駆動することができます。0.0にジャンプしたり、にジャンプし1.0たり1.0するときにシームレスに見えるように、これに応答するコードを構造化するだけ0.0です。

もちろん、ループしているものを通常のスクロール表示速度よりも速くまたは遅くする必要がある場合は、画面幅の小さい部分または大きい部分を使用してください。私はそれを勝手に選んだ。

スクロール可能なコンテンツの端にぶつかるのが心配な場合は、スクロールビューが完全に残り1になったら、コンテンツのオフセットを同じ初期中心値に加えて、画面幅の残りの部分(またはあなたが何であれ)にリセットします。使用)スクロールビューは、スクロールを停止したときのものでした。

上記のリセットアプローチを考えると、表示されているコンテンツをホストしているスクロールビューの場合でも、リセットされたスクロールオフセットを考慮してビューフレーム/モデル値を更新する限り、無限にスクロールするビューを効果的に実現できます。


1これを適切にキャプチャするには、とを実装scrollViewDidEndDecelerating(_:)します。scrollViewDidEndDragging(_:willDecelerate:)後者の場合willDecelerateは、がである場合にのみ「完全なREST」関数を呼び出しますfalse。前者の場合は必ず呼んでください。

于 2016-12-27T22:09:07.307 に答える
0

あなたが電話すれば私はそれを見つけました

[scrollView setContentOffset:CGPointMake(0,0) animated:NO];

point(0,0)で、UIScrollViewのバウンスアクションがトリガーされ、減速が停止します。setContentOffsetコンテンツの境界を呼び出すときにも同じ状況が発生します。

したがってsetContentOffset、point(10,10)または他の場所に呼び出して、減速を簡単に維持できます。

于 2017-09-28T03:46:31.703 に答える