02
  • Introduction
  • 2.1
  • 2.2
  • 2.3
  • 2.4
  • 2.5
  • 2.6
  • 2.7
  • 2.8
  • 2.9
  • 2.10
  • Graphical User Interfaces

    As discussed on week 1 presentation part 2, the Android platform has been designed to run on a different types of device, screen sizes, and screen resolutions. This impose lots of challenges to android developers in terms of providing rich components of user interfaces (UI) in response to the need of the specific applications. To overcome this, Android provides a user interfaces(UI) toolkit that can be used by developers to customise UI components of an applications. Android developers relies heavily on using XML framework to create liquid layout that can adapt to these environmental changes.

    In this week, we are going to use practical ways to shape this framework to fit your specific development needs. There are two important classes in the construction of graphical user interfaces, these are:
    Views
    ViewGroups

    Views

    The View class represents the basic building block for user interface components. A View occupies a rectangular area on the screen and is responsible for drawing and event handling.

    View is the base class for graphical components, which are used to create interactive UI components e.g. buttons, labels, edit boxes etc..

    ViewGroup

    The ViewGroup subclass is the base class for layouts, which are invisible containers that hold other Views (or other ViewGroups) and define their layout properties ViewGroups will be dealt with separately. For more discussion of Views and ViewGroups click 🔗 here 1

  • Graphical Components

    Initial appearance as defined at Design time is defined in the xml file contained in the layout folder. This file is usually called main.xml. Changes to the appearance of the graphical components are achieved via Java Code at run time.

    1 - 🔗 https://www.studytonight.com/android/introduction-to-views

    Basic Building Blocks

    There are a number of basic components that can be used to make a good effect in a range of applications such as:
    TextView - a user interface element that displays text to the user and to provide user-editable text
    EditText - a user interface element for entering and modifying text.
    Button - used to instigate an “Action”

    TextView

    TextView is a user interface element that displays text to the user and to provide user-editable text.

    The following code sample shows a typical use, with an XML layout and code to modify the contents of the text view:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:orientation="vertical"
          android:layout_width="fill_parent"
          android:layout_height="fill_parent"
        >
        
    <TextView
        android:id="@+id/salutation"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textSize="20sp"
        android:text="Welcome to Mobile Platform Development"
        />
    

    So you should treat the TextView widget as a label and use it to “label” other objects. The initial appearance of the app is the same as the default background colour. There is no border.

    In Java code, you can use setText(“This is some text”); to sets the text to be displayed and use getText() to retrieve the text that TextView is displaying. Here’s a sample code for it.

    myTextView.setText(“Length”);
    astring = myTextView.getText();
    
  • Basic Building Blocks

    Other basic components for graphical user interface as outlined on tab 2.1 are EditText and button.

    EditText

    A user interface element for entering and modifying text. For example, for plain text input set inputType to "text": So EditText can be used to enter “data” for your application where’s “Visible” keypad can be customized i.e. numbers letters etc. and the default appearance includes a border.

    Again here you can use getText() to retrieve the data entered, note that getText() returns an object of type Editable e.g.

    Editable anItem= inputBox.getText();
    stringLength = anItem.toString();
    

    The toString method here is used to convert a string as required to say a numerical type, but in general, the toString method returns a string that "textually represents" this object.

    Button

    A user interface element when the user tap or click to perform an action. To display a button in an activity, add a button to the activity's layout XML file and a default appearance includes a border. Action is carried out in a “listener method” and the listener needs to be “attached” to object(s) of interest. So, to specify an action when the button is pressed, set a click listener on the button object in the corresponding activity code:

    <Button
         android:id="@+id/button_id"
         android:layout_height="wrap_content"
         android:layout_width="wrap_content"
         android:text="@string/self_destruct" />
    
    

    See separate handout in the footnote for this week for “Manipulating GUI Objects, Listeners, Event Handlers and a note on Debugging”

  • Controlling Data input

    Every text field in android studio expects a certain type of text input, such as an email address, phone number, or just plain text. So it's important that you specify the input type of the text field and include an entry in the main.xml for each EditText that you require customised, input as can be seen in a sample code below.

    <EditText
             …….
             android:inputType="textCapWords"
             …….
    </EditText
    

    Options for Input Type

    textPersonName
    textPostalAddress
    textPassword
    textVisiblePassword
    textWebEditText
    textFilter
    textPhonetic
    number
    numberSigned
    numberDecimal
    phone
    datetime
    date
    time
    text
    textCapCharacters
    textCapWords
    textCapSentences
    textAutoCorrect
    textAutoComplete
    textMultiLine
    textImeMultiLine
    textNoSuggestions
    textUri
    textEmailAddress
    textEmailSubject
    textShortMessage
    textLongMessage

    Customising Appearance

    customising appearance of the widgets can be done by first adding borders to the widgets. This can be achieved by adding XML code to create a border around a TextView object. The best approach to this is to define the border in an XML file and then “refer” to this in an “attribute” of the component. The sample code below shows xml code snippet on how to add a border around a TextView object in an xml file.

    <TextView  
        	android:layout_width="fill_parent" 
        	android:layout_height="wrap_content" 
        	android:text="@string/hello"
        	android:background="@drawable/theborder"
     />
    

    The background attribute in the above code is “specified” by the xml file theborder

    The border.xml

    <shape xmlns:android="http://schemas.android.com/apk/res/android"> 
        <stroke android:width="1dp" 					
        android:color="#55771B" /> 
       <padding android:left="17dp" 					
    android:top="13dp" 
             	android:right="17dp" 					
    android:bottom="17dp" /> 
        <corners android:radius="14dp" /> 
    </shape>
    
  • Changing the Background

    Setting the background of your application to be something other than a “colour” can be achieved by using the background attribute as discussed before. The most efficient way to do this is again via an XML file as shown in 2 sample code below, the background patterns outline the layout then calls backrepeat.xml file to change the background.

    Background Patterns

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout 
    xmlns:android=http://schemas.android.com/apk/res/android
    	android:id=“@+id/mainView”
        	android:orientation="vertical"
        	android:layout_width="fill_parent"
        	android:layout_height="fill_parent"
       	android:background="@drawable/backrepeat">
    
    	………..
    
    </LinearLayout>
    

    backrepeat.xml

    <bitmap
    	xmlns:android="http://schemas.android.com/apk/res/android"
    	android:src="@drawable/greenmarbled1"
    	android:tileMode="repeat"
    />
    

    📷 Background Pattern

    Changing the value android:tileMode to mirror as shown below, produces a uniform appearance to the background.

    android:tileMode="repeat"
    

    📷 Uniform Background

    X
    Background Pattern Screenshot
    X
    Uniform Pattern Screenshot
  • ViewGroup

    The ViewGroup subclass is the base class for layouts, which are invisible containers that hold other Views (or other ViewGroups) and define their layout properties.

    Layouts

    There are a range of layouts that you can employ as an Android Developer. The available layouts in Android studio can be utilised in the construction of Graphical Interfaces are absolute, linear, relative, table and various others. These will be discussed in details.

    Absolute

    Absolute layout as the name suggests requires you to place the graphical components at specific locations on the screen of the Android device. So would add appropriate entries to your main.xml file.

    In the Android world the top left hand corner of the screen is given the coordinates (0,0). So specifying a value for layout_x will move the graphical component to the right and specifying a value for layout_y will move the component down the screen.

    In the XML text android:layout_x and android:layout_y specifies the absolute location of the top left corner of each graphical component that requires to be drawn.

    Let’s look at the code for the method you called from BlueJ, speedUp in the class Rider. The full code for this is actually a bit complicated, so here’s a simpler version that shows how this interaction works more clearly (you’ll see how the full version works shortly).

    Example

    <AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent">    
    <Button     	
         android:id="@+id/navigateBack"    
         android:text="Back"    	
         android:layout_x="15px"    	
         android:layout_y="10px"  
         android:layout_width="wrap_content" 
         android:layout_height="wrap_content"     />
    
    </Absolutelayout>
    
  • Frame

    Frame Layout is intended to display a single item at a time. You can display multiple items in your display using Frame layout but they may overlap depending where you position them. This may be ok for some applications but not for others. This approach may be useful for a splash screen at the start of a game.

    Linear

    Linear Layout organises the components horizontally or vertically in terms of rows and columns. The android:orientation entry controls this aspect.

    Linear Example

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    	android:orientation="vertical"
    	android:layout_width="fill_parent"
        	android:layout_height="fill_parent">
         	<Button 
        		android:id="@+id/navigateBack"
        		android:text="Back"
        		android:layout_width="wrap_content"
        		android:layout_height="wrap_content" 
        	/>
        	<TextView
        		android:text="Home Telephone"
        		android:layout_width="wrap_content"
        		android:layout_height="wrap_content"
    	/>
    	...................
    
    </Linearlayout>
    

    Relative

    With Relative layout the position of a graphical component can be specified in relation to another component.

    Relative Layout Example

    <RelativeLayout 
    	android:layout_width="fill_parent" 
    	android:layout_height="fill_parent" 
    	xmlns:android="http://schemas.android.com/apk/res/android">
    	<Button 
     		android:id="@+id/navigateBack"
     		android:text="Back"
     		android:textSize="20dip"
     		android:layout_width="wrap_content"
     		android:layout_height="wrap_content" 
    	/>
    	<TextView
       		android:id="@+id/homeTelephoneLabel"
       		android:text="Home Telephone"
       		android:textSize="20dip"
       		android:layout_width="wrap_content"
       		android:layout_height="wrap_content"
       		android:layout_below="@id/navigateBack" 
    	/>
     …….
    </RelativeLayout>
    

    For a full list of Relative Layout Parameters see the link below.

    🔗 RelativeLayout.LayoutParams

  • Table

    Table is another type of layout as the name suggests provides a way to lay graphical components out as rows and columns in a grid arrangement. The interface to some applications lends itself to this type of arrangement. The classic example here is the Dialer app in Android in which the keypad and the text pad is laid out in a grid format.

    Example Table Layout

    <TableLayout 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    xmlns:android="http://schemas.android.com/apk/res/android">
    	<TableRow>
    		……….
    	</TableRow>
    	<TableRow>
    		<TextView 
         			android:text="Home Telephone"
         			android:layout_width="wrap_content"
        			android:layout_height="wrap_content"
         			android:layout_column="1" 
       		 />
        		 <EditText
        			 android:id="@+id/editHomeTelephone"
         			android:width="100px"
         			android:layout_width="wrap_content"
         			android:layout_height="wrap_content" 
       		 />
    		……………….
    
    	</TableRow>
    
    </Tablelayout>
    

    ScrollView

    This is a Layout container for a view hierarchy that can be scrolled by the user. This means that it can be larger than the physical display.

    A ScrollView is a FrameLayout, meaning you should place one child in it containing the entire contents to scroll.

    This child may itself be a layout manager with a complex hierarchy of objects. A child that is often used is a LinearLayout in a vertical orientation, presenting a vertical array of top-level items that the user can scroll through.

    XML for ScrollView

    <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        tools:context=".ScrollTestActivity" >
        
        <LinearLayout
          	android:id="@+id/linearLayout2"
          	android:layout_width="fill_parent"
          	android:layout_height="wrap_content"
          	android:orientation="vertical" >
        	<TextView
           	 	android:layout_width="wrap_content"
            	android:layout_height="wrap_content"
            	android:text="@string/label1" 
           		android:textSize="40sp"
        	/>
    
    	<!– etc. ->
        </LinearLayout>
    
    </ScollView>
    
  • Landscape and Portrait

    Portrait and landscape layouts need to be handled separately by your application

    Include a Portrait layout and a Landscape layout

    Handling Portrait and Landscape modes

    Create 2 activity_main.xml files one for landscape mode and one for portrait mode and put these 2 activity_main.xml files into the res folder as shown below

    /res/layout-land/activity_main.xml
    /res/layout-port/activity_main.xml
    

    Android Studio

    Creating Separate Layouts for Landscape and Portrait
    Make sure you are in “Project Files” view and not “Android” view
    Directory name layout-land or layout-port
    Resource Type layout

    Detecting Orientation in code

    public void onConfigurationChanges(Configuration newConfig)
    {
    		Configuration c = 
    			getResources().getConfiguration();
    		if (c.configuration == 
    			Configuration.ORIENTATION_PORTRAIT)
    		{
    			// portrait
    		}
    		else if (c.configuration ==  
    			 Configuration.ORIENTATION_LANDSCAPE)
    		{
    			// landscape
    		}
    }
    

    Changing Orientation

    The following screenshots outline how to switch modes when you are running the Android Emulator.

    You can make use of the 2 rotate options shown on the right hand side of the emulator.

    📷 Portrait view

    📷 Landscape view

    🔗 Layout Test Projects

    X
    Portrait View Screenshot
    X
    Landscape View Screenshot
  • Events

    Handling Events

    “On Android, there's more than one way to intercept the events from a user's interaction with your application. When considering events within your user interface, the approach is to capture the events from the specific View object that the user interacts with. The View class provides the means to do so.”

    On Android studio, there’s different ways to intercept with events when user interact with your application. The approach is to capture the events from a specific View object that the user interacts with within your user interface. This can be achieved by using the View class method.

    There are several public callback methods within the view classes that are called by Android framework when an e/object is triggered within the user interfaces. For example, when a View method (such as a Button) is clicked, the onClick() is called on that object. And for this to work, you will need to extend the class and override the method and use the View class which contains a collection of nested interfaces called event listeners that are used to capture user inputs during interactions within the user interfaces.

    Event Listener

    “An event listener is an interface in the View class that contains a single callback method. These methods will be called by the Android framework when the View to which the listener has been registered is triggered by user interaction with the item in the UI.”1

    onClick/onClickListener

    onClick()From View.OnClickListener is called when the user either touches (when in touch mode), click the item or focuses upon the item with the navigation-keys or trackball and presses the suitable "enter" key or presses down on the trackball.

    Click Events
    Activity class implements OnClickListener interface
    Implements the onClick method
    SetOnClickListener for each interested object

    onClick

    public void onClick (View v)
    {
    	if (v == button3)
    	{
    		// do domething
    	}	
    }
    

    Long Click

    onLongClick()From View.OnLongClickListener. This is called when the user either touches and holds the item (when in touch mode), or focuses upon the item with the navigation-keys or trackball and presses and holds the suitable "enter" key or presses and holds down on the trackball (for one second).

    OnLongClickListener/onLongClick
    Activity class implements OnLongClickListener interface
    Implements the onLongClick method
    SetOnLongClickListener for each interested object

    onLongClick

    public boolean onLongClick (View v)
    {
    boolean status = false;
    	if (v == button4)
    	{
    		// do domething
    		status = true;
    	}
    	return status;
    }
    

    onTouch/OnTouchListener
    Activity class implements OnTouchListener interface
    Implements the onTouch method and returns true if event “consumed”
    SetOnTouchListener for each interested object

    onTouch

    public boolean onTouch (View v)
    {
    boolean status = false;
    	if (v == button3)
    	{
    		// do domething
    		status = true;
    	}
    	return status;
    }
    

    1. http://developer.android.com/guide/topics/ui/ui-events.html

  • Parsing

    Parsing is when you analyse text by looking for sequences of tokens. The analysis is being carried out to determine the grammatical structure of the text. In our case we will be analysing XML text to “pick” out useful data.

    XML Data

    See XML Data for Assignment.

    PullParser

    Android supports the XML Pull Parser interface. The Pull Parser approach requires the developer to “look for” events such as:
    Start of Document
    End of Document
    Start Tag
    Etc.

    PullParser Setup

    XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
    factory.setNamespaceAware(true);
    XmlPullParser xpp = factory.newPullParser();
    xpp.setInput( new StringReader ( dataToParse ) );
    

    Where dataToParse is a String object.

    PullParser

    Android supports the XML Pull Parser interface. There are a number of useful methods
    getEventType()
    getName()
    next()
    nextText()

    PullParser

    The XML Pull Parser approach generates events. It is these events that are of interest to the programmer who requires to extract information from the various tags in an XML document.

    next() provides access to high level parsing events

    nextText() provides the text if the current event is START_TAG

    Note how next() is used in the examples
    The current event state of the parser can be determined by calling the getEventType() method.
    Initially, the parser is in the START_DOCUMENT state.
    The method next() advances the parser to the next event. The int value returned from next determines the current parser state and is identical to the value returned from following calls to getEventType ().

    The following event types are seen by next()
    START_TAG An XML start tag was read.
    TEXT Text content was read; the text content can be retrieved using the getText() method. (when in validating mode next() will not report ignorable whitespace, use nextToken() instead)
    END_TAG An end tag was read
    END_DOCUMENT No more events are available

    Sample Code

    XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
    
             factory.setNamespaceAware(true);
             XmlPullParser xpp = factory.newPullParser();
             xpp.setInput( new StringReader ( "<foo>Hello World!</foo>" ) );
             int eventType = xpp.getEventType();
             while (eventType != XmlPullParser.END_DOCUMENT) {
              if(eventType == XmlPullParser.START_DOCUMENT) {
                  System.out.println("Start document");
              } else if(eventType == XmlPullParser.START_TAG) {
                  System.out.println("Start tag "+xpp.getName());
              } else if(eventType == XmlPullParser.END_TAG) {
                  System.out.println("End tag "+xpp.getName());
              } else if(eventType == XmlPullParser.TEXT) {
                  System.out.println("Text "+xpp.getText());
              }
              eventType = xpp.next();
             }
             System.out.println("End document")
    

    Full Sample Code can be viewed here

    Example

    Let’s have a look at more complex example

    XML String

    Let’s assume that we need to “parse” the following XML string

    <WidgetCollection>
         <Widget>
             <Bolt>M8 x 100</Bolt>
             <Nut>M8 Hex</Nut>
             <Washer>M8 Penny Washers</Washer>
         </Widget>
    </WidgetCollection>
    

    Information Required

    The information that we want to extract from the code above is:
    M8 x 100
    M8 Hex
    M8 Penny Washers

    So we probably need a Widget class to store these data and a collection to store the widgets.

    Widget Class

    public class Widget 
    {
    private String bolt;
    private String nut;
    private String washer;
    	
    // Constructors plus get and set methods
    }
    

    Collection Class

    import java.util.LinkedList;
    private LinkedList<Widget> alist;
    alist = new LinkedList<Widget> ();
      alist.add(aWidget); 
    

    Retrieving the Data

    public LinkedList<Widget> retrieveWidget() 
    {
        return alist;
    }
    

    Class and Collection

    You need to decide where to put:
    the creation of the Widget class
    the creation of the Collection

    See lab exercise.

    🔗 XmlPullParser

School of Computing, Engineering and Built Environment