Monday, March 14, 2016

Lesson 7. Layout parameters for View-elements

In this lesson we will:
- examine screen properties;
- explore layout parameters (height, width, margin, gravity, weight)
Translated by Taras Leskiv (http://android-by-example.blogspot.com/)

Screens

To begin with, here is some theory about screens. A screen has such physical properties as size and resolution. Screen size - a distance between two opposite corners of the screens, usually measured in inches. Resolution - a number of points horizontally and vertically, which the screen is able to display, measured in pixels.
Let’s take a display of HTC Desire smartphone as an example. Screen size = 3.7 inches, resolution = 800x480 pixels.
The number of pixels in one inch is called dpi (dots per inch). Let’s find out what is dpi equal to in this case. Remembering the basics: c2 = a2 + b2, where c is a number of pixels on the diagonal. c is a number of pixels that fits into 3.7 inches. a and b are the sides of the screen.
c = 3,7 * dpi
(3,7 * dpi)2 = 4802 + 8002dpi2 = 870400 / 13,69 = 63579
dpi = 252. So into one inch of the screen fits the number of pixels which is equal to 252.

Let’s get back to the lesson subject. Let’s look through in detail the following parameters of View elements

Layout width and Layout height

We have talked a little about width (layout_width) and height (layout_height) in the previous lesson. We can specify absolute values for them or we can use constants. Let’s explore these possibilities.

ABSOLUTE VALUES:

The following units of measure are used (MU):
dp or dip - Density-independent Pixels. Abstract unit of measure, that allows applications to look alike on different screens and resolutions.
sp - Scale-independent Pixels. The same as dp, but is used for font sizes in View-elements.
pt - 1/72 of an inch, is defined by the physical screen size. This MU if from typoghraphy.
px - pixel, not recommended to use, as the application will look different on different screens.
mm - a millimeter, defined by the physical size of the screen.
in - an inch, defined by the physical size of the screen.

CONSTANTS

match_parent (fill_parent) - means that the element will occupy all the available width/height in the parent element.
wrap_content - width/height is defined by its content

Let’s create a project:
Project name: P0072_LayoutProp
Build Target: Android 2.3.3
Application name: LayoutProp
Package name: ru.startandroid.develop.layoutprop
Create Activity: MainActivity
Open main.xml. Configure root LinearLayout to have horizontal orientation. Delete the TextView and add a Button with width and height equal to wrap_content. It is now displayed on the screen and its width corresponds to the text width in it.

Change text "Button" to "Button with text", save and have a look at the screen.

The button became wider, as the width is defined by the content. If we now specify the width of 250 dp, the button will stretch independently of content.

Now make the width equal to match_parent. The button has stretched for the whole parent width (LinearLayout). And LinearLayout by-turn occupies the whole screen width.

If our parent contains a few elements and we want them to occupy the whole space, we must use Layout weight parameter. Free space is distributed proportionally to element weight values.
Change text of our button to B1 and add it a neighbour in LinearLayout - the second button with B2 text. Set the wrap_content width for both

Let’s start dividing. If we want the space of the parent to be distributed equally - specify weight = 1 for both. In this case buttons will have equal widths.

Note that simple numbers are specified, not units of measure.
If you need B1 to occupy a quarter and B2 three quarters of the available space, then specify weight = 1 for B1 and weight = 3 for B2.

There can be any number of elements. Add also a button with text B3weight = 2 and width = wrap_content

xml-code of the resulted screen:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal">
<Button
android:id="@+id/button1"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="B1"
android:layout_weight="1">
</Button>
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="B2"
android:layout_weight="3">
</Button>
<Button
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="@+id/button3"
android:text="B3"
android:layout_weight="2">
</Button>
</LinearLayout>

Now specify weight = 0 for B2 and B3. They don’t have a claim on the free space now and have a width defined by the content, so B1 occupies all the space

It is obvious this can be also applied to the height parameter.
When using weight attribute you can specify the value of height or width = 0dp. In this case the content of the element would be ignored and the result will more correspond to weight ratios.

Layout gravity

layout_gravity parameter is similar to alignment in Word or Excel. It would be the most convenient to demonstrate it using FrameLayout. I didn’t describe this layout in the previous lesson as it is very simple. All the elements put in it, are by default positioned in the top left corner and are not lined up in any way. It fits great for demonstrating alignment settings.
Create grlayout.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/frameLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top|left"
android:text="gravity = top left">
</Button>
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top|right"
android:text="gravity = top right">
</Button>
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|left"
android:text="gravity = bottom left">
</Button>
<Button
android:id="@+id/button4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:text="gravity = bottom right">
</Button>
<Button
android:id="@+id/button5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="gravity = center">
</Button>
</FrameLayout>
</LinearLayout>

On the screen:
For clarity text on the button displays its properties. Everything is clear and simple.
I honestly tried to understand what are gravity values fill_* and clip_* for, but I couldn’t. What is written in help about them, doesn’t work for me. If you have any information regarding this - write a comment.

Layout margin

margin parameters are completely similar to html margin. Margin can be on all the sides at once or only on the sides, where it is required. Let’s demonstrate it with a TableLayout example. We will create marginlayout.xml and draw a table three by three with buttons
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TableLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:id="@+id/tableLayout1">
<TableRow
android:id="@+id/tableRow1"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button
android:text="Button"
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</Button>
<Button
android:text="Button"
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</Button>
<Button
android:text="Button"
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</Button>
</TableRow>
<TableRow
android:id="@+id/tableRow2"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button
android:text="Button"
android:id="@+id/button4"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</Button>
<Button
android:text="Margin"
android:id="@+id/button5"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</Button>
<Button
android:text="Button"
android:id="@+id/button6"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</Button>
</TableRow>
<TableRow
android:id="@+id/tableRow3"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button
android:text="Button"
android:id="@+id/button7"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</Button>
<Button
android:text="Button"
android:id="@+id/button8"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</Button>
<Button
android:text="Button"
android:id="@+id/button9"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</Button>
</TableRow>
</TableLayout>
</LinearLayout>


We will experiment with the button in the middle.
margin = 50 dp
And a margin = 50 dp appears around the button


margin left = 10 dp
margin top = 20 dp
Top and left margins.


margin right = 30 dp
margin bottom = 40 dp
Right and bottom margins

The lesson appears to be quite big, but valuable. I guess it is the last lesson of design, modelling and making-up and we will start coding.

In the next lesson we will:
- learn how to refer to View-elements from code and change their properties
  1. ANDROID TRAINING IN KATHMANDU
  2. ANDROID TRAINING IN LALITPUR 
  3. APP DEVELOPMENT IN KATHMANDU

Sunday, March 13, 2016

Lesson 6. Layout types. Key differences and properties

LinearLayout - displays View-elements as a single row (if it is Horizontal) or a single column (if it is Vertical). I used it in the previous lesson, when demonstrating usage of layout-files during screen orientation change.
TableLayout - displays elements in the form of a table, with rows and columns.
RelativeLayout - each element’s position is configured relatively to other elements.
AbsoluteLayout - each element is specified an absolute position on the screen in the coordinate system (x, y)
Lets observe these types
  1. ANDROID TRAINING IN KATHMANDU
  2. ANDROID TRAINING IN LALITPUR 
  3. APP DEVELOPMENT IN KATHMANDU

LinearLayout (LL)

This type of a ViewGroup is set as default when creating new layout-files. It is really convenient and flexible enough to create screens of different complexity. LL has an Orientation property, which defines how will the child elements be positioned - in a vertical or horizontal line.
Let’s make a simple and clear example.
Create a project:
Project name: P0061_Layouts
Build Target: Android 2.3.3
Application name: Layouts
Package name: ru.startandroid.develop.layouts
Create Activity: MainActivity

Open main.xml layout-file and place the following code inside:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</LinearLayout>
Now we have a LinearLayout with vertical orientation as a root element.
Drag three buttons from the left to the root LinearLayout. They are positioned horizontally.

Now change Orientation property to horizontal for LL in Properties and save (CTRL+SHIFT+S) - buttons are positioned horizontally

A ViewGroup can be inserted into another ViewGroup. Let’s place two other LL into one. Delete all the elements from main.xml (three buttons) except of the root LL. Specify vertical orientation for the root LL and add two new horizontal LL inside it. They are located in the Layouts section in the list of elements on the left. Let me remind you, that you can drag and drop elements from the list not only to the screen, but also to the specific element in the Outline tab.
Add three buttons inside each horizontal LL. Now we have got two horizontals rows of buttons.

TableLayout (TL)

TableLayout consists of rows TableRow (TR). And each TR contains View elements that form columns. So the number of Views in TR is a number of columns. But the number of columns in  a table must be equal for all rows. That’s why, when different TRs have different numbers of View-elements (columns), the overall number of columns is defined by the TR with the maximum number. Let’s observe an example.
Create layout-file tlayout.xml with TableLayout as a root element.

Add three TableRow rows into the root TableLayout (from Layouts section on the left) and add two buttons into each row. The result: our table has got three rows and two columns.

Add a few more buttons to the first row. The number of columns now equals 4, as it is defined by the row with the maximum number of elements and it is the first row in our case. For the second and the third rows the third and the fourth columns are empty.

Add a TextView and a Button to the second row and make text in the added TextView empty. Do the same with the third row. We can see that these elements are now placed in the third and the fourth column. And because TextView is empty and not seen on the screen, it seems like the third column in the second and third rows is empty.

The width of the column is defined by the widest element in this column. Enter some text into one of the TextViews and we can see that it has made a column wider.

Now I will remove elements of the fourth column and build a screen like this. Try to do it on your own as an exercise.

TL can contain not only TRs, but also simple Views. For example, add Button just into the TL, not into TR and you will see how it stretches to the width of the whole table.

RelativeLayout (RL)


In this type of Layout, each View-element can be positioned in a specific way relatively to the specified View-element.
Types of relationships:
1) to the left, right, above or below the specified element (layout_toLeftOf, layout_toRightOf, layout_above, layout_below)
2) aligned by the left, right, top or bottom edge of the specified element (layout_alignLeft, layout_alignRight, layout_alignTop, layout_alignBottom)
3) aligned by the left, right, top or bottom edge of a parent (layout_alignParentLeft, layout_alignParentRight, layout_alignParentTop, layout_alignParentBottom)
4) centered vertically, centered horizontally, centered vertically and horizontally relative to its parent (layout_centerVertical, layout_centerHorizontal, layout_centerInParent)
More details are available in help.

