【问题标题】:Remove UIWebView Shadow?删除 UIWebView 阴影?
【发布时间】:2010-11-07 15:24:00
【问题描述】:

有谁知道是否可以删除放置在 UIWebView 窗口上的阴影?

示例:http://uploadingit.com/files/1173105_olub5/shadow.png

如果可以的话,你是怎么做到的?

谢谢

【问题讨论】:

标签: iphone uiwebview shadow


【解决方案1】:

这是“尼古拉磷虾”解决方案的更清洁替代品。这只会隐藏 UIWebView 中的 UIImageViews 而不是 UIWebBrowserView。

for (UIView *view in [[[webView subviews] objectAtIndex:0] subviews]) { 
  if ([view isKindOfClass:[UIImageView class]]) view.hidden = YES;
}   

谢谢 詹姆斯

【讨论】:

  • 有人已经通过 appStore 验证流程了吗?
  • 是的,我创建的一个应用程序使用了这个代码,并在星期一第一次完成了验证过程。
  • 经过测试,我猜这个方案只适用于iOS 4.x?
  • 感谢 Martin,我在 2010 年发表的评论是因为当时的 3.x 兼容性原因;)
  • 要保留滚动条指示器,请使用此代码:if([wview isKindOfClass:[UIImageView class]] && wview.frame.size.width != 7) { wview.hidden = YES; },而不是此答案中的 if 语句。
【解决方案2】:

小for循环非常危险,因为如果苹果更改子视图的数量,它可能会崩溃。

这样它至少不会在发生变化时崩溃:

if ([[webView subviews] count] > 0)
{
    for (UIView* shadowView in [[[webView subviews] objectAtIndex:0] subviews])
    {
        [shadowView setHidden:YES];
    }

    // unhide the last view so it is visible again because it has the content
    [[[[[webView subviews] objectAtIndex:0] subviews] lastObject] setHidden:NO];
}

【讨论】:

  • 当 Apple 决定在 UIWebView 中放置零个子视图时,它确实会崩溃。
【解决方案3】:

选择器 setAllowsRubberBanding: 有一个私有方法,它采用 BOOL 值。如果通过 NO,您将无法将 web 视图滚动到内容区域的顶部或底部,但仍然可以让您正常滚动 web 视图。不幸的是,这种方法是私有的,如果您使用它,您的应用可能不会被允许进入商店。

但是,您可以尝试提取方法实现并将其绑定到您创建的不同选择器,使用 Objective-C 运行时的动态特性。

不过,该方法是私有的,并且可能不再存在于操作系统的未来版本中。如果您仍想尝试,这里有一些示例代码将提取 setAllowsRubberBanding: 方法实现并为您调用它。

static inline void ShhhDoNotTellAppleAboutThis (UIWebView *webview)
{
    const char *hax3d = "frgNyybjfEhooreOnaqvat";
    char appleSelName[24];

    for (int i = 0; i < 22; ++i)
    {
        char c = hax3d[i];
        appleSelName[i] = (c >= 'a' && c <= 'z') ? ((c - 'a' + 13) % 26) + 'a' : ((c - 'A' + 13) % 26) + 'A';
    }
    appleSelName[22] = ':';
    appleSelName[23] = 0;

    SEL appleSEL = sel_getUid(appleSelName);

    UIScrollView *scrollView = (UIScrollView *)[webview.subviews objectAtIndex:0];
    Class cls = [scrollView class];
    if (class_respondsToSelector(cls, appleSEL) == NO)
    {
        return;
    }

    IMP func = class_getMethodImplementation(cls, appleSEL);
    func(scrollView, appleSEL, NO);
}

请注意,如果您选择使用此代码向 AppStore 提交应用程序,Apple 的静态分析器可能仍会捕获此问题。

