عرض iPhone UiwebView لا يتناسب بعد عملية التكبير + تغيير UiInterfaceorientation

StackOverflow https://stackoverflow.com/questions/2890673

سؤال

لقد قمت بإنشاء تطبيق iPhone عاري مع uiwebview (صفحة المقاييس لتناسب = نعم ، يجب أن يكون ذلك https://stackoverflow.com/

يوضح تدوير الجهاز أن UIWEBView محدد تلقائيًا لتناسب العرض. جيد.

غير صحيح: التكبير في الصفحة والتصغير. تدور الجهاز الآن يعرض Uiwebview في عرض غريب في أحد الاتجاهات (إذا كان u Zoom في المناظر الطبيعية ، فإن عرض الصورة غريب والعكس صحيح). يتم إصلاح هذا السلوك فقط عند الانتقال إلى صفحة أخرى.

صحيح: تحميل نفس عنوان URL في Safari المتنقلة. الأعمال الدوارة والعرض يناسب بغض النظر عن تمرين التكبير.

هل هذا خطأ uiwebview (ربما لا)؟ أم أن هناك شيء يجب القيام به لجعل الأشياء "تعمل فقط" كما هو الحال في Safari المتنقلة؟

هل كانت مفيدة؟

المحلول

لقد وجدت شيئًا كان يعمل بالنسبة لي. المشكلة هي أنه عندما يغير UIWEBView محتويات الويب الخاصة به ، تكون محتويات الويب الخاصة بها تتناسب مع منفذ العرض. لكن معلمة ZoomScale من Scrollview Subview لم يتم تحديثها بشكل صحيح (ولا يتم تحديث الحد الأدنى

ثم نحتاج إلى القيام بذلك يدويًا في 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;
    }
}

جرب هذا الرمز ، فإنه يغير بشكل كبير مستوى التكبير (1.01) للسماح لـ UIWebview بزيادة حجم المحتوى في وضع المناظر الطبيعية

FindScrollViewInsideView: تمت إضافة الطريقة لدعم iOS4

أنا أنشر هذا لأنني واجهت أيضًا نفس المشكلة وهنا أتابع M Penades يقترب.M Penades إجابة woks جيدة فقط للحالة إذا كان المستخدم لا يشوه (قرصة) عرض الويب ثم قم بتدوير الجهاز وكرر هذه العملية. ثم يتم تقليل حجم المحتوى من UIWebView تدريجياً. لذلك كانت هذه هي المشكلة M Penades إجابه. لذلك قمت بإصلاح هذه المشكلة أيضًا ورمزتي كما هو موضح أدناه.

1) لهذا ، قمت بتعيين إيماءة قرصة بحيث عندما يتمكن المستخدم من التحقق من الحجم المقيس لـ 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);
}

إذا قام المستخدم بقرص/خارج عرض الويب في هذه الحالة ، فما عليك سوى تعيين عامل التكبير هذا. بحيث يمكن أن يعدل WebView المحتويات مع تغير Oreintaion.

- (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 دون كسر القواعد.

أولاً ، نحتاج إلى الحصول على uiscrollview من Uiwebview:

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;
    }
}

الآن يصبح في حالة من الفوضى.

نحتاج إلى تتبع الدوران ، لذلك ستحتاج إلى إضافة هذا إلى LoadDiddload أو 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 ، سيتم استدعاء. السبب في تأخير الأداء لمدة 0.0 ثانية هو أننا نريد استدعاء AdguntWithZoomData على Runloop التالي. إذا قمت بتسميتها مباشرة ، فسيتم ضبط AdjustWithZoomData للاتجاه السابق.

فيما يلي طريقة AdjustWithZoomdata:

- (void)adjustWithZoomData{
    UIScrollView *sview = [[webView subviews] objectAtIndex:0];
    [sview setZoomScale:zoomData animated:YES];
    [sview setContentOffset:zoomOffset animated:YES]; 
    [sview setContentSize:zoomContentSize];
    updateZoomData = YES;
}

هذا هو! الآن عند تدويره ، سيحافظ على التكبير ، ويحافظ على الإزاحة الصحيحة تقريبًا. إذا كان أي شخص يريد القيام بالرياضيات حول كيفية الحصول على الإزاحة الصحيحة الدقيقة ، فاذهب لذلك!

كنت أبحث في هذا بنفسي واكتشفت المزيد من المعلومات:

المشكلات عند تغيير التكبير:

  1. غالبًا ما لا يعيد Safari إعادة رسمها بشكل صحيح (إن وجدت) على الرغم من تغير مستوى التكبير.
  2. تغيير العرض يجبر إعادة الطلاء.
  3. قد تعتقد أن العرض = عرض الجهاز في المشهد سيستخدم 1024 ولكن يبدو أنه يستخدم 768 (الشاشة. يحدث العرض أيضًا).

على سبيل المثال ، إذا كان العرض الحالي هو 1024 وتريد التكبير من 1 إلى 1.5 في المناظر الطبيعية ، يمكنك:

  • تغيير الجمع بين العرض والتكبير على سبيل المثال العرض إلى 2048 وتكبير إلى 0.75
  • تغيير العرض إلى 1023 (الاسم المستعار القبيح؟)
  • تغيير العرض ليقول 1023 ، ثم السطر التالي مرة أخرى إلى 1024 (إعادة طلاء مزدوج ، ولكن على الأقل تم إعادة طلاء النافذة).

على ما يبدو ، لم أستخدم الحل بواسطة M Penades في النهاية (ونسيت تحديث هذا المنشور! آسف).

ما فعلته هو تغيير حجم المستند بأكمله (وتغيير حجم الخط الخاص بي للحفاظ على الأشياء متناسبة). هذا على ما يبدو إصلاح القضية.

ومع ذلك ، فإن UIWEBView الخاص بي هو فقط لتحميل HTML & CSS الخاص بي من نظام ملفات iOS - إذا كنت تقوم بإنشاء متصفح ويب للأغراض العامة ، فقد لا تعمل هذه الخدعة أيضًا.

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; }

جوهر في https://gist.github.com/d6589584944685909ae5

عند الدوران ، حاول تعيين ZoomScale Scrollview إلى 0. انظر إجابتي الكاملة هنا: محتوى UIWEBView لم يتم ضبطه على إطار جديد بعد الدوران

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top