17

ページングが有効になってUISliderいる に読み込まれるビューの一部として があります。UIScrollView予期しない動作に気付きました。ユーザーがスライダーをすばやく使用しようとすると (つまり、押して動かす)、スクロール ビューが「アクティブ化」され、ページが切り替わります。ただし、1 秒間長押しすると、スライダーが「アクティブ」になり、スライダーの値を調整できます。この動作は望ましくありません。

UISliderにロードされたときにレスポンシブにする最良の方法は何UIScrollViewですか? スライダーの下に配置されたタッチイベントを食い尽くすだけの「ブロッカー」ビューを追加することを考えましたが、これが最善の方法であるかどうかはわかりません.

4

7 に答える 7

47

UIScrollViewサイドでのヒット テストは必要ありません。遅延はUIScrollViewそれ自体によって設定されるためです。カスタムのサブクラス化と実装は、hitTest:withEvent:まだ遅延してトリガーされるため、役に立ちません。

iOSアプリケーションスイッチャーでアップル独自のボリュームスライダーをシミュレートしたかったので、これに対するエレガントなソリューションを何時間も探しました。

トリック:

yourScrollView.delaysContentTouches = NO;

残念ながら、これはUISlidersトラックに沿ったイベントを無効にするため、この部分でUIScrollViewは、最初にスライダーによってキャッチされるため、タッチイベントをトリガーしません。

サム四角形以外の touchevents を渡すにはUISliders、サブクラスUISlider化して以下を追加する必要があります。

// get the location of the thumb
- (CGRect)thumbRect 
{
   CGRect trackRect = [self trackRectForBounds:self.bounds];
   CGRect thumbRect = [self thumbRectForBounds:self.bounds
                                  trackRect:trackRect
                                      value:self.value];
   return thumbRect;
}

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{   
   CGRect thumbFrame = [self thumbRect];

      // check if the point is within the thumb
   if (CGRectContainsPoint(thumbFrame, point))
   {
      // if so trigger the method of the super class
      NSLog(@"inside thumb");
      return [super hitTest:point withEvent:event];
   }
   else
   {
      // if not just pass the event on to your superview
      NSLog(@"outside thumb");
      return [[self superview] hitTest:point withEvent:event];
   }
}
于 2011-06-22T20:03:29.243 に答える
3

スクロール ビューに、スライダーが占める領域へのタッチを検出させます ( をオーバーライドしhitTest:withEvent:、 をサブクラス化する必要がある場合がありますUIScrollView)。上記の領域へのタッチが検出された場合は、スクロールビューにタッチをすぐにスライダーに渡すように指示します。

于 2011-01-05T02:24:57.580 に答える
2

これをコメントとして投稿したかったのですが、アカウントに担当者がいないため、回答全体を投稿する必要がありました。hitTest オーバーライドを含む user762391 の回答は完全に機能します。hitTest をオーバーライドする代わりに、次のように pointInside:withEvent: をオーバーライドすることもできます (thumbRect メソッドを保持します)。

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent * _Nullable)event {
    return CGRectContainsPoint([self thumbRect], point)
}

またはスウィフトで:

var thumbRect: CGRect {
    return thumbRectForBounds(bounds, trackRect: trackRectForBounds(bounds), value: value)
}

override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool {
    return thumbRect.contains(point)
}
于 2015-10-07T17:01:48.913 に答える
2

オーディオ プレーヤーを作成しているときに、に正確な問題がありsliderView、 に追加されました。これを避けるために、ユーザーが に触れたときの srcolling を無効にし、それ以外の場合はスクロールを有効にしました。scrollViewsliderViewscrollViewsliderViewscrollViewscrollViewsliderView

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {

    UIView *result = [super hitTest:point withEvent:event] ;
    if (result == sliderView)
    {
        scrollView.scrollEnabled = NO ;
    }
    else
    {
        scrollView.scrollEnabled = YES ;
    }

    return result ;

}
于 2013-11-19T06:52:47.850 に答える
0

UIScrollView をサブクラス化- (BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)viewし、次のようにメソッドをオーバーライドできます。

- (BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view {
    if ([view isKindOfClass:[UISlider class]]) {
        UITouch *touch = [[event allTouches] anyObject];
        CGPoint location = [touch locationInView:view];
        CGRect thumbRect;
        UISlider *mySlide = (UISlider*) view;
        CGRect trackRect = [mySlide trackRectForBounds:mySlide.bounds];
        thumbRect = [mySlide thumbRectForBounds:mySlide.bounds trackRect:trackRect value:mySlide.value];
        if (CGRectContainsPoint(thumbRect, location))
            return YES;
    }
    return NO;
}

yourScrollView.delaysContentTouches = NO;スクロールビューのプロパティも設定します。

于 2013-05-22T12:26:11.167 に答える