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

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

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

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