How do I create a scalable UI using graphics?

Creating interfaces that grow / scale based on the size and aspect ratio of their container.

Introduction

In this lesson we look about building a UI using vector graphics that scales all assets and positions them according the device screen size and density.

By way of example, we will convert an app that was made for a small form factor mobile device (original iPhone) and make it scale for any device in any orientation.

Note: This lesson is taken from a seminar run at RunRevLive 2013 by Ben Beaumont, LiveCode product manager. As a result, it may not explain the concepts as clearly as other standard lessons.

SheepHerder Original

SheepHerder Original

App made as a promo for how quickly mobile apps can be made with LiveCode

PRO

1) We made an app in a little over 3 hours

CON

1) The app only ran at 320x480 and didn't scale for different devices

2) The app was based entirely on images so making it scale for devices was not possible without exporting those images at a variety of resolutions

SheepHerder Vector

SheepHerder Vector

I then remade the SheepHerder app using only graphics.

PRO

1) Works at ANY screen resolution and aspect ratio.

2) The total source for the application is 89Kb.

CON

1) There is an overhead using graphics, particularly with effects like gradients because they have to be calculated when displayed.

2) Very rich applications may not suit this approach.

SheepHerder is a simple app that is perfectly suited to this method.

1) It doesn't have a complex layout so works on any aspect ratio.

2) It doesn't have any animated elements or visually rich elements.

3) It has a simplistic UI.

However, I use these principles in all the apps I write to varying degrees.

Preparation

Preparation

Break the UI up into logical containers whose components are logically scaled and positioned based on the container. With SheepHerder I broke it up like this:

- Background

- Sheep

- Pit

- Footer

- Message Screen

Each is a group of objects.

Example Footer Group

1) Create a new stack

2a) Add a graphic

2b) Style it: I've added a gradient

3a) Add a button

3b) Style it: I've made it a round button with a blue background color

4) Group the objects

5) Set the group margins to 0

NOTE: Margin 0.

- Whenever working with groups as containers it's best to set the margins to 0. It makes calculating the position of components much easier.

ResizeControl message

1) A group receives a resize control message whenever it changes size.

2) We can use this message to resize and reposition all the controls in the group.

Example Script - Scale and position the background.

Example Script - Scale and position the background.
on resizecontrol
   set the rect of graphic 1 of me to the rect of me
end resizecontrol

NOTE: "of me".

- When working with groups we use the "of me" syntax which ensures the script acts on the object in the group rather than an similarly named object.

Example Script - Scale and position the button.

Example Script - Scale and position the button.
on resizecontrol
   lock screen
   
   // Background
   set the rect of graphic 1 of me to the rect of me
   
   // Background
   set the width of button 1 of me to the width of me * 0.4
   set the height of button 1 of me to height of me * 0.65
   set the loc of button 1 of me to the loc of me
   
   unlock screen
end resizecontrol

NOTE: "lock screen" when resizing multiple objects.

- To avoid flickers as objects resize and move, surround the code with "lock/unlock screen".

NOTE: % scaling applied by setting width/height of objects to a scale factor of width/height of group.

ResizeStack

1) Once you have created your scalable components your can turn your attention to scaling and positioning them in the context of a full app.

2) When a stack changes size, a "resizeStack" message is sent to the stack.

Example script - Position the footer

1) Name the group "footer"

2) Position the group in the "resizeStack" handler in the stack script

on resizeStack
   lock screen
   
   // FOOTER
   set the width of group "footer" to the width of me
   set the left of group "footer" to 0
   set the bottom of group "footer" to the height of me
   
   unlock screen
end resizeStack
Example script - Position and scale the footer
on resizeStack
   lock screen
   
   // FOOTER
   set the height of group "footer" to the height of me * 0.15
   set the width of group "footer" to the width of me
   set the left of group "footer" to 0
   set the bottom of group "footer" to the height of me
   
   unlock screen
end resizeStack

Example Script - Scale the button text size

Example Script - Scale the button text size
on resizecontrol
   lock screen
   
   // Background
   set the rect of graphic 1 of me to the rect of me
   
   // Button Size and Position
   set the width of button 1 of me to the width of me * 0.4
   set the height of button 1 of me to height of me * 0.65
   set the loc of button 1 of me to the loc of me
   
   // Button Text Size
   put the height of button 1 of me * 0.7 into tTextHeight
   repeat with x = 6 to 100
      set the textSize of button 1 of me to x
      if the formattedheight of button 1 of me > tTextHeight then exit repeat
   end repeat
   
   unlock screen
end resizecontrol

Example Script - Scale field text size

Example Script - Scale field text size

1) Add a field

2) Make the field scale and position left

3) Make the button scale and position right

on resizecontrol
   lock screen
   
   // Background
   set the rect of graphic 1 of me to the rect of me
   
   // Button Size and Position
   set the width of button 1 of me to the width of me * 0.4
   set the height of button 1 of me to height of me * 0.65
   set the loc of button 1 of me to the loc of me
   set the right of button 1 of me to (the left of me + (the width of me * 0.95))
   
   // Button Text Size
   put the height of button 1 of me * 0.7 into tTextHeight
   repeat with x = 6 to 100
      set the textSize of button 1 of me to x
      if the formattedheight of button 1 of me > tTextHeight then exit repeat
   end repeat
   
   // Field Size and Position
   set the width of field 1 of me to the width of me * 0.5
   set the height of field 1 of me to height of me * 0.65
   set the loc of field 1 of me to the loc of me
   set the left of field 1 of me to (the left of me + (the width of me * 0.05))
   
   // Field Margins (Centers the text in the field)
   local tTextRect, tFieldRect, tDeltaY
   set the textsize of field 1 of me to the textsize of button 1 of me
   set the margins of field 1 of me to 0
   put the formattedRect of line 1 to -1 of field 1 of me into tTextRect
   put the rect of field 1 of me into tFieldRect
   put ((item 4 of tFieldRect - item 2 of tFieldRect) - (item 4 of tTextRect - item 2 of tTextRect)) div 2 + (item 2 of tFieldRect - item 2 of tTextRect) into tDeltaY
   set the margins of field 1 of me to 0,tDeltaY,4,0
   
   unlock screen
end resizecontrol

0 Comments

Add your comment

E-Mail me when someone replies to this comment