Android Application Development in step by step info

Part 03

Android Custom Components

Android offers a great list of pre-built widgets like Button, TextView, EditText, ListView, CheckBox,RadioButton, Gallery, Spinner, AutoCompleteTextViewetc. which you can use directly in your Android application development, but there may be a situation when you are not satisfied with existing functionality of any of the available widgets. Android provides you with means of creating your own custom components which you can customized to suit your needs.

If you only need to make small adjustments to an existing widget or layout, you can simply subclass the widget or layout and override its methods which will give you precise control over the appearance and function of a screen element.

This tutorial explains you how to create custom Views and use them in your application using simple and easy steps.

Creating a Simple Custom Component

The simplest way to create your custom component is to extend an existing widget class or subclass with your own class if you want to extend the functionality of existing widget like Button, TextView, EditText,ListView, CheckBox etc. otherwise you can do everything yourself by starting with theandroid.view.View class.

At its simplest form you will have to write your constructors corresponding to all the constructors of the base class. For example if you are going to extendTextView to create a DateView then following three constructors will be created for DateView class:

public class DateView extends TextView {

   public DateView(Context context) {

      super(context);

      //--- Additional custom code --

   }

 

   public DateView(Context context,AttributeSet attrs) {

      super(context, attrs);

      //--- Additional custom code --

   }

 

   public DateView(Context context,AttributeSet attrs, int defStyle) {

      super(context, attrs, defStyle);

      //--- Additional custom code --

   }

}

Because you have created DateView as child ofTextView so it will have access on all the attributes, methods and events related to TextView and you will be able to use them without any further implementation. You will implement additional custom functionality inside your own code as explained in the given examples below.

If you have requirement for implementing custom drawing/sizing for your custom widgets then you need to override onMeasure(int widthMeasureSpecintheightMeasureSpec) and onDraw(Canvas canvas)methods. If you are not going to resize or change the shape of your built-in component then you do not need either of these methods in your custom component.

The onMeasure() method coordinate with the layout manager to report the widget's width and height, and you need to call setMeasuredDimension(int width, intheight) from inside this method to report the dimensions.

You can then execute your custom drawing inside theonDraw(Canvas canvas) method, whereandroid.graphis.Canvas is pretty similar to its counterpart in Swing, and has methods such asdrawRect(), drawLine(), drawString(), drawBitmap() etc. which you can use to draw your component.

Once you are done with the implementation of a custom component by extending existing widget, you will be able to instantiate these custom components in two ways in your application development:

Instantiate using code inside activity class

It is very similar way of instantiating custom component the way you instantiate built-in widget in your activity class. For example you can use following code to instantiate above defined custom component:

@Override

 protected void onCreate(BundlesavedInstanceState) {

     super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    

     DateView dateView = newDateView(this);

     setContentView(dateView);

 }

Check this example to understand how to Instantiate a Basic Android Custom Component using code inside an activity.

Instantiate using Layout XML file

Traditionally you use Layout XML file to instantiate your built-in widgets, same concept will apply on your custom widgets as well so you will be able to instantiate your custom component using Layout XML file as explained below. Herecom.example.dateviewdemo is the package where you have put all the code related to DateView class andDateView is Java class name where you have put complete logic of your custom component.

<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"

    android:paddingLeft="@dimen/activity_horizontal_margin"

    android:paddingRight="@dimen/activity_horizontal_margin"

    android:paddingTop="@dimen/activity_vertical_margin"

    tools:context=".MainActivity" >

   

    <com.example.dateviewdemo.DateView

     android:layout_width="match_parent"

     android:layout_height="wrap_content"

     android:textColor="#fff"

     android:textSize="40sp"

     android:background="#000"

     />

</RelativeLayout>

It is important to note here that we are using allTextView attributes along with custom component without any change. Similar way you will be able to use all the events, and methods along with DateViewcomponent.

Check this example to understand how to Instantiate a Basic Android Custom Component using Layout XML file.

Custom Component with Custom Attributes

We have seen how we can extend functionality of built-in widgets but in both the examples given above we saw that extended component can make use of all the default attributes of its parent class. But consider a situation when you want to create your own attribute from scratch. Below is a simple procedure to create and use new attributes for Android Custom components. Consider we want to introduce three attributes and will use them as shown below:

<com.example.dateviewdemo.DateView

   android:layout_width="match_parent"

   android:layout_height="wrap_content"

   android:textColor="#fff"

   android:textSize="40sp"

   custom:delimiter="-"

   custom:fancyText="true"

/>

Step 1

The first step to enable us to use our custom attributes is to define them in a new xml file under res/values/and call it attrs.xml. Let's have a look on an example attrs.xml file:

<?xml version="1.0" encoding="utf-8"?>

<resources>

   <declare-styleable name="DateView">

   <attr name="delimiter" format="string"/>

   <attr name="fancyText" format="boolean"/>

   </declare-styleable>

</resources>

