Photos and Images

In this chapter, we will talk about importing images from user's Photos Library, and taking pictures with Camera.

This process may sound complicated, but this is actually one of the easiest and shortest part of the book. Even if we used plain Objective-C syntax, it would take just 5-7 strings of code.

To allow user to select an image from his Photos Library, or to take a new picture with camera, we need to:

However if you are using the bubble-wrap gem, it can be even easier. Just call bubble-wrap's method that shows media library or a camera, and gem will do everything for you, and return a selected image.

To check how does it work on practice, let's allow tutorial_app to choose an image from Library, or take a picture. Since we already have a screen that shows pictures selected by a user, let's use it for this tutorial as well.

We are going to change FilesScreenLayout by adding two new buttons: Take a Photo, and Select from Library. When the user wants to take a new picture, we will call method make_photo, that will show an image picker in a plain Objective-C way. Select from Library button will call an open_library method, that will use bubble-wrap gem to present user's library.

When the user finishes adding pictures, save_image will be called, to save it to the filesystem, and show next time the user opens the app. Let's begin!

        class FilesScreenLayout < MotionKit::Layout
          def layout
            add UITextField, :url
            add UIButton, :get
            add UIButton, :photo
            add UIButton, :library
            add UIImageView, :image
          end

          # FilesScreenLayout code ...

          def photo_style
            title "Take a Photo"
            title_color :blue.uicolor
            constraints do
              center_x.equals(:superview, :center_x)
              top.equals(:get, :bottom).plus(20)
            end
          end

          def library_style
            title "Select from Library"
            title_color :blue.uicolor
            constraints do
              center_x.equals(:superview, :center_x)
              top.equals(:photo, :bottom).plus(20)
            end
          end

          def image_style
            content_mode UIViewContentModeScaleAspectFit
            constraints do
              center_x.equals(:superview, :center_x)
              top.equals(:library, :bottom).plus(20)
              width(300)
              height(300)
            end
          end
        end
      

Now we need to make those new buttons work:

        class FilesScreen < PM::Screen
          title "Files and Images"

          # screen code ...
          def on_load
            self.view.backgroundColor = 0xffffff.uicolor
            @layout.get(:get).on_tap do
              download_image_from @layout.get(:url).text.to_s
            end
            @layout.get(:photo).on_tap { make_photo }
            @layout.get(:library).on_tap { open_library }
            @image_view = @layout.get(:image)

            @get = @layout.get(:get)
            load_image
          end

          def make_photo
            picker = UIImagePickerController.new
            picker.sourceType = UIImagePickerControllerSourceTypeCamera
            picker.delegate = self

            open_modal picker
          end

          def imagePickerController(picker, didFinishPickingMediaWithInfo: info)
            image = info["UIImagePickerControllerOriginalImage"]
            return if !image.is_a?(UIImage)

            @image_view.image = image
            save_image image
          end

          def open_library
            BW::Device.camera.any.picture(media_types: [:movie, :image]) do |result|
              break if !result[:original_image].is_a?(UIImage)

              @image_view.image = result[:original_image]
              save_image result[:original_image]
            end
          end

          # rest of screen code ...
        end
      
on_load code should be easy to understand. It has only two new string that connect buttons with actions.

In make_photo method, we create new image picker and defining its source type. In this example, you can see that source type is Camera, which means the user will use device's camera to add a picture. Then we set image picker's delegate and opening it as a modal screen. When the user takes a picture, imagePickerController(picker, didFinishPickingMediaWithInfo: info) method will be called. There we retrieve an image, and trying to show it to the user, and save it for future use.

The open_library method uses bubble-wrap gem to select a picture from the library. If you would like to use Objective-C method, you could use the same code from make_photo method, just with a different sourceType. You can read more about bubble-wrap on their page: Bubble-Wrap. Its code should be easy to understand - we ask it use to show image picker that would allow the user to select video or an image. When ready, it will return a picture in a result variable.

Don't forget to add bubble-wrap gem into Gemfile, and run bundle install after:

        
          gem 'bubble-wrap', :require => [ 'bubble-wrap/core', 'bubble-wrap/camera' ]
        
      

It is time to make a commit!

        git add .
        git commit -m "added image pickers to Files Screen"
      

Summary

It is very easy to allow the user to select a picture even without any Rubymotion gems: just create an instance of image picker, set its type (library picker or camera), and present it to the user!

You can read more info on Image Picker at Apple's Docs. And here are Bubble Wrap docs.

Book Index | Next