我有一个scrollview,或者实际上是一个UIWebView,它最初位于距其父视图顶部320px处。
当用户开始滚动时,我希望整个UIWebView向上跟随移动直到它到达顶部,然后webview应该开始正常滚动。我希望这发生在同一个手指运动中。 (也就是说,用户不需要抬起手指)。
我已经在UIWebView上使用UIPanGestureRecognizer实现了这一点(参见下面的代码)。手势处理程序移动UIWebView并不断将scrollview的contentOffset重置为0.它可以工作,但性能很差,特别是如果webview包含繁重的页面。我想这是webview的滚动和重置,使渲染变得沉重。我的解决方案闻起来很糟糕,我认为必须有更好的方法吗?
您是否知道有任何更好的解决方案可以实现我的目标?
@interface ViewController ()
@property (strong, nonatomic) IBOutlet UIWebView *webView;
@property (nonatomic, strong) UIPanGestureRecognizer *panGestureRecognizer;
@property(nonatomic, strong) UIScrollView *webViewScrollView;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *webViewTopMarginConstraint;
@end
@implementation ViewController {
BOOL gestureEnabled;
}
- (void)viewDidLoad
{
[super viewDidLoad];
gestureEnabled = YES;
// Initially put the webview 320 px down on the topview
self.webView.translatesAutoresizingMaskIntoConstraints = NO;
self.webViewTopMarginConstraint.constant = 320.0;
// SET UP GESTURE RECOGNIZER
_panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesturesForWebview:)];
_panGestureRecognizer.minimumNumberOfTouches = 1;
_panGestureRecognizer.maximumNumberOfTouches = 1;
_panGestureRecognizer.delegate = self;
[self.webView addGestureRecognizer:_panGestureRecognizer];
// Get hold of the webviews scrollview
for (UIView* subView in self.webView.subviews) {
if ([subView isKindOfClass:[UIScrollView class]]) {
_webViewScrollView = (UIScrollView *)subView;
}
}
// Load a web page in the webview
NSURLRequest *requestObj = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.macrumors.com"]];
[self.webView loadRequest:requestObj];
}
- (void)handlePanGesturesForWebview:(UIPanGestureRecognizer *)gesture {
if (gesture.state == UIGestureRecognizerStateChanged) {
CGFloat transY = [gesture translationInView:self.view].y; //transY will be negative by the number of pixels panned when panning upwards
if (gestureEnabled) {
// Move the whole webview according to gesture movement upwards
// todo Handle scrolling in the opposite direction
self.webViewTopMarginConstraint.constant = 320 + transY;
if (self.webViewTopMarginConstraint.constant <= 0.0) {
// The webview is at the top, disable the gesture recognizer
gestureEnabled = NO;
self.webViewTopMarginConstraint.constant = 0.0;
self.panGestureRecognizer.delegate = nil;
}
// "Rewind" the web scrolling
CGPoint offset = CGPointMake(0.0, 0.0);
[self.webViewScrollView setContentOffset:offset animated:NO];
}
}
}
#pragma mark UIGestureRecognizerDelegate impl
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
return YES;
}
@end
编辑:使用@JPHribovsek中的insets在接受的答案中建议完美。代码也变得更简单了。您可以在此处查看解决方案: http://gist.github.com/melke/8684172
答案 0 :(得分:1)
我认为在不移动滚动视图的情况下,您想要更简单地做的是设置内容插入
CGFloat top = 320.0;
self.webView.scrollView.contentInset = UIEdgeInsetsMake(top, 0.0, 0.0, 0.0);
请注意,您需要将部署目标设置为iOS5 +才能像这样获取滚动视图,而不是像您一样循环浏览子视图。
总体而言,您的viewDidLoad
方法会更简单,并且不需要手势识别器:
- (void)viewDidLoad
{
[super viewDidLoad];
CGFloat top = 320.0;
self.webView.scrollView.contentInset = UIEdgeInsetsMake(top, 0.0, 0.0, 0.0);
self.webview.scrollView.delegate = self;
// Load a web page in the webview
NSURLRequest *requestObj = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.macrumors.com"]];
[self.webView loadRequest:requestObj];
}
此外,根据您原始帖子中的一条评论,您似乎还在移动另一个视图以及滚动视图。 在这种情况下,您将需要跟踪滚动视图滚动委托,并相应地移动其他视图。根据其他视图的内容(例如,如果它只是一个imageView横幅类型的东西),我个人会发现调整大小/裁剪其他视图而不是将其移出屏幕更为优雅;但这应该是我猜的另一个问题。
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
CGFloat offsetY = scrollView.contentOffset.y;
//here whatever code you use to set that other view frame position
}