Here the name=value is what we want to use in our Layout XML file as attribute, and the format=type is the type of attribute.

Step 2

Your second step will be to read these attributes from Layout XML file and set them for the component. This logic will go in the constructors that get passed anAttributeSet, since that is what contains the XML attributes. To read the values in the XML, you need to first create a TypedArray from the AttributeSet, then use that to read and set the values as shown in the below example code:

TypedArray a =context.obtainStyledAttributes(attrs,R.styleable.DateView);

 

final int N = a.getIndexCount();

for (int i = 0; i < N; ++i)

{

   int attr = a.getIndex(i);

   switch (attr)

   {

      case R.styleable.DateView_delimiter:

         String delimiter =a.getString(attr);

         //...do something with delimiter...

         break;

      case R.styleable.DateView_fancyText:

         boolean fancyText =a.getBoolean(attr, false);

         //...do something withfancyText...

         break;

   }

}

a.recycle();

Step 3

Finally you can use your defined attributes in your Layout XML file as follows:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:tools="http://schemas.android.com/tools"

    xmlns:custom="http://schemas.android.com/apk/res/com.example.dateviewdemo"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:paddingBottom="@dimen/activity_vertical_margin"

    android:paddingLeft="@dimen/activity_horizontal_margin"

    android:paddingRight="@dimen/activity_horizontal_margin"

    android:paddingTop="@dimen/activity_vertical_margin"

    tools:context=".MainActivity" >

   

    <com.example.dateviewdemo.DateView

    android:layout_width="match_parent"

    android:layout_height="wrap_content"

    android:textColor="#fff"

    android:textSize="40sp"

    custom:delimiter="-"

    custom:fancyText="true"

    />

 

</RelativeLayout>

The important part is xmlns:custom="http://schemas.android.com/apk/res/com.example.dateviewdemo". Note that http://schemas.android.com/apk/res/ will remain as is, but last part will be set to your package name and also that you can use anything after xmlns:, in this example I usedcustom, but you could use any name you like.

 Android UI Layouts

The basic building block for user interface is a Viewobject which is created from the View class and occupies a rectangular area on the screen and is responsible for drawing and event handling. View is the base class for widgets, which are used to create interactive UI components like buttons, text fields, etc.

The ViewGroup is a subclass of View and provides invisible container that hold other Views or otherViewGroups and define their layout properties.

At third level we have different layouts which are subclasses of ViewGroup class and a typical layout defines the visual structure for an Android user interface and can be created either at run time usingView/ViewGroup objects or you can declare your layout using simple XML file main_layout.xml which is located in the res/layout folder of your project.

This tutorial is more about creating your GUI based on layouts defined in XML file. A layout may contain any type of widgets such as buttons, labels, textboxes, and so on. Following is a simple example of XML file havingLinearLayout:

<?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="vertical" >

        <TextView android:id="@+id/text"

        android:layout_width="wrap_content"

       android:layout_height="wrap_content"

        android:text="This is a TextView" />

        <Button android:id="@+id/button"

        android:layout_width="wrap_content"

       android:layout_height="wrap_content"

        android:text="This is a Button" />

       

        <!-- More GUI components go here  -->

       

</LinearLayout>

Once your layout is defined, you can load the layout resource from your application code, in yourActivity.onCreate() callback implementation as shown below:

public void onCreate(BundlesavedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

}

Android Layout Types

There are number of Layouts provided by Android which you will use in almost all the Android applications to provide different view, look and feel.

S.N.

Layout & Description

1

Linear Layout
LinearLayout is a view group that aligns all children in a single direction, vertically or horizontally.

2

Relative Layout
RelativeLayout is a view group that displays child views in relative positions.

3

Table Layout
TableLayout is a view that groups views into rows and columns.

4

Absolute Layout
AbsoluteLayout enables you to specify the exact location of its children.

5

Frame Layout
The FrameLayout is a placeholder on screen that you can use to display a single view.

6

List View
ListView is a view group that displays a list of scrollable items.

7

Grid View
GridView is a ViewGroup that displays items in a two-dimensional, scrollable grid.

Layout Attributes

Each layout has a set of attributes which define the visual properties of that layout. There are few common attributes among all the layouts and their are other attributes which are specific to that layout. Following are common attributes and will be applied to all the layouts:

Attribute

Description

android:id

This is the ID which uniquely identifies the view.

android:layout_width

This is the width of the layout.

android:layout_height

This is the height of the layout

android:layout_marginTop

This is the extra space on the top side of the layout.

android:layout_marginBottom

This is the extra space on the bottom side of the layout.

android:layout_marginLeft

This is the extra space on the left side of the layout.

android:layout_marginRight

This is the extra space on the right side of the layout.

android:layout_gravity

This specifies how child Views are positioned.

android:layout_weight

This specifies how much of the extra space in the layout should be allocated to the View.

android:layout_x

This specifies the x-coordinate of the layout.

android:layout_y

This specifies the y-coordinate of the layout.

android:layout_width

