I recently posted about a small weekend project with my sons: building an iOS soundboard app using NativeScript and a text-to-speech engine. In this post, I wanted to dive a bit deeper into resizing images for a NativeScript App, and how I went about integrating static images into my app.
Using XML and CSS to Add Images to your App
In my app, I embedded images for the profile pictures on the main page:
Planning ahead, I wanted to tap each image and perform an action. usually in nativeScript, you would use an Image tag to display an image; however, Images don’t have a tap event, so I had to use a Button control, with a background image set via CSS. For example, the markup and CSS for my image looks like this:
You’ll notice the button markup includes a row and col attribute, used to position the Button in a Grid Layout. You’ll also notice the tap event of the button is data bound to a function on my view model, named “onTap”. In the CSS, notice the how I set common button size and background image attributes with the Button {…} styles.
If you’re familiar with CSS, all of these elements shouldn’t seem out of the ordinary (which is why I love NativeScript, b/c I can leverage my existing web skills to build a truly native app). You will also see the #mike id selector, which sets the actual background image of the button. Most of this syntax should be familiar, with the exception of the res://mike syntax. This syntax tells NativeScript to use an app resource for the image source.
Image resources are a convention-based way to have the NativeScript runtime auto-select an appropriate image based upon the device (i.e., screen resolution and pixel density). For example, this app may run on an iPhone 4s or an iPad Mini with retina display. The usual problem is screen resolution and accounting for that in your images. The NativeScript docs have a great write-up on how to handle this through their conventions; however, as an app writer, you need to supply the runtime with image assets of multiple resolutions. Yuck.
I’ve written about this problem before, and previously created a website to automatically resize images for iOS and Android apps. This was my first opportunity to use the website, and let me say, it saved me tons of time.
Planning for Different Device Resolutions
When I started planning for this app, I knew I wanted to support multiple form factors: iPhone, iPad, iPad Mini 2 (retina), so I needed to start planning my images early. As a general rule of thumb, I always plan for the maximum device resolution and scale down my images accordingly. On the home page of my app, I wanted to show an image of each person in the family:
Knowing that I wanted to support the iPad Mini 2 (retina), my max screen resolution was 2048 x 1536. So with some quick math, the max size of each image should be 768 x 768. But, there’s a catch: this image size is for an iPad retina, which is considered an @2x image size. Planning ahead, I know I want to support higher pixel densities (@3x), so I needed to scale the dimensions of the original image up to 1.5x of the 768 x 768 size. The size I needed to start from was actually 1152 x 1152 to support the iPhone 6 plus.
With my image dimensions in mind, I began cropping a high-res JPG from my recent visit to San Francisco. Using Paint.NET, I scaled down the image to a square version that was at least 1152 x 1152. I then cropped the picture further to have a circular outline. I finally saved the image as a PNG:
An important aspect to note is that I did not crop my image down to 768 x 768 first, then expand/increase the size to 1152 x 1152. Resizing images multiple times by scaling up, then down, then up again will eventually produce a “grainy image”, which is undesirable. As a result, it’s generally important (especially for photos) to start with a high resolution image and scale down once (I said “generally” above because direct resizing of images is not necessary the best approach, but I’m not ready to get into this further right now – many different people have written about image resizing in the past, so take a look).
Uploading to the NativeScript Image Builder Site
With my base (and highest resolution) image created, I headed over to my NativeScript Image Builder site, selected my image (mike.png), selected the “Static Image – iOS” option, and pressed “Upload App Image”:
The site returns a zip file containing the original image resized to the appropriate proportions, as required by iOS:
Inside the zip file, you’ll find the original image was renamed to [original-name]@3x.png, a 2/3 scaled down version named [original-name]@2x.png, and a 1/3 scaled down version named [original-name].png.
Making Static Images work at Multiple Device Resolutions
To add static images to the app, I placed the images inside the app/App_Resources/iOS folder (note you’re seeing my wife’s images added and not mine):
Once the images are in the App_Resources folder, you can reference them via the res:// syntax within your app. If you recall, this is exactly what I did earlier:
When the NativeScript runtime encounters an image loaded via res://, the current mobile platform is detected (Android or iOS), the device screen resolution and pixel density is determined, and the appropriate image is selected for rendering. On iOS, the base image (mike.png) is used for iPad 2 and iPad Mini, the @2x image is used for iPhone 4s, iPhone 5, iPhone 6, and other retina devices, and the @3x image is used for iPhone 6 plus. What’s nice about using the resource approach is that NativeScript handles everything for you.
If you have a change, clone my Git repo over at Github and try out our app. We have had a lot of fun playing with it at home over the past several days. Enjoy!