omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    Welcome!

    This is the community forum for my apps Pythonista and Editorial.

    For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.


    UI gaussian blur

    Pythonista
    6
    17
    9209
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • Webmaster4o
      Webmaster4o last edited by

      One of the major UI elements since iOS 7 is the large-radius gaussian blur behind a view. It's everywhere since iOS 7 /OS X 10.10. In ui, is there a way to make a view that blurs everything behind it in this way?

      Some examples from google images:

      1 Reply Last reply Reply Quote 1
      • omz
        omz last edited by

        Below is a little BlurView class I've written to wrap UIVisualEffectView in an easy-to-use ui.View subclass. For the style argument, you can pass 1 (extra light) 2 (light) or 3 (dark). You can also use this class in the UI editor. Simply add a custom view and set its class to BlurView. To set the style from the UI editor, you can put something like {'style': 2} in the "custom attributes" field.

        import ui
        from objc_util import *
        
        class BlurView (ui.View):
        	def __init__(self, style=1, *args, **kwargs):
        		ui.View.__init__(self, **kwargs)
        		self._style = style
        		self.effect_view = None
        		self.setup_effect_view()
        	
        	@on_main_thread
        	def setup_effect_view(self):
        		if self.effect_view is not None:
        			self.effect_view.removeFromSuperview()
        		UIVisualEffectView = ObjCClass('UIVisualEffectView')
        		UIBlurEffect = ObjCClass('UIBlurEffect')
        		frame = (self.bounds[:2], self.bounds[2:])
        		self.effect_view = UIVisualEffectView.alloc().initWithFrame_(frame).autorelease()
        		effect = UIBlurEffect.effectWithStyle_(self._style)
        		self.effect_view.effect = effect
        		self.effect_view.setAutoresizingMask_(18)
        		ObjCInstance(self).addSubview_(self.effect_view)
        	
        	@property
        	def style(self):
        		return self._style
        	
        	@style.setter
        	def style(self, value):
        		if value != self._style:
        			self._style = value
        			self.setup_effect_view()
        
        1 Reply Last reply Reply Quote 2
        • Webmaster4o
          Webmaster4o last edited by

          This is awesome! Thanks!

          1 Reply Last reply Reply Quote 1
          • Phuket2
            Phuket2 last edited by

            Ok, I didn't want to be the stupid one to ask this question, but I will. What's the usage of the class. Sorry, I don't get it from the text.
            Do you use create a custom class inheriting from BlurView, or do you add Blur view as a subview to a class?
            Sorry, its probably a silly question,

            1 Reply Last reply Reply Quote 2
            • omz
              omz last edited by

              @Phuket2 Basically, you just create a BlurView instance, and add it on top of the background you want to apply the blur effect on.

              Phuket2 1 Reply Last reply Reply Quote 1
              • Phuket2
                Phuket2 @omz last edited by

                @omz , ok thanks.
                Should it work if you already have a custom class that inherits from ui.View, then you change it to inherit from BlurView instead

                1 Reply Last reply Reply Quote 1
                • omz
                  omz last edited by

                  @Phuket2 Should be possible, but you must make sure to call BlurView.__init__ in your custom subclass.

                  1 Reply Last reply Reply Quote 0
                  • blmacbeth
                    blmacbeth last edited by

                    @omz I have been playing around with UIBlurView and UIVibrancyEffect, but have not been able to get the UIVibrancyEffect to work (text does not show up). Any suggestions on how to get it to work? I'm away from my iPad right now and can post some code later, if needed. But, my code is based on the following Objective-C code:

                    // Blur effect
                    UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
                    UIVisualEffectView *blurEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
                    [blurEffectView setFrame:self.view.bounds];
                    [self.view addSubview:blurEffectView];
                    
                    // Vibrancy effect
                    UIVibrancyEffect *vibrancyEffect = [UIVibrancyEffect effectForBlurEffect:blurEffect];
                    UIVisualEffectView *vibrancyEffectView = [[UIVisualEffectView alloc] initWithEffect:vibrancyEffect];
                    [vibrancyEffectView setFrame:self.view.bounds];
                    
                    // Label for vibrant text
                    UILabel *vibrantLabel = [[UILabel alloc] init];
                    [vibrantLabel setText:@"Vibrant"];
                    [vibrantLabel setFont:[UIFont systemFontOfSize:72.0f]];
                    [vibrantLabel sizeToFit];
                    [vibrantLabel setCenter: self.view.center];
                    
                    // Add label to the vibrancy view
                    [[vibrancyEffectView contentView] addSubview:vibrantLabel];
                    
                    // Add the vibrancy view to the blur view
                    [[blurEffectView contentView] addSubview:vibrancyEffectView];
                    

                    Thanks,
                    B

                    1 Reply Last reply Reply Quote 1
                    • omz
                      omz last edited by

                      @blmacbeth Here's an extended version of BlurView that includes support for vibrancy effects. The main function shows a little demo.

                      # coding: utf-8
                      
                      import ui
                      from objc_util import *
                      
                      class BlurView (ui.View):
                      	def __init__(self, style=1, *args, **kwargs):
                      		ui.View.__init__(self, **kwargs)
                      		self._style = style
                      		self.effect_view = None
                      		self.setup_effect_view()
                      	
                      	@on_main_thread
                      	def setup_effect_view(self):
                      		if self.effect_view is not None:
                      			self.effect_view.removeFromSuperview()
                      		UIVisualEffectView = ObjCClass('UIVisualEffectView')
                      		UIVibrancyEffect = ObjCClass('UIVibrancyEffect')
                      		UIBlurEffect = ObjCClass('UIBlurEffect')
                      		UILabel = ObjCClass('UILabel')
                      		frame = (self.bounds[:2], self.bounds[2:])
                      		self.effect_view = UIVisualEffectView.alloc().initWithFrame_(frame).autorelease()
                      		effect = UIBlurEffect.effectWithStyle_(self._style)
                      		self.effect_view.effect = effect
                      		self.effect_view.setAutoresizingMask_(18)
                      		ObjCInstance(self).addSubview_(self.effect_view)
                      		vibrancy_effect = UIVibrancyEffect.effectForBlurEffect_(effect)
                      		self.vibrancy_view = UIVisualEffectView.alloc().initWithFrame_(frame).autorelease()
                      		self.vibrancy_view.effect = vibrancy_effect
                      		self.effect_view.contentView().addSubview_(self.vibrancy_view)
                      		
                      	@property
                      	def style(self):
                      		return self._style
                      	
                      	@style.setter
                      	def style(self, value):
                      		if value != self._style:
                      			self._style = value
                      			self.setup_effect_view()
                      	
                      	@on_main_thread
                      	def add_vibrant_label(self, label):
                      		self.vibrancy_view.contentView().addSubview_(ObjCInstance(label))
                      
                      def main():
                      	image_view = ui.ImageView(frame=(0, 0, 320, 320))
                      	image_view.image = ui.Image.named('test:Mandrill')
                      	blur_view = BlurView(style=2, frame=image_view.bounds.inset(40, 40))
                      	image_view.add_subview(blur_view)
                      	label = ui.Label(frame=blur_view.bounds)
                      	label.text = 'Hello World'
                      	label.font = ('HelveticaNeue', 40)
                      	label.alignment = ui.ALIGN_CENTER
                      	blur_view.add_vibrant_label(label)
                      	image_view.present('sheet')
                      
                      main()
                      
                      1 Reply Last reply Reply Quote 2
                      • blmacbeth
                        blmacbeth last edited by

                        @omz You're the man! Thanks for that.

                        1 Reply Last reply Reply Quote 1
                        • blmacbeth
                          blmacbeth last edited by

                          Noticed some bugs in the above code, so here are my fixes to make it work (in Pythonista3, at least).

                          # coding: utf-8
                          
                          import ui
                          from objc_util import *
                          
                          class BlurView (ui.View):
                              def __init__(self, style=1, *args, **kwargs):
                                  ui.View.__init__(self, **kwargs)
                                  self._style = style
                                  self.effect_view = None
                                  self.setup_effect_view()
                              
                              @on_main_thread
                              def setup_effect_view(self):
                                  if self.effect_view is not None:
                                      self.effect_view.removeFromSuperview()
                                  UIVisualEffectView = ObjCClass('UIVisualEffectView')
                                  UIVibrancyEffect = ObjCClass('UIVibrancyEffect')
                                  UIBlurEffect = ObjCClass('UIBlurEffect')
                                  UILabel = ObjCClass('UILabel')
                                  # Brooks patch for Rect not having a 'slice' 
                                  bounds = self.bounds.as_tuple()
                                  frame = (bounds[:2], bounds[2:])
                                  self.effect_view = UIVisualEffectView.alloc().initWithFrame_(frame).autorelease()
                                  effect = UIBlurEffect.effectWithStyle_(self._style)
                                  self.effect_view.effect = effect
                                  self.effect_view.setAutoresizingMask_(18)
                                  ObjCInstance(self).addSubview_(self.effect_view)
                                  vibrancy_effect = UIVibrancyEffect.effectForBlurEffect_(effect)
                                  self.vibrancy_view = UIVisualEffectView.alloc().initWithFrame_(frame).autorelease()
                                  self.vibrancy_view.effect = vibrancy_effect
                                  self.effect_view.contentView().addSubview_(self.vibrancy_view)
                                  
                              @property
                              def style(self):
                                  return self._style
                              
                              @style.setter
                              def style(self, value):
                                  if value != self._style:
                                      self._style = value
                                      self.setup_effect_view()
                              
                              # Brooks fix @on_mains_thread to @on_main_thread
                              @on_main_thread
                              def add_vibrant_label(self, label):
                                  self.vibrancy_view.contentView().addSubview_(ObjCInstance(label))
                          
                          def main():
                              image_view = ui.ImageView(frame=(0, 0, 320, 320))
                              image_view.image = ui.Image.named('test:Mandrill')
                              blur_view = BlurView(style=2, frame=image_view.bounds.inset(40, 40))
                              image_view.add_subview(blur_view)
                              label = ui.Label(frame=blur_view.bounds)
                              label.text = 'Hello World'
                              label.font = ('HelveticaNeue', 40)
                              label.alignment = ui.ALIGN_CENTER
                              blur_view.add_vibrant_label(label)
                              image_view.present('sheet')
                          
                          main()
                          

                          The biggest problem was that the ui.Rect() object does not have the ability to use slices. This was fixed with the ui.Rect().as_tuple() function. The second problem was just a typo.

                          B

                          1 Reply Last reply Reply Quote 1
                          • rb
                            rb last edited by

                            How could you apply the vibrancy effect to work with a rectangular region rather than a label? I read there is a fill method and a separator method but not sure how you would implement.

                            cvp 1 Reply Last reply Reply Quote 0
                            • cvp
                              cvp @rb last edited by

                              @rb What do you call a rectangular region? A label could be seen as a rectangular region if you don't set its text.

                              1 Reply Last reply Reply Quote 0
                              • rb
                                rb last edited by

                                Ah ok - so what is the difference then between fill and label?I just thought label would be isolated to text - but it I’ll try that!

                                cvp 1 Reply Last reply Reply Quote 0
                                • cvp
                                  cvp @rb last edited by

                                  @rb the blur_view it-self is a rectangular region, thus no need of label at all

                                  def main():
                                      image_view = ui.ImageView(frame=(0, 0, 320, 320))
                                      image_view.image = ui.Image.named('test:Mandrill')
                                      blur_view = BlurView(style=16, frame=image_view.bounds.inset(40, 40))
                                      image_view.add_subview(blur_view)
                                      #label = ui.Label(frame=blur_view.bounds)
                                      #label.text = 'Hello World'
                                      #label.font = ('HelveticaNeue', 40)
                                      #label.alignment = ui.ALIGN_CENTER
                                      #blur_view.add_vibrant_label(label)
                                      image_view.present('sheet')
                                  
                                  1 Reply Last reply Reply Quote 0
                                  • rb
                                    rb last edited by

                                    No I mentioned vibrancy- ie I want bg to be blurred but a central rectangle to be not blurred and more vibrant.

                                    cvp 1 Reply Last reply Reply Quote 0
                                    • cvp
                                      cvp @rb last edited by

                                      @rb ok, sorry, misunderstood

                                      1 Reply Last reply Reply Quote 0
                                      • First post
                                        Last post
                                      Powered by NodeBB Forums | Contributors