This is the width of the layout.

android:layout_width

This is the width of the layout.

android:paddingLeft

This is the left padding filled for the layout.

android:paddingRight

This is the right padding filled for the layout.

android:paddingTop

This is the top padding filled for the layout.

android:paddingBottom

This is the bottom padding filled for the layout.

Here width and height are the dimension of the layout/view which can be specified in terms of dp (Density-independent Pixels), sp ( Scale-independent Pixels), pt ( Points which is 1/72 of an inch), px( Pixels), mm ( Millimeters) and finally in (inches).

You can specify width and height with exact measurements but more often, you will use one of these constants to set the width or height:

android:layout_width=wrap_content tells your view to size itself to the dimensions required by its content.

android:layout_width=fill_parent tells your view to become as big as its parent view.

Gravity attribute plays important role in positioning the view object and it can take one or more (separated by '|') of the following constant values.

Constant

Value

Description

top

0x30

Push object to the top of its container, not changing its size.

bottom

0x50

Push object to the bottom of its container, not changing its size.

left

0x03

Push object to the left of its container, not changing its size.

right

0x05

Push object to the right of its container, not changing its size.

center_vertical

0x10

Place object in the vertical center of its container, not changing its size.

fill_vertical

0x70

Grow the vertical size of the object if needed so it completely fills its container.

center_horizontal

0x01

Place object in the horizontal center of its container, not changing its size.

fill_horizontal

0x07

Grow the horizontal size of the object if needed so it completely fills its container.

center

0x11

Place the object in the center of its container in both the vertical and horizontal axis, not changing its size.

fill

0x77

Grow the horizontal and vertical size of the object if needed so it completely fills its container.

clip_vertical

0x80

Additional option that can be set to have the top and/or bottom edges of the child clipped to its container's bounds. The clip will be based on the vertical gravity: a top gravity will clip the bottom edge, a bottom gravity will clip the top edge, and neither will clip both edges.

clip_horizontal

0x08

Additional option that can be set to have the left and/or right edges of the child clipped to its container's bounds. The clip will be based on the horizontal gravity: a left gravity will clip the right edge, a right gravity will clip the left edge, and neither will clip both edges.

start

0x00800003

Push object to the beginning of its container, not changing its size.

end

0x00800005

Push object to the end of its container, not changing its size.

View Identification

A view object may have a unique ID assigned to it which will identify the View uniquely within the tree. The syntax for an ID, inside an XML tag is:

android:id="@+id/my_button"

Following is a brief description of @ and + signs:

The at-symbol (@) at the beginning of the string indicates that the XML parser should parse and expand the rest of the ID string and identify it as an ID resource.

The plus-symbol (+) means that this is a new resource name that must be created and added to our resources. To create an instance of the view object and capture it from the layout, use the following:

Button myButton = (Button)findViewById(R.id.my_button);

 Android UI Controls

An Android application user interface is everything that the user can see and interact with. You have learned about the various layouts that you can use to position your views in an activity. This chapter will give you detail on various views.

View is an object that draws something on the screen that the user can interact with and a ViewGroup is an object that holds other View (and ViewGroup) objects in order to define the layout of the user interface.

You define your layout in an XML file which offers a human-readable structure for the layout, similar to HTML. For example, a simple vertical layout with a text view and a button looks like this:

<?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="vertical" >

  

   <TextView android:id="@+id/text"

      android:layout_width="wrap_content"

      android:layout_height="wrap_content"

      android:text="I am a TextView" />

   <Button android:id="@+id/button"

      android:layout_width="wrap_content"

      android:layout_height="wrap_content"

      android:text="I am a Button" />

</LinearLayout>

Android UI Controls

There are number of UI controls provided by Android that allow you to build the graphical user interface for your app.

S.N.

UI Control & Description

1

TextView
This control is used to display text to the user.

2

EditText
EditText is a predefined subclass of TextViewthat includes rich editing capabilities.

3

AutoCompleteTextView
The AutoCompleteTextView is a view that is similar to EditText, except that it shows a list of completion suggestions automatically while the user is typing.

4

Button
A push-button that can be pressed, or clicked, by the user to perform an action.

5

ImageButton
AbsoluteLayout enables you to specify the exact location of its children.

6

CheckBox
An on/off switch that can be toggled by the user. You should use checkboxes when presenting users with a group of selectable options that are not mutually exclusive.

7

ToggleButton
An on/off button with a light indicator.

8

RadioButton
The RadioButton has two states: either checked or unchecked.

9

RadioGroup
A RadioGroup is used to group together one or more RadioButtons.

10

ProgressBar
The ProgressBar view provides visual feedback about some ongoing tasks, such as when you are performing a task in the background.

11

Spinner
A drop-down list that allows users to select one value from a set.

12

TimePicker
The TimePicker view enables users to select a time of the day, in either 24-hour mode or AM/PM mode.

13

DatePicker
The DatePicker view enables users to select a date of the day.

Create UI Controls