【讨论】:

    【解决方案4】:

    这是一个 Swift 函数,它可以消除 iOS 9 中 UIWebView 中的阴影。它比我在 SO 上看到的任何替代方法都更安全,因为其中的所有内容都在 Apple 文档中,并且它专门改变了 shadow 属性(如反对隐藏整个视图或视图的某些其他属性)。

    func removeShadow(webView: UIWebView) {
        for subview:UIView in webView.scrollView.subviews {
            subview.layer.shadowOpacity = 0
            for subsubview in subview.subviews {
                subsubview.layer.shadowOpacity = 0
            }
        }
    }
    

    您始终可以访问UIView(documentation) 的子视图属性。每个UIView 都有一个layer 属性,即CALayer (documentation)。每个CALayer 都有shadowOpacity (documentation)。

    注意事项:

    1. 根据您的情况,您可能需要更深入地通过子视图导航视图层次结构。
    2. 只要您不希望 Web 视图控制器中的任何位置出现任何阴影,此方法就可以工作。如果您有一个想要保留阴影的视图(默认的 UIWebView 阴影除外),那么您可以添加一个 if-check 来识别该视图,并且不将该视图的图层 shadowOpacity 设置为零。
    3. 根据 Apple “对于在 UIKit 和其他系统框架中声明的复杂视图,视图的任何子视图通常被认为是私有的,并且随时可能更改。因此,您不应尝试检索或修改这些类型的系统提供的视图的子视图。如果这样做,您的代码可能会在未来的系统更新期间中断”。 . .换句话说,UIWebView 可以更改,不建议深入这些子视图。然而,深入 UIWebView 是摆脱阴影的唯一方法,这是一种相对安全的方法。

    【讨论】:

      【解决方案5】:

      这可以在不使用私有 API 的情况下完成。您需要做的就是隐藏每个带有阴影的 UIImageView。代码如下:

      for (int x = 0; x < 10; ++x) {
          [[[[[webView subviews] objectAtIndex:0] subviews] objectAtIndex:x] setHidden:YES];
      }
      

      【讨论】:

      • 如果没有子视图,这可能会崩溃
      • 这对我们有用,谢谢!但是,如果 Apple 的代码发生变化怎么办?让我烦恼的是,如果您想要格式化文本,建议您使用 UIWebView...但是 UIWebView 看起来不一样!
      • 天哪...永远不要在不透明的视图层次结构中假设这种东西!
      【解决方案6】:

      试试这个

      func webViewDidFinishLoad(_ webView: UIWebView) {
          for shadowView in self.webView.scrollView.subviews {
              if !shadowView.isKind(of: UIImageView.self) {
                  shadowView.subviews[0].layer.shadowColor = UIColor.clear.cgColor
              } else {
                  shadowView.layer.shadowColor = UIColor.clear.cgColor
              }
          }
      }
      

      【讨论】:

        【解决方案7】:

        遍历所有子view,图片只有1像素宽的UIImageView是阴影图片,可以隐藏。

        - (void)hideShadows {
            [webview traverseViewsWithBlock:^(UIView *view) {
                UIImageView *imgView = ([view isKindOfClass:[UIImageView class]] ? (UIImageView*)view : nil;
                // image views whose image is 1px wide are shadow images, hide them
                if (imgView && imgView.image.size.width == 1) {
                    imgView.hidden = YES;
                }
            }];
        }
        

        traverseViewsWithBlock 看起来像这样:

        - (void)traverseViewsWithBlock:(void (^)(UIView* view))block
        {
            block(self);
            for (id subview in self.subviews) {
                [subview traverseViewsWithBlock:block];
            }
        }
        

        【讨论】:

          【解决方案8】:

          我查看了类属性并没有找到任何东西,但我可以想到两种“掩盖”策略:

          1.您可以使用另一个视图(父的 web 视图)来剪裁 webview 边界。
          2. 您可以在 webview 顶部添加另一个视图,以使用与背景匹配的颜色覆盖所需区域,您可以使用uiimage,中间有一个透明区域。

          顺便说一句,我不喜欢这种标准的表格视图背景:P,但改变它可能会让人头疼:P

          【讨论】:

            【解决方案9】:

            你必须小心,滚动指示器也是 UIImageViews。 我会改进我的代码,但这里有一个基本的子类解决方案:

            http://forrst.com/posts/A_tiny_UIWebView_hack_remove_shadows_from_behi-gzH

            【讨论】:

              【解决方案10】:

              隐藏滚动指示器和透明 Web 视图的最简单方法here in UIWebView

              移除卷轴。

                  for(UIView *view in webView.subviews){   
                       if ([view isKindOfClass:[UIScrollView class]]) {  
                            UIScrollView *sView = (UIScrollView *)view;  
                            //to hide verticalScroller  
                            sView.showsVerticalScrollIndicator = NO;
                            sView.showsVerticalScrollIndicator = NO;
                       }   
                  }  
              

              【讨论】:

                【解决方案11】:

                UIWebView 上的类别是这样的:

                - (BOOL)showsScrollShadows
                {
                    for(UIImageView *imageView in [self imageViewsWithShadows])
                    {
                        if(imageView.hidden)
                        {
                            return NO;
                        }
                
                        break;
                    }
                
                    return YES;
                }
                
                - (void)setShowsScrollShadows:(BOOL)showsScrollShadows
                {
                    [[self imageViewsWithShadows] makeObjectsPerformSelector:@selector(setHidden:) withObject:@(!showsScrollShadows)];
                }
                
                - (NSArray *)imageViewsWithShadows
                {
                    NSArray *potentialShadowImageViews = (self.subviews.count > 0) ? [self.subviews[0] subviews] : nil;
                
                    if(potentialShadowImageViews.count > 0)
                    {
                        NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings)
                        {
                            return [evaluatedObject isKindOfClass:[UIImageView class]];
                        }];
                
                        return [potentialShadowImageViews filteredArrayUsingPredicate:predicate];
                    }
                
                    return nil;
                }
                

                【讨论】:

                  【解决方案12】:

                  我环顾四周,看不到任何与之相关的东西。除了用视图掩盖它或以某种方式对其进行剪裁之外,我唯一能想到的就是循环遍历所有 UIWebView 子视图(和子子视图等),看看你是否可以在那里看到任何东西!

                  【讨论】:

                    【解决方案13】:

                    我可能错了,但我认为只有在我们滚动 webview 时才会出现阴影,不是吗? 在这种情况下,您是要阻止滚动还是真正隐藏阴影?我不知道有什么技巧可以隐藏阴影。要禁用滚动,我会将 UserInteractionEnabled 设置为 NO。

                    【讨论】:

                      【解决方案14】:

                      我向 UIView 对象添加了一个递归方法作为类别,以便它对方法的接收视图的子视图进行深度优先遍历,隐藏它找到的任何 UIImageView 子类。如果没有子视图,它不会崩溃。 -apply: 方法来自BlocksKit。您可以重写此函数以不使用它,但该块并行应用于接收数组的每个元素,因此速度非常快。

                      @implementation UIView (RemoveShadow)
                      
                      - (void)removeShadow {
                        if (self.subviews.count == 0 && [self isKindOfClass:[UIImageView class]]) {
                          self.hidden = YES;
                        } else if (self.subviews.count > 0) {
                          [self.subviews apply:^(id sender) {
                            [(UIView *)sender removeShadow];
                          }];
                        }
                      }
                      
                      @end
                      

                      【讨论】:

                        【解决方案15】:
                        if (UIDevice.currentDevice.systemVersion.intValue < 7)
                            for (UIImageView *imageView in webView.scrollView.subviews)
                                if ([imageView isKindOfClass:[UIImageView class]] && imageView.image.size.width == 1)
                                    imageView.hidden = YES;
                        

                        【讨论】:

                          猜你喜欢
                          • 2012-01-18
                          • 2015-06-12
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 2016-08-17
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          相关资源
                          最近更新 更多