开发者

UIScrollView scroll vertically by touch and horizontally programmatically

开发者 https://www.devze.com 2023-03-12 16:06 出处:网络
I have looked on stackoverflow, but unable to find an answer that exactly answers my question. If I missed something, please point me to the correct question.

I have looked on stackoverflow, but unable to find an answer that exactly answers my question. If I missed something, please point me to the correct question.

Here is my scenario --

I originally had a case where my vertical window size was set, so it was easy for me to restrict scrolling completely simply by doing this --

CGRect scrollContainer = CGRectMake(0, 0, 320, 440);
self.baseView = [[UIScrollView alloc] initWithFrame:scrollContainer];
self.baseView.contentSize = CGSizeMake(6400, 440);
self.baseView.bounces = NO;
self.baseView.pagingEnabled = NO;
self.baseView.scrollE开发者_JAVA百科nabled = NO;

Based on the movement of the phone, I was then able to scroll programmatically --

CGPoint scrollOffset = CGPointMake(x*20, 0);
[self.baseView setContentOffset:scrollOffset];

In my new requirement, the vertical content increases drastically so I would have the contentSize like so

self.baseView.contentSize = CGSizeMake(6400, 4400);

I still want to scroll horizontally programmatically, but give the user the ability to scroll ONLY vertically by touch. So, I'm assuming I would have to say scrollEnabled = YES. But this lets the user scroll in both directions.

Do I have to capture touch events and override them ? How would I recognize if it was a horizontal scroll or a vertical scroll? What happens if its a diagonal scroll action?

I'm a bit clueless at this point, so any input would be greatly appreciated.


You would probably be able to do this by nesting two UIScrollViews.

The inner scroll view would have contentSize of the actual content and its actual dimensions would be screen width and the same height as contentSize with scrolling disabled.

The outer scroll view would have it's contentSize be the same as the outer scroll view's dimensions and it's actual dimensions would be the screen dimensions with scrolling enabled.

This way the user can scroll up and down on the outer view while you control the horizontal offset programmatically with the inner view.

It's a little complex but at least you don't have to subclass. :D

(Also will only work with iOS 3.0+) but that doesn't seem to be a problem)

[See "Scroll View Programming Guide for iOS" section on "Nesting Scroll Views"]


You can use a UISwipeGestureRecognizer to recognize a series of touch events as a vertical or horizontal swipe.

// ensure that automatic scrolling is not enabled
scrollView.scrollEnabled = NO;

UISwipeGestureRecognizer *swipeRecognizer = [[UISwipeGestureRecognizer alloc] 
                                           initWithTarget:self 
                                           action:@selector(handleGesture:)];
swipeRecognizer.direction = UISwipeGestureRecognizerDirectionUp | UISwipeGestureRecognizerDirectionDown;
[scrollView addGestureRecognizer:swipeRecognizer];
[swipeRecognizer release];

In your handleGesture: method, you can now adjust the scrollOffset appropriately. Read up on UIGestureRecognizer for more details.


I also think two scrollViews is the answer here. If you don't want to nest them, link their data in the controller:

There is one scrollView that holds your content and has user interaction disabled, let's call it contentScrollView, and one invisible scrollView of the same size on top, interactionScrollView. In the delegate-controller for both, implement

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    if (scrollView == interactionScrollView)
    {
        CGPoint offset = CGPointMake(yourProgrammaticallySetHorizontalOffset,interactionScrollView.contentOffset.y);
        [contentScrollView setContentOffset:offset];
    }
}

You can also link zooming in this way.


Another possibility, since you probably don't really need horizontal scrolling, you just want to set the content's offset:

Put your contentView into a scrollView normally, but set the scrollView's contentSize as CGPointMake(scrollView.size.width,content.size.height). This means the scrollView won't ever scroll horizontally.

Now, from your code, you can shift the content around horizontally: content.frame = CGRectOffset(content.frame, yourPreferredOffset, 0).

I haven't tested this, but I thnk it's gonna work, and only needs one scrollView. You could also put that frame changing stuff into an animation to make it look like a scroll (which it is) instead of a sudden content change.

0

精彩评论

暂无评论...
验证码 换一张
取 消