Media

INFO PAGE

Adaptive, Flexive and Responsive Design for Mobile

Creators have had to rethink their designs to accomodate Mobile. The designs need to make sense on smaller screens in portrait or landscape, in dark and light, noisy or quiet conditions. Often, we want the design to change depending on the environment. The main terms we use are responsive and adaptive. We have thrown in a Flexive here as well.

RESPONSIVE DESIGN

Responsive design is when we scale or wrap to fit the screen. Scaling to different screen sizes and aspect ratios can be done using percentages.

For example:
var circle = new zim.Circle().center();
circle.height = H * .5;  // 50% or .2 which is 20%, etc.

This will make a circle half the height of the stage at any stage size. If the orientation is landscape (horizontal), this may be what we want - but if the orientation is portrait (vertical) then the circle may go off the screen. So we may want to scale the circle based on the smallest dimension. This is quite an easy calculation to test if the W is less than the H for instance. But it is annoying to have to do the calculation all the time. So you can make a little function to do it or use the scaleTo() function / method in ZIM:

circle.scaleTo(S, 50, 50);

This will scale the circle to 50% of the stage in the smallest of stage width or height dimensions. If you use FILL it would scale to the biggest of width and height dimensions. Note, if you added a FULL as the next parameter, it would make the circle an oval with 50% the width and 50% the height.

circle.fit(0, 0, W, H);

This will fit the circle within the dimensions given and center it. So, you can manually proportion objects in any way you want using the above techniques. But making them work together is tricky - and the next topic called Flexive.

Note that Tile() can be made responsive - see Responsive Tile. Also, Pack() provides a way to pack in objects like pictures depending on available size - see Pack

Wrapping in ZIM can be done with the Wrapper() which wraps many items and has lots of features like CSS FlexBox.

const circles = [];
loop(40, ()=>{
    circles.push(new Circle(20, [orange, green, blue]));
});
const wrapper = new Wrapper(circles, 400, 20, 20).center();

interval(.5, ()=>{
    wrapper.resize(rand(300,500)).outline();
    S.update();
});

FLEXIVE DESIGN

Flex design allows you to place regions with fixed aspect ratios together on the page and specify their relationship.

Many applications with interfaces and content creation areas are easier to design and build with fixed-ratio regions. A simple example is a picture. A picture has a fixed ratio. Assuming a portrait orientation, we may want a logo above the picture and some buttons below the picture. The logo also has a fixed aspect ratio. The buttons could probably stretch, but it is easier to make them with a fixed aspect ratio that works well with the label on the buttons.

An efficient solution would be to maximize the picture on the width (with a bit of margin) and then to place and scale the logo on what room is left above the picture and place and scale the buttons on what room is left below the picture - also with margins. We will want to choose the alignment as well. We may have more than three regions.

All this is very hard to code - as in 370 lines of complex iterative code. It is what Adobe Flex was created for - to layout regions with scales, margins, min, max, alignments, etc. I am guessing, it was Adobe who introduced the flex display style based on their code. https://css-tricks.com/snippets/css/a-guide-to-flexbox/

// these would be containers with your content
// make sure that bounds are set on containers
// you may want to hard code bounds for clarity
const header = new Rectangle(500, 200, blue);
const content = new Rectangle(600, 500, green);
const footer = new Rectangle(500, 200, blue);
S.addChild(header, content, footer);

// make a vertical Layout - more useful for FULL scale mode
new Layout({
    holder:S,
    regions:[
        {obj:header, marginTop:10, maxWidth:80, minHeight:10, valign:TOP},
        {obj:content, marginTop:5, maxWidth:90}, // note, middle gets no minHeight
        {obj:footer, marginTop:5, maxWidth:80, height:10}
    ],
    lastMargin:5
});

// As of ZIM ZIM 02, A GlobalManager will automatically be added
// to resize any Layout objects

ZIM has a Layout class that does flex design with any number of horizontal or vertical (or nested) regions. Some parameters are different for vertical or horizontal regions - for instance, vertical regions get marginTop and maxWidth and minHeight whereas horizontal regions get marginLeft, maxHeight and minWidth, etc. It is sometimes tricky to get what you want, but so far, I have always been able to do it and it gets easier with practice.

ADAPTIVE DESIGN

Adaptive design generally means to change the position of something or indeed whether to show something or not depending on screen size or on orientation change.

Obviously, we can just use conditionals to govern whether we add an object to the stage or not.

if (W > 640) circle.center();

For orientation change, we can capture an orientation event - that comes from evaluating a resize event to see if the aspect ratio has switched from greater than to less than one for instance. And F.orientation will give us "horizontal" or "vertical" values. Based on these the content layout can be changed.

The technique I have found the easiest is to make a page for each orientation. These both exist with their own objects. This doubles the memory for page objects but that memory is usually not an issue unless you have hundreds of pages… This allows you to layout the pages at authoring time rather than dynamically swapping positions, etc.

// make pages (these can have content added to them)
const page1 = new Page(W, H, blue);
new Label("Swipe sideways").center(page1);
const page2 = new Page(W, H, green, pink); // makes a gradient
const page3 = new Page(W, H, yellow);
const horizontal = new Pages([page1, page2, page3], "slide").addTo();

// then make more pages for vertical and store in vertical.

F.on("orientation", (e)=>{
    if (e.orientation==VERTICAL) {
        vertical.go(horizontal.index); // keep pages synched
        vertical.addTo();
        horizontal.removeFrom();
    } else {
        horizontal.go(vertical.index); 
        horizontal.addTo();
        vertical.removeFrom();
    }
    S.update();
});

ZIM has a Pages class that helps keep track of pages. You would make a Pages object for each orientation. Then in the orientation event function, you enable the Pages object for the current orientation and disable the pages object for the other orientation. You also need to add or remove the appropriate Pages object from the stage. Also, you will want to synch the pages on orientation change so the newly enabled Pages object is on the same page as the newly disabled Pages object. Guaranteed, that ZIM is at least 1/20 the code that APPLE requires to do the same in Objective C.

Making digital environments in which people cancreate, communicate and play