Create rlayout.xml and copy and paste this xml-code:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Type here:">
</TextView>
<EditText
android:id="@+id/entry"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/label"
android:background="@android:drawable/editbox_background">
</EditText>
<Button
android:id="@+id/ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_below="@+id/entry"
android:layout_marginLeft="10dip"
android:text="OK">
</Button>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@+id/ok"
android:layout_toLeftOf="@+id/ok"
android:text="Cancel">
</Button>
</RelativeLayout>
RelativeLayout is a the root element here.
We will get such a screen:

We are interested in xml-code. I will now shortly describe unknown attributes and their meanings:
android:layout_width="match_parent" 
android:layout_height="wrap_content" 
android:id="@+id/entry"

- the android word in the name of each element is a namespace, I will omit it in the explanations. 
id - the element ID,
layout_width (the width of the element) and layout_height (the height of the element) can be specified in absolute values or can be the following: fill_parent (maximum available width or height in the bounds of its parent) and wrap_content (width of height is defined by the content of an element). Help states that there is also match_parent. It is the same as fill_parent. For some reasons, developers of the system decided that match_parent name is more convenient and they will stop using fill_parent soon. For now, it’s left for compatibility. So remember that match_parent = fill_parent and we will be trying to use match_parent further. Later we will stop on this and analyze it in more detail.

