缩放操作 + uiinterfaceorientation更改后,iPhone uiwebview宽度不适合
-
04-10-2019 - |
题
我创建了一个带有UIWebView的Bare Bones iPhone应用程序(fit fit = YES,showerautorotatetointerfaceorientation = yes)并加载了一个网页,例如 https://stackoverflow.com/
旋转设备表明UIWebView是自动固定的,以适合宽度。好的。
不正确: :放大页面并缩小。现在,旋转设备在一个方向之一中以怪异的宽度显示uiwebview(如果您在景观中放大,肖像宽度很奇怪,反之亦然)。仅当您导航到另一页时,此行为才能修复。
正确的: :在移动野生动物园中加载相同的URL。旋转作品和宽度适合不管进行缩放练习。
这是一个UIWebView错误(可能不是)吗?还是需要做一些事情才能使事情像移动野生动物园一样“正常工作”?
解决方案
我找到了对我有用的东西。问题在于,当UiWebView更改其方向的Web内容时,将与视口拟合。但是ScrollView子视图的ZoomScale参数未正确更新(也没有更新的最低ZoomScale或MaximumZoomScale
然后我们需要在 willRotateToInterfaceOrientation
:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
CGFloat ratioAspect = webview.bounds.size.width/webview.bounds.size.height;
switch (toInterfaceOrientation) {
case UIInterfaceOrientationPortraitUpsideDown:
case UIInterfaceOrientationPortrait:
// Going to Portrait mode
for (UIScrollView *scroll in [webview subviews]) { //we get the scrollview
// Make sure it really is a scroll view and reset the zoom scale.
if ([scroll respondsToSelector:@selector(setZoomScale:)]){
scroll.minimumZoomScale = scroll.minimumZoomScale/ratioAspect;
scroll.maximumZoomScale = scroll.maximumZoomScale/ratioAspect;
[scroll setZoomScale:(scroll.zoomScale/ratioAspect) animated:YES];
}
}
break;
default:
// Going to Landscape mode
for (UIScrollView *scroll in [webview subviews]) { //we get the scrollview
// Make sure it really is a scroll view and reset the zoom scale.
if ([scroll respondsToSelector:@selector(setZoomScale:)]){
scroll.minimumZoomScale = scroll.minimumZoomScale *ratioAspect;
scroll.maximumZoomScale = scroll.maximumZoomScale *ratioAspect;
[scroll setZoomScale:(scroll.zoomScale*ratioAspect) animated:YES];
}
}
break;
}
}
希望这可以帮助!
其他提示
我已经尝试了M Penades的解决方案,这似乎也对我有用。
我遇到的唯一问题是,在3GS上运行此操作时,不幸的是,旋转不是很好。
因此,我现在使用另一种方法:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
CGFloat scale = browserWebView.contentScaleFactor;
NSString *javaStuff = [NSString stringWithFormat:@"document.body.style.zoom = %f;", scale];
[browserWebView stringByEvaluatingJavaScriptFromString:javaStuff];
}
最好的祝福,
拉尔夫
- (UIScrollView *)findScrollViewInsideView:(UIView *)view
{
for(UIView *subview in view.subviews){
if([subview isKindOfClass:[UIScrollView class]]){
return (UIScrollView *)subview;
}
UIScrollView *foundScrollView = [self findScrollViewInsideView:subview];
if (foundScrollView){
return foundScrollView;
}
}
return nil;
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
switch (self.interfaceOrientation){
case UIInterfaceOrientationLandscapeLeft:
case UIInterfaceOrientationLandscapeRight:
{
UIScrollView *webViewScrollView = ([self.webView respondsToSelector:@selector(scrollView)])
? self.webView.scrollView
: [self findScrollViewInsideView:self.webView];
[webViewScrollView setZoomScale:1.01f animated:YES];
}
break;
default:
break;
}
}
尝试此代码,它微不足道地更改Zoom级别(1.01)以允许UIWebView在景观模式下增加内容大小
FINDSCROLLVIEWINEDEVIEW:添加以支持IOS4的方法
我之所以发布此信息,是因为我也面临着同样的问题,在这里我关注 M Penades
方法。M Penades
仅如果用户不偏斜(捏出)WebView然后旋转设备并重复此过程。然后UIWebView的内容大小逐渐减小,则可以将其答案wok有好处。所以这就是问题 M Penades
回答。因此,我也解决了这个问题,我的代码如下。
1)为此,我设置了捏手势,以便用户偏斜时,UIWebView可以检查UIWebView的缩放大小。 //一个,请导入 UIGestureRecognizerDelegate
“ .h文件”中的协议
//call below method in ViewDidLoad Method for setting the Pinch gesture
- (void)setPinchgesture
{
UIPinchGestureRecognizer * pinchgesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(didPinchWebView:)];
[pinchgesture setDelegate:self];
[htmlWebView addGestureRecognizer:pinchgesture];
[pinchgesture release];
// here htmlWebView is WebView user zoomingIn/Out
}
//Allow The allow simultaneous recognition
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
保证返回是可以同时识别。不能保证返回否可以防止同时认可,因为另一个手势的代表可以返回是
-(void)didPinchWebView:(UIPinchGestureRecognizer*)gestsure
{
//check if the Scaled Fator is same is normal scaling factor the allow set Flag True.
if(gestsure.scale<=1.0)
{
isPinchOut = TRUE;
}
else// otherwise Set false
{
isPinchOut = FALSE;
}
NSLog(@"Hello Pinch %f",gestsure.scale);
}
如果用户hase捏入/输出在这种情况下的Web视图,则只需设置该缩放因子即可。因此,随着Oreintaion的更改,WebView可以调整其内容化。
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
//Allow the Execution of below code when user has Skewed the UIWebView and Adjust the Content Size of UiwebView.
if(isPinchOut){
CGFloat ratioAspect = htmlWebView.bounds.size.width/htmlWebView.bounds.size.height;
switch (toInterfaceOrientation) {
case UIInterfaceOrientationPortraitUpsideDown:
case UIInterfaceOrientationPortrait:
// Going to Portrait mode
for (UIScrollView *scroll in [htmlWebView subviews]) { //we get the scrollview
// Make sure it really is a scroll view and reset the zoom scale.
if ([scroll respondsToSelector:@selector(setZoomScale:)]){
scroll.minimumZoomScale = scroll.minimumZoomScale/ratioAspect;
scroll.maximumZoomScale = scroll.maximumZoomScale/ratioAspect;
[scroll setZoomScale:(scroll.zoomScale/ratioAspect) animated:YES];
}
}
break;
default:
// Going to Landscape mode
for (UIScrollView *scroll in [htmlWebView subviews]) { //we get the scrollview
// Make sure it really is a scroll view and reset the zoom scale.
if ([scroll respondsToSelector:@selector(setZoomScale:)]){
scroll.minimumZoomScale = scroll.minimumZoomScale *ratioAspect;
scroll.maximumZoomScale = scroll.maximumZoomScale *ratioAspect;
[scroll setZoomScale:(scroll.zoomScale*ratioAspect) animated:YES];
}
}
break;
}
}
}
这对于用户偏向UIWebView的功能也非常有效。
我有解决这个问题的方法,但我必须说我不是这个问题的忠实拥护者。它效果很好,但是解决方案实际上会导致另一个问题。我对次要问题有修复,但这需要一些努力。
请记住,由于OS3.2或IOS4(不确定哪个)UIWebView的直接子视图现在是UISCrollView而不是UISCroller,因此我们可以对此做更多的事情。另外,由于访问视图的子视图不是私人操作,因此也没有使用将其铸造为已记录的视图的子视图,我们可以在不违反规则的情况下使用UIWebView做很多事情。
首先,我们需要从uiwebview获得uiscrollview:
UIScrollView *sview = [[webView subviews] objectAtIndex:0];
现在,我们需要更改此scrollview的委托,以便我们可以覆盖scrollview委托呼叫(这实际上可能是由于此解决方案而导致次要错误的原因,我将在片刻中分享):
sview.delegate = self;
现在,如果您在这一点上尝试,则缩放被打破了。我们需要实现UISCrollViewDelegate方法来修复它。添加:
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
UIView *webBrowserView = [[scrollView subviews] objectAtIndex:10];
return webBrowserView;
}
WebBrowserview实际上是UIWebBrowserview,但这不是记录的类,因此我们将其视为Uiview。
现在运行您的应用程序,放大,然后缩放网页。旋转,应该正确显示。
这确实会导致一个相当大的错误,这可能比原始的更糟糕。
如果您放大然后旋转,您将松开滚动能力,但是您的视图将被放大。这是完成整个过程的修复程序。
首先,我们需要跟踪几个数字,并定义一个标志:
我在h文件中定义了这些:
BOOL updateZoomData;
float zoomData; //this holds the scale at which we are zoomed in, scrollView.zoomScale
CGPoint zoomOffset; //this holds the scrollView.contentOffset
CGSize zoomContentSize; //this holds the scrollView.contentSize
您可能会认为您可以从UISCROLLVIEW中获取这些数字,但是当您需要它们时,它们会更改,因此我们需要将它们存储在其他地方。
我们需要使用另一种委托方法:
- (void)scrollViewDidZoom:(UIScrollView *)scrollView{
if(updateZoomData){
zoomData = scrollView.zoomScale;
zoomOffset = scrollView.contentOffset;
zoomContentSize = scrollView.contentSize;
}
}
现在我感到一团糟。
我们需要跟踪旋转,因此您需要将其添加到ViewDidload,LoadView或用于注册通知的任何方法:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(webViewOrientationChanged:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
并创建此方法:
- (void)webViewOrientationChanged:(NSNotification *)notification{
updateZoomData = NO;
[self performSelector:@selector(adjustWithZoomData) withObject:nil afterDelay:0.0];
}
因此,现在只要您旋转WebVieworientationChange。 performelector延迟0.0秒的原因是因为我们要在下一个Runloop上调用AdvichZoomData。如果您直接调用它,则调整WithZoomData将调整以前的方向。
这是AdvistwithZoomData方法:
- (void)adjustWithZoomData{
UIScrollView *sview = [[webView subviews] objectAtIndex:0];
[sview setZoomScale:zoomData animated:YES];
[sview setContentOffset:zoomOffset animated:YES];
[sview setContentSize:zoomContentSize];
updateZoomData = YES;
}
就是这样!现在,当您旋转时,它将保持变焦,并大致保持正确的偏移。如果有人想对如何获得正确的正确偏移进行数学,那就去吧!
我本人正在研究这个,发现了更多信息:
更改Zoom时的问题:
- 即使变焦级别更改,Safari通常也无法正确重新粉刷(如果有的话)。
- 更改宽度迫使重新粉刷。
- 您会认为宽度=景观中的设备宽度将使用1024,但它似乎使用了768(屏幕。
例如,如果当前宽度为1024,并且您想在景观中从1缩放到1.5,则可以:
- 将宽度和变焦的组合更改为2048,并缩放为0.75
- 将宽度更改为1023(丑陋的别名?)
- 更改宽度为1023,然后将下一行回到1024(双重重新粉刷,但至少要重新粉刷窗口)。
因此,显然我最终没有使用M Penades的解决方案(并且忘了更新此帖子!对不起)。
我所做的是调整整个文档的大小(并更改我的字体大小以保持比例)。这显然解决了问题。
但是,我的UIWebView仅用于从iOS文件系统中加载自己的HTML&CSS-如果您要构建通用网络浏览器,则此技巧可能无法正常工作。
ViewController.m
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
switch (toInterfaceOrientation) {
case UIInterfaceOrientationPortraitUpsideDown:
case UIInterfaceOrientationPortrait:
if ((UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)) {
[webview stringByEvaluatingJavaScriptFromString:@"document.body.className = 'ppad'"];
} else {
[webview stringByEvaluatingJavaScriptFromString:@"document.body.className = 'pphone'"];
}
break;
default:
if ((UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)) {
[webview stringByEvaluatingJavaScriptFromString:@"document.body.className = 'lpad'"];
} else {
[webview stringByEvaluatingJavaScriptFromString:@"document.body.className = 'lphone'"];
}
break;
}
}
和app.css
html>body.pphone { font-size:12px; width: 980px; }
html>body.lphone { font-size:18px; width: 1470px; }
html>body.ppad { font-size:12px; width: 768px; }
html>body.lpad { font-size:15.99999996px; width: 1024px; }
旋转时,尝试将ScrollView ZoomScale设置为0。请参阅我的完整答案: 旋转后未调整到新框架的UIWebView内容