As explained in previous chapter, a view object may have a unique ID assigned to it which will identify the View uniquely within the tree. The syntax for an ID, inside an XML tag is:

android:id="@+id/text_id"

To create a UI Control/View/Widget you will have to define a view/widget in the layout file and assign it a unique ID as follows:

<?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="vertical" >

  

   <TextView android:id="@+id/text_id"

      android:layout_width="wrap_content"

      android:layout_height="wrap_content"

      android:text="I am a TextView" />

</LinearLayout>

Then finally create an instance of the Control object and capture it from the layout, use the following:

TextView myText = (TextView)findViewById(R.id.text_id);

Android Event Handling

Events are a useful way to collect data about a user's interaction with interactive components of your app, like button presses or screen touch etc. The Android framework maintains an event queue into which events are placed as they occur and then each event is removed from the queue on a first-in, first-out (FIFO) basis. You can capture these events in your program and take appropriate action as per requirements.

There are following three concepts related to Android Event Management:

Event Listeners: The View class is mainly involved in building up a Android GUI, same View class provides a number of Event Listeners. The Event Listener is the object that receives notification when an event happes.

Event Listeners Registration: Event Registration is the process by which an Event Handler gets registered with an Event Listener so that the handler is called when the Event Listener fires the event.

Event Handlers: When an event happens and we have registered and event listener fo the event, the event listener calls the Event Handlers, which is the method that actually handles the event.

Event Listeners & Event Handlers

Event Handler

Event Listener & Description

onClick()

OnClickListener()
This is called when the user either clicks or touches or focuses upon any widget like button, text, image etc. You will use onClick() event handler to handle such event.

onLongClick()

OnLongClickListener()
This is called when the user either clicks or touches or focuses upon any widget like button, text, image etc. for one or more seconds. You will useonLongClick() event handler to handle such event.

onFocusChange()

OnFocusChangeListener()
This is called when the widgetlooses its focus ie. user goes away from the view item. You will useonFocusChange() event handler to handle such event.

onKey()

OnFocusChangeListener()
This is called when the user is focused on the item and presses or releases a hardware key on the device. You will use onKey() event handler to handle such event.

onTouch()

OnTouchListener()
This is called when the user presses the key, releases the key, or any movement gesture on the screen. You will use onTouch() event handler to handle such event.

onMenuItemClick()

OnMenuItemClickListener()
This is called when the user selects a menu item. You will useonMenuItemClick() event handler to handle such event.

There are many more event listeners available as a part of View class like OnHoverListener,OnDragListener etc which may be needed for your application. So I recommend to refer official documentation for Android application development in case you are going to develop a sophisticated apps.

Event Listeners Registration:

Event Registration is the process by which an Event Handler gets registered with an Event Listener so that the handler is called when the Event Listener fires the event. Though there are several tricky ways to register your event listener for any event, but I'm going to list down only top 3 ways, out of which you can use any of them based on the situation.

Using an Anonymous Inner Class

Activity class implements the Listener interface.

Using Layout file activity_main.xml to specify event handler directly.

Below section will provide you detailed examples on all the three scenarios:

Event Handling Examples

Event Listeners Registration Using an Anonymous Inner Class

Here you will create an anonymous implementation of the listener and will be useful if each class is applied to a single control only and you have advantage to pass arguments to event handler. In this approach event handler methods can access private data of Activity. No reference is needed to call to Activity.

But if you applied the handler to more than one control, you would have to cut and paste the code for the handler and if the code for the handler is long, it makes the code harder to maintain.

Following are the simple steps to show how we will make use of separate Listener class to register and capture click event. Similar way you can implement your listener for any other required event type.

Step

Description

1

You will use Eclipse IDE to create an Android application and name it as EventDemo under a package com.example.eventdemo as explained in the Hello World Example chapter.

2

Modify src/MainActivity.java file to add click event listeners and handlers for the two buttons defined.

3

Modify the detault content of res/layout/activity_main.xml file to include Android UI controls.

4

Define required constants in res/values/strings.xml file

5

Run the application to launch Android emulator and verify the result of the changes done in theaplication.

Following is the content of the modified main activity file src/com.example.eventdemo/MainActivity.java. This file can include each of the fundamental lifecycle methods.

package com.example.eventdemo;

 

import android.os.Bundle;

import android.app.Activity;

import android.view.Menu;

import android.view.View;

import android.widget.Button;

import android.widget.TextView;

 

public class MainActivity extends Activity {

 

    @Override

    protected void onCreate(BundlesavedInstanceState) {

        super.onCreate(savedInstanceState);

       setContentView(R.layout.activity_main);

       

        //--- find both the buttons---

        Button sButton = (Button)findViewById(R.id.button_s);

        Button lButton = (Button)findViewById(R.id.button_l);

       

        // -- register click event with first button ---

        sButton.setOnClickListener(newView.OnClickListener() {

           public void onClick(View v) {

               // --- find the text view --

               TextView txtView = (TextView) findViewById(R.id.text_id);

               // -- change text size --

               txtView.setTextSize(14);

           }

        });

       

        // -- register click event with second button ---

        lButton.setOnClickListener(newView.OnClickListener() {

           public void onClick(View v) {

               // --- find the text view --

               TextView txtView = (TextView) findViewById(R.id.text_id);

               // -- change text size --

               txtView.setTextSize(24);

           }

        });

    }

 