Now let’s get back to our elements. In the example we can see a TextView, EditText, and two Buttons - OK and Cancel. Let’s look through the attributes we are interested in.


TextView 
android:id="@+id/label" - ID
android:layout_width="match_parent" - occupies all the available width (even though, it’s not visible on the screen) 
android:layout_height="wrap_content" - height defined by the content 
it is not related to anything

EditText 
android:id="@+id/entry" - ID
android:layout_width="match_parent" - occupies all the available width
android:layout_height="wrap_content" - height defined by the content
android:layout_below="@id/label" - located below the TextView (reference by ID)

Button_OK 
android:id="@+id/ok" – ID
android:layout_width="wrap_content" - width defined by the content 
android:layout_height="wrap_content" – height defined by the content 
android:layout_below="@id/entry" - is located below EditText
android:layout_alignParentRight="true" - is aligned by the right edge of the parent
android:layout_marginLeft="10dip" – has a margin on the left (for Button_Cancel not to be adjacent)

Button_Cancel
android:layout_width="wrap_content" - width defined by the content 
android:layout_height="wrap_content" – height defined by the content 
android:layout_toLeftOf="@id/ok" - located to the left of Button_OK
android:layout_alignTop="@id/ok" - aligned by the top edge of Button_OK


You can add some more elements and experiment with their locations.
Pay your attention, that a View element can have no ID (android:id). For example, it is not usually needed for a TextView, because most of the times they are static and we rarely refer to them in the application. EditText is different - we work with the text field content, and a Button - we need to process clicks and to know exactly which Button has been pressed. In the future, we will see one more reason to specify an ID for a View-element

AbsoluteLayout (AL)

Provides absolute positioning of elements on the screen. You specify the coordinates for the left top corner of the component.
Create alayout.xml with AbsoluteLayout as a root element

Now try to add different elements by dragging them to the screen. They are not aligned as in LinearLayout or in TableLayout, but placed where you dragged them. So it is absolute positioning.

Open xml-code and note that for specifying coordinates layout_x and layout_y properties are used
<?xml version="1.0" encoding="utf-8"?>
<AbsoluteLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_x="42dp"
android:layout_y="62dp"
android:text="Button">
</Button>
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_x="142dp"
android:layout_y="131dp"
android:text="TextView">
</TextView>
<CheckBox
android:id="@+id/checkBox1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_x="55dp"
android:layout_y="212dp"
android:text="CheckBox">
</CheckBox>
<RadioButton
android:id="@+id/radioButton1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_x="171dp"
android:layout_y="318dp"
android:text="RadioButton">
</RadioButton>
</AbsoluteLayout>


First you might think that this is the most convenient and intuitive method of placing elements on the screen - they are placed wherever you want at once. But this is only in the case when you develop for the screen with a specific resolution. If you look at such application on the other screen, all the elements will be shifted and their positioning will be different from what you have planned. That’s why it is not recommended to use this Layout. And it’s compatibility with future Android versions is not guaranteed.