    @Override

    public boolean onCreateOptionsMenu(Menu menu) {

       getMenuInflater().inflate(R.menu.main, menu);

        return true;

    }

   

}

Following will be the content of res/layout/activity_main.xml file:

<?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="vertical" >

 

 

    <Button

    android:id="@+id/button_s"

    android:layout_height="wrap_content"

    android:layout_width="match_parent"

    android:text="@string/button_small"/>

   

    <Button

    android:id="@+id/button_l"

    android:layout_height="wrap_content"

    android:layout_width="match_parent"

    android:text="@string/button_large"/>

 

    <TextView

    android:id="@+id/text_id"

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:capitalize="characters"

    android:text="@string/hello_world" />

 

</LinearLayout>

Following will be the content of res/values/strings.xml to define two new constants:

<?xml version="1.0" encoding="utf-8"?>

<resources>

 

    <string name="app_name">EventDemo</string>

    <string name="action_settings">Settings</string>

    <string name="hello_world">Hello world!</string>

   <string name="button_small">Small Font</string>

   <string name="button_large">Large Font</string>

  

</resources>

Following is the default content ofAndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

    package="com.example.guidemo"

    android:versionCode="1"

    android:versionName="1.0" >

 

    <uses-sdk

        android:minSdkVersion="8"

        android:targetSdkVersion="17" />

 

    <application

        android:allowBackup="true"

        android:icon="@drawable/ic_launcher"

        android:label="@string/app_name"

        android:theme="@style/AppTheme" >

        <activity

           android:name="com.example.guidemo.MainActivity"

            android:label="@string/app_name" >

            <intent-filter>

                <actionandroid:name="android.intent.action.MAIN" />

 

                <categoryandroid:name="android.intent.category.LAUNCHER" />

            </intent-filter>

        </activity>

    </application>

 

</manifest>

Let's try to run your EventDemo application. I assume you had created your AVD while doing environment setup. To run the app from Eclipse, open one of your project's activity files and click Run icon from the toolbar. Eclipse installs the app on your AVD and starts it and if everything is fine with your setup and application, it will display following Emulator window:

Now you try to click on two buttons one by one and you will see that font of the Hello World text will change, which happens because registered click event handler method is being called against each click event.

Registration Using the Activity Implements Listener Interface

Here your Activity class implements the Listener interface and you put the handler method in the main Activity and then you call setOnClickListener(this).

This approach is fine if your application has only a single control of that Listener type otherwise you will have to do further programming to check which control has generated event. Second you cannot pass arguments to the Listener so, again, works poorly for multiple controls.

Following are the simple steps to show how we will implement Listener class to register and capture click event. Similar way you can implement your listener for any other required event type.

Step

Description

1

We do not need to create this application from scratch, so let's make use of above created Android application EventDemo.

2

Modify src/MainActivity.java file to add click event listeners and handlers for the two buttons defined.

3

We are not making any change in res/layout/activity_main.xml, it will remain as shown above.

4

We are also not making any change in res/values/strings.xml file, it will also remain as shown above.

5

Run the application to launch Android emulator and verify the result of the changes done in theaplication.

Following is the content of the modified main activity file src/com.example.eventdemo/MainActivity.java. This file can include each of the fundamental lifecycle methods.

package com.example.eventdemo;

 

import android.os.Bundle;

import android.app.Activity;

import android.view.Menu;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.TextView;

 

public class MainActivity extends Activity implements OnClickListener {

 

    @Override

    protected void onCreate(BundlesavedInstanceState) {

        super.onCreate(savedInstanceState);

       setContentView(R.layout.activity_main);

       

        //--- find both the buttons---

        Button sButton = (Button)findViewById(R.id.button_s);

        Button lButton = (Button)findViewById(R.id.button_l);

       

       

        // -- register click event with first button ---

        sButton.setOnClickListener(this);

        // -- register click event with second button ---

        lButton.setOnClickListener(this);

    }

       

    //--- Implement the OnClickListenercallback

    public void onClick(View v) {

       if(v.getId() == R.id.button_s)

       {

            // --- find the text view --

            TextView txtView = (TextView)findViewById(R.id.text_id);

            // -- change text size --

            txtView.setTextSize(14);

            return;

       }

       if(v.getId() == R.id.button_l)

       {

            // --- find the text view --

            TextView txtView = (TextView)findViewById(R.id.text_id);

            // -- change text size --

            txtView.setTextSize(24);

            return;

       }

    }

 

    @Override

    public boolean onCreateOptionsMenu(Menu menu) {

       getMenuInflater().inflate(R.menu.main, menu);

        return true;

    }

   

}

Now again let's try to run your EventDemoapplication. I assume you had created your AVD while doing environment setup. To run the app from Eclipse, open one of your project's activity files and click Runicon from the toolbar. Eclipse installs the app on your AVD and starts it and if everything is fine with your setup and application, it will display following Emulator window:

Now you try to click on two buttons one by one and yuwill see that font of the Hello World text will change, which happens because registered click event handler method is being called against each click event.

Registration Using Layout file activity_main.xml

Here you put your event handlers in Activity class without implementing a Listener interface or call to any listener method. Rather you will use the layout file (activity_main.xml) to specify the handler method via the android:onClick attribute for click event. You can control click events differently for different control by passing different event handler methods.

The event handler method must have a void return type and take a View as an argument. However, the method name is arbitrary, and the main class need not implement any particular interface.

This approach does not allow you to pass arguments to Listener and for the Android developers it will be difficult to know which method is the handler for which control until they look into activity_main.xml file. Second, you can not handle any other event except click event using this approach.

Following are the simple steps to show how we can make use of layout file Main.xml to register and capture click event.

Step

Description

1

We do not need to create this application from scratch, so let's make use of above created Android application EventDemo.

2

Modify src/MainActivity.java file to add click event listeners and handlers for the two buttons defined.

3

Modify layout file res/layout/activity_main.xml, to specify event handlers for the two buttons.

4

We are also not making any change in res/values/strings.xml file, it will also remain as shown above.

5

Run the application to launch Android emulator and verify the result of the changes done in theaplication.

Following is the content of the modified main activity file src/com.example.eventdemo/MainActivity.java. This file can include each of the fundamental lifecycle methods.

package com.example.eventdemo;

 

import android.os.Bundle;

import android.app.Activity;

import android.view.Menu;

import android.view.View;

import android.widget.Button;

import android.widget.TextView;

 

public class MainActivity extends Activity{

 

    @Override

    protected void onCreate(BundlesavedInstanceState) {

        super.onCreate(savedInstanceState);

       setContentView(R.layout.activity_main);

    }

       

    //--- Implement the event handler for the first button.

    public void doSmall(View v)  {

       // --- find the text view --

       TextView txtView = (TextView)findViewById(R.id.text_id);

       // -- change text size --

       txtView.setTextSize(14);

       return;

   }

   //--- Implement the event handler for the second button.

   public void doLarge(View v)  {

       // --- find the text view --

       TextView txtView = (TextView)findViewById(R.id.text_id);

       // -- change text size --

       txtView.setTextSize(24);

       return;

   }

 

    @Override

    public boolean onCreateOptionsMenu(Menu menu) {

       getMenuInflater().inflate(R.menu.main, menu);

        return true;

    }

   

}

Following will be the content of res/layout/activity_main.xml file. Here we have to addandroid:onClick="methodName" for both the buttons, which will register given method names as click event handlers.

<?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="vertical" >

 

 

    <Button

    android:id="@+id/button_s"

    android:layout_height="wrap_content"

    android:layout_width="match_parent"

    android:text="@string/button_small"

    android:onClick="doSmall"/>

   

    <Button

    android:id="@+id/button_l"

    android:layout_height="wrap_content"

    android:layout_width="match_parent"

    android:text="@string/button_large"

    android:onClick="doLarge"/>

 

    <TextView

    android:id="@+id/text_id"

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:capitalize="characters"

    android:text="@string/hello_world" />

 

</LinearLayout>

Again let's try to run your EventDemo application. I assume you had created your AVD while doing environment setup. To run the app from Eclipse, open one of your project's activity files and click Run icon from the toolbar. Eclipse installs the app on your AVD and starts it and if everything is fine with your setup and application, it will display following Emulator window:

Now you try to click on two buttons one by one and you will see that font of the Hello World text will change, which happens because registered click event handler method is being called against each click event.

Android Drag and Drop

Android drag/drop framework allows your users to move data from one View to another View in the current layout using a graphical drag and drop gesture. The framework includes following three important components to support drag & drop functionality:

Drag event class:

Drag listeners:

Helper methods and classes:

The Drag/Drop Process

There are basically four steps or states in the drag and drop process:

Started: This event occurs when you start dragging an item in a layout, your application calls startDrag() method to tell the system to start a drag. The arguments inside startDrag() method provide the data to be dragged, metadata for this data, and a callback for drawing the drag shadow.

The system first responds by calling back to your application to get a drag shadow. It then displays the drag shadow on the device.

Next, the system sends a drag event with action type ACTION_DRAG_STARTED to the registered drag event listeners for all the View objects in the current layout.

To continue to receive drag events, including a possible drop event, a drag event listener must return true, If the drag event listener returns false, then it will not receive drag events for the current operation until the system sends a drag event with action type ACTION_DRAG_ENDED.

Continuing: The user continues the drag. System sends ACTION_DRAG_ENTERED action followed by ACTION_DRAG_LOCATION action to the registered drag event listener for the View where dragging point enters. The listener may choose to alter its View object's appearance in response to the event or can react by highlighting its View.

The drag event listener receives aACTION_DRAG_EXITED action after the user has moved the drag shadow outside the bounding box of the View.

Dropped: The user releases the dragged item within the bounding box of a View. The system sends the View object's listener a drag event with action type ACTION_DROP.

Ended: Just after the action type ACTION_DROP, the system sends out a drag event with action type ACTION_DRAG_ENDED to indicate that the drag operation is over.

The DragEvent Class

The DragEvent represents an event that is sent out by the system at various times during a drag and drop operation. This class provides few Constants and important methods which we use during Drag/Drop process.

Constants

Following are all constants integers available as a part of DragEvent class.

S.N.

Constants & Description

1

ACTION_DRAG_STARTED 
Signals the start of a drag and drop operation.

2

ACTION_DRAG_ENTERED 
Signals to a View that the drag point has entered the bounding box of the View.

3

ACTION_DRAG_LOCATION 
Sent to a View after ACTION_DRAG_ENTERED if the drag shadow is still within the View object's bounding box.

4

ACTION_DRAG_EXITED 
Signals that the user has moved the drag shadow outside the bounding box of the View.

5

ACTION_DROP 
Signals to a View that the user has released the drag shadow, and the drag point is within the bounding box of the View.

6

ACTION_DRAG_ENDED 
Signals to a View that the drag and drop operation has concluded.

Methods

Following are few important and most frequently used methods available as a part of DragEvent class.

S.N.

Constants & Description

1

int getAction() 
Inspect the action value of this event..

2

ClipData getClipData() 
Returns the ClipData object sent to the system as part of the call to startDrag().

3

ClipDescription getClipDescription() 
Returns the ClipDescription object contained in the ClipData.

4

boolean getResult() 
Returns an indication of the result of the drag and drop operation.

5

float getX() 
Gets the X coordinate of the drag point.

6

float getY() 
Gets the Y coordinate of the drag point.

7

String toString() 
Returns a string representation of this DragEventobject.

Listening for Drag Event

If you want any of your views within a Layout should respond Drag event then your view either implementsView.OnDragListener or setuponDragEvent(DragEvent) callback method. When the system calls the method or listener, it passes to them aDragEvent object explained above. You can have both a listener and a callback method for View object. If this occurs, the system first calls the listener and then defined callback as long as listener returns true.

The combination of the onDragEvent(DragEvent)method and View.OnDragListener is analogous to the combination of the onTouchEvent() andView.OnTouchListener used with touch events in old versions of Android.

Starting a Drag Event

You start with creating a ClipData and ClipData.Itemfor the data being moved. As part of the ClipDataobject, supply metadata that is stored in aClipDescription object within the ClipData. For a drag and drop operation that does not represent data movement, you may want to use null instead of an actual object.

Next either you can extend extendView.DragShadowBuilder to create a drag shadow for dragging the view or simply you can useView.DragShadowBuilder(View) to create a default drag shadow that's the same size as the View argument passed to it, with the touch point centered in the drag shadow.

Example

Following example shows the functionality of a simple Drag & Drop using a View.setOnLongClickListener()event listener along withView.OnDragEventListener().

Step

Description

1

You will use Eclipse IDE to create an Android application and name it as DragNDropDemounder a package com.example.dragndropdemo. While creating this project, make sure youTarget SDK and Compile With at the latest version of Android SDK to use higher levels of APIs.

2

Modify src/MainActivity.java file and add the code to define event listeners as well as a call back methods for the logo image used in the example.

3

Copy image logo.png in res/drawable-* folders. You can use images with different resolution in case you want to provide them for different devices.

4

Modify layout XML file res/layout/activity_main.xml to define default view of the logo images.

5

Run the application to launch Android emulator and verify the result of the changes done in theaplication.

Following is the content of the modified main activity file src/com.example.dragndropdemo/MainActivity.java. This file can include each of the fundamental lifecycle methods.

package com.example.dragndropdemo;

 

import android.os.Bundle;

import android.app.Activity;

import android.content.ClipData;

import android.content.ClipDescription;

import android.util.Log;

import android.view.DragEvent;

import android.view.View;

import android.view.View.DragShadowBuilder;

import android.view.View.OnDragListener;

import android.widget.*;

 

public class MainActivity extends Activity{

   ImageView ima;

   private static final String IMAGEVIEW_TAG = "Android Logo";

   String msg;

 

   privateandroid.widget.RelativeLayout.LayoutParamslayoutParams;

 

   @Override

   public void onCreate(BundlesavedInstanceState) {

      super.onCreate(savedInstanceState);

     setContentView(R.layout.activity_main);

 

      ima = (ImageView)findViewById(R.id.iv_logo);

      // Sets the tag

      ima.setTag(IMAGEVIEW_TAG);

 

      ima.setOnLongClickListener(newView.OnLongClickListener() {

         @Override

         public boolean onLongClick(View v) {

            ClipData.Item item = newClipData.Item((CharSequence)v.getTag());

 

            String[] mimeTypes = {ClipDescription.MIMETYPE_TEXT_PLAIN};

            ClipData dragData = newClipData(v.getTag().toString(),

            mimeTypes, item);

 

            // Instantiates the drag shadow builder.

            View.DragShadowBuilder myShadow= new DragShadowBuilder(ima);

 

            // Starts the drag

            v.startDrag(dragData,  // the data to be dragged

            myShadow,  // the drag shadow builder

            null,      // no need to use local data

            0          // flags (not currently used, set to 0)

            );

            return true;

         }

      });

 

      // Create and set the drag event listener for the View

      ima.setOnDragListener( newOnDragListener(){

         @Override

         public boolean onDrag(View v, DragEvent event){

        switch(event.getAction())                  

         {

            caseDragEvent.ACTION_DRAG_STARTED:

               layoutParams = (RelativeLayout.LayoutParams)

               v.getLayoutParams();

               Log.d(msg, "Action isDragEvent.ACTION_DRAG_STARTED");

               // Do nothing

               break;

            caseDragEvent.ACTION_DRAG_ENTERED:

               Log.d(msg, "Action isDragEvent.ACTION_DRAG_ENTERED");

               int x_cord = (int)event.getX();

               int y_cord = (int)event.getY(); 

               break;

            caseDragEvent.ACTION_DRAG_EXITED :

               Log.d(msg, "Action isDragEvent.ACTION_DRAG_EXITED");

               x_cord = (int) event.getX();

               y_cord = (int) event.getY();

               layoutParams.leftMargin =x_cord;

               layoutParams.topMargin =y_cord;

              v.setLayoutParams(layoutParams);

               break;

            caseDragEvent.ACTION_DRAG_LOCATION  :

               Log.d(msg, "Action isDragEvent.ACTION_DRAG_LOCATION");

               x_cord = (int) event.getX();

               y_cord = (int) event.getY();

               break;

            caseDragEvent.ACTION_DRAG_ENDED   :

               Log.d(msg, "Action isDragEvent.ACTION_DRAG_ENDED");

               // Do nothing

               break;

            case DragEvent.ACTION_DROP:

               Log.d(msg, "ACTION_DROP event");

               // Do nothing

               break;

            default: break;

            }

            return true;

         }

      });

   }

}

Following will be the content of res/layout/activity_main.xml file:

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:id="@+id/container"

    android:layout_width="fill_parent"

    android:layout_height="fill_parent"

    android:orientation="vertical" >

       

    <ImageView

               android:id="@+id/iv_logo"

        android:layout_width="wrap_content"

       android:layout_height="wrap_content"

        android:src="@drawable/logo"

       android:contentDescription="@string/drag_drop"  />

          

</RelativeLayout>

Following will be the content of res/values/strings.xml to define two new constants:

<?xml version="1.0" encoding="utf-8"?>

<resources>

 

    <string name="app_name">DragNDropDemo</string>

    <string name="action_settings">Settings</string>

    <string name="hello_world">Hello world!</string>

    <string name="drag_drop">Click on the image to drag and drop</string>

  

</resources>

Following is the default content ofAndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

    package="com.example.guidemo"

    android:versionCode="1"

    android:versionName="1.0" >

 

    <uses-sdk

        android:minSdkVersion="16"

        android:targetSdkVersion="17" />

 

    <application

        android:allowBackup="true"

        android:icon="@drawable/ic_launcher"

        android:label="@string/app_name"

        android:theme="@style/AppTheme" >

        <activity

           android:name="com.example.guidemo.MainActivity"

            android:label="@string/app_name" >

            <intent-filter>

                <actionandroid:name="android.intent.action.MAIN" />

 

                <categoryandroid:name="android.intent.category.LAUNCHER" />

            </intent-filter>

        </activity>

    </application>

 

</manifest>

Let's try to run your DragNDropDemo application. I assume you had created your AVD while doing environment setup. To run the app from Eclipse, open one of your project's activity files and click Run icon from the toolbar. Eclipse installs the app on your AVD and starts it and if everything is fine with your setup and application, it will display following Emulator window:

Now do long click on the displayed android logo and you will see that logo image moves a little after 1 seconds long click from its place, its the time when you should start dragging the image. You can drag it around the screen and drop it at a new location.

Comments

Popular posts from this blog

कंफर्म ट्रेन टिकट ना मिलने पर स्मार्ट बस से करें सफर, रेल यात्री का खास ऑफर

इकोनॉमिक सर्वे की 10 खास बातें यहां पढ़ें

Musk ने क्रिएटर्स को दिया लाखों रुपये, ट्विटर से आप भी कर सकते हैं कमाई, इस तरीके से X यूजर्स हुए मालामाल