Pages

Monday, October 29, 2012

Draw line on finger touch

There are many application in Android you can use to draw something on screen. This is a simple application which will draw straight line on screen between touch you have started and the last point of your touch. 

This application will use Bitmap, Canvas, and Paint class.

Bitmap class covers some common techniques for processing and loading Bitmap objects in a way that keeps your user interface (UI) components responsive and avoids exceeding your application memory limit. 

Canvas class holds the DRAW calls. To draw something, you need four basic components: A bitmap to hold the pixels, a Canvas to host the draw calls (writing into the bitmap), a drawing primitive (e.g. Rect, Circle), and a paint (to describe the colours and styles for the drawing).

Paint class holds the style and colour information about how to draw geometries, text and bitmaps.
 
1. Design Screen: 

activity_touch_draw.xml

<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" >

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:src="@drawable/ic_launcher" />

</RelativeLayout>

An ImageView will be used as drawing board and your finger will work as pencil. A straight line will drawn from starting touch to ending point where user pull up finger. 

TouchDraw.java
package app.test;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;

public class Test extends Activity implements OnTouchListener {
  ImageView imageView;
  Bitmap bitmap;
  Canvas canvas;
  Paint paint;
  float downx = 0, downy = 0, upx = 0, upy = 0;
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    imageView = (ImageView) this.findViewById(R.id.ImageView);

    Display currentDisplay = getWindowManager().getDefaultDisplay();
    float dw = currentDisplay.getWidth();
    float dh = currentDisplay.getHeight();

    bitmap = Bitmap.createBitmap((int) dw, (int) dh,
        Bitmap.Config.ARGB_8888);
    canvas = new Canvas(bitmap);
    paint = new Paint();
    paint.setColor(Color.GREEN);
    imageView.setImageBitmap(bitmap);

    imageView.setOnTouchListener(this);
  }

  public boolean onTouch(View v, MotionEvent event) {
    int action = event.getAction();
    switch (action) {
    case MotionEvent.ACTION_DOWN:
      downx = event.getX();
      downy = event.getY();
      break;
    case MotionEvent.ACTION_MOVE:
      break;
    case MotionEvent.ACTION_UP:
      upx = event.getX();
      upy = event.getY();
      canvas.drawLine(downx, downy, upx, upy, paint);
      imageView.invalidate();
      break;
    case MotionEvent.ACTION_CANCEL:
      break;
    default:
      break;
    }
    return true;
  }
}

First of all you'll need to know what is width and height of your screen. You'll need Display class object to get detail about screen. Display class provides information about the display size and density.   


Display currentDisplay = getWindowManager().getDefaultDisplay();
float dw = currentDisplay.getWidth();
float dh = currentDisplay.getHeight();

currentDisplay object will provider display width and height.
bitmap object will of provided width and height.
canvas object will used to class draw functions. Your actual line will draw on canvas.
paint object will actually a line on the canvas.

Finally, user will draw on screen line by touching ImageView object. So, I have set OnTouchListener on ImageView object.

OnTouchListener is an interface definition for a callback to be invoked when a touch event is dispatched to the view.

onTouch method is called when a touch event is dispatched to a view. This allows a listeners to get chance to respond before the target view.
public boolean onTouch(View v, MotionEvent event)

  • is object of View class from where touch is dispatched.  
  • event is object of MotionEvent containing full information about event

int action = event.getAction();

getAction() return the kind of action being performed. During entire process of drawing a line on touch many actions will be called like.

  • ACTION_DOWN
  • ACTION_MOVE
  • ACTION_CANCEL
  • ACTION_UP

So, I need to draw a line starting from action called ACTION_DOWN up to the action ACTION_UP. I have taken starting X & Y co-ordinate where ACTION_DOWN action called and again I have retrieved ending X & Y co-ordinate when ACTION_UP action called. Finally, I have used drawLine() method of Canvas class to draw straight line.

Thursday, October 25, 2012

TabActivity example

TabActivity class is used to create Tabs in your application. You can add multiple tab in your application based on different activities of your application.

[Note: This class is deprecated from Android 3.0 Honeycomb. From Android 3.0 Fragment class is used to create Tabs.]

Though this class is deprecated you can still use because most of the Android phones run Android 2.3. Here, I have developed an application which will have five tabs for five different activities.

1. Design your screen
Let us create main activity which will have all tabs.

activity_tabed.xml 

<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/tabhost"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:padding="5dp">
        
        <TabWidget
            android:id="@android:id/tabs"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content" />
        
        <FrameLayout
            android:id="@android:id/tabcontent"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:padding="5dp" />
        
    </LinearLayout>
    
</TabHost>
 
TabHost is a container for a tabbed window view. This object holds two children: a set of tab labels that the user clicks to select specific tab, and a FrameLayout object that displays the content of that page. The individual element are typically controlled using this container object, rather then setting values on the child elements themselves. 

TabWidget displays a list of tab labels representing each page in the parent's tab collection. The container object for this widget is TabHost. When a user selects a tab, this object sends a message to container, TabHost, to tell to switch the display page. The container TabHost is used to add labels, add the callback handler, and manage callbacks.

Here I have developed an application having five tabs. For each tab I have created an Activity. Take a look at all five activities.
  1. AndroidActivity
  2. LinuxActivity
  3. BlackBerryActivity
  4. WindowsActivity
  5. MacActivity  

Each tab will run individual activity from above list. So, there are many files per activity, like, Java file, layout file, drawable file. Take a look at each file. Below three files belongs from only AndroidActivity. You can have same for each different tab.

activity_android.xml
<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/textView1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="This is an Android Activity."
            android:textAppearance="?android:attr/textAppearanceLarge" />

        <ImageView
            android:id="@+id/imageView1"
            android:layout_width="match_parent"
            android:layout_height="300dp"
            android:src="@drawable/android" />
</LinearLayout> 

 android_cfg.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    
    <item android:drawable="@drawable/android_icon"
          android:state_selected="true"></item>
    
    <item android:drawable="@drawable/android_icon"></item>

</selector>

This file highlight that which tab is selected. Each tab will have individual selector xml file. On selection of any tab the state_selected attribute will set to true so the selected tab will display in highlighted colour. All non-selected tabs will have common and other colour then the highlighted one.

AndroidActivity.java
package adnroidrises.tabedactivity;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;

public class AndroidActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_android_activoty);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_android_activoty, menu);
        return true;
    }
}  


There is nothing to code in above activity Java file. You can put your code what ever you want to put in this tab.

Like android activity you can add as many activity as many tabs you want in your application. I have added five activities to the application. 

Now lets code for main activity which will contain all five sub activities as tab. You have seen XML file for this activity. Lets have look at Java file.

package adnroidrises.tabedactivity;

import android.os.Bundle;
import android.app.ActionBar.Tab;
import android.app.Activity;
import android.app.TabActivity;
import android.content.Intent;
import android.content.res.Resources;
import android.view.Menu;
import android.widget.TabHost;
import android.widget.TabHost.TabSpec;

public class TabedActivity extends TabActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_tabed);
        
        Resources ressources = getResources(); 
        TabHost tabHost = getTabHost();
        
        // Android tab
        Intent intentAndroid = new Intent().setClass(this, AndroidActivity.class);
        TabSpec tabSpecAndroid = tabHost.newTabSpec("Android")
                .setIndicator("", ressources.getDrawable(R.drawable.android_cfg))
                .setContent(intentAndroid);
        
        //Linux tab
        Intent intentLinux = new Intent().setClass(this, LinuxActivity.class);
        TabSpec tabSpecLinux = tabHost.newTabSpec("Linux")
                .setIndicator("Linux", ressources.getDrawable(R.drawable.linux_cfg))
                .setContent(intentLinux);    

        // Apple tab
        Intent intentApple = new Intent().setClass(this, MacActivity.class);
        TabSpec tabSpecApple = tabHost
          .newTabSpec("Apple")
          .setIndicator("", ressources.getDrawable(R.drawable.mac_cfg))
          .setContent(intentApple);

        // Windows tab
        Intent intentWindows = new Intent().setClass(this, WindowActivity.class);
        TabSpec tabSpecWindows = tabHost
          .newTabSpec("Windows")
          .setIndicator("", ressources.getDrawable(R.drawable.windows_cfg))
          .setContent(intentWindows);

        // Blackberry tab
        Intent intentBerry = new Intent().setClass(this, BlackberryActivity.class);
        TabSpec tabSpecBerry = tabHost
          .newTabSpec("Berry")
          .setIndicator("", ressources.getDrawable(R.drawable.blackberry_cfg))
          .setContent(intentBerry);

        // add all tabs 
        tabHost.addTab(tabSpecAndroid);
        tabHost.addTab(tabSpecApple);
        tabHost.addTab(tabSpecWindows);
        tabHost.addTab(tabSpecBerry);
        tabHost.addTab(tabSpecLinux);

        //set Windows tab as default (zero based)
        tabHost.setCurrentTab(0);      
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_tabed, menu);
        return true;
    }
}

As you can see I have created objects of classes Resources & TabHost. I have explained about TabHost in this article.Resources class is used for accessing an application resources. This class extends TabActivity instead of normal Activity class.

When you select any tab from application, a new activity will launch inside that tab. So, we'll need Intent to launch that activity. You'll need as many Intent objects as many tabs are there in your application.

 // Android tab
 Intent intentAndroid = new Intent().setClass(this, AndroidActivity.class);
 TabSpec tabSpecAndroid = tabHost.newTabSpec("Android")
            .setIndicator("", ressources.getDrawable(R.drawable.android_cfg))
            .setContent(intentAndroid);

In first line of above code I have created instance of Intent class which used to call AndroidActivity
Every tab has a tab indicator and a tag that is used to keep track it. 
TabSpec is used to set Indicator, Content, Label, Icon, etc. on the particular tab. I have created TabSpec object which will initialized by newTabSpec method or TabHost class, which will have tag or title as parameter. 
setIndicator will indicate TabHost that particular tab is selected or not. The file android_cfg in /res/drawable will indicate that tab is selected of not. This file will set background of tabs on the basis of that tab is selected of not. 
setContent will set the activity to launch on selection of the tab Android.

I have repeated same process for each tab I have used in my application. After creating tabs I have added all tabs to TabHost object.

tabHost.addTab(tabSpecAndroid);

addTab() method is used to add tab to TabHost object. each TabSpec object represent a  single tab. I have added all five TabSpec object to TabHost.  
Finally, you have to set any one tab as selected by default. setCurrentTab() method will set any one tab as selected by default at starting time of application. Method takes tab number starting from 0 as the parameter.

That's it, You are done with the application.

You can download file from below location.





 

Sunday, October 14, 2012

Working with GalleryView...


GalleryView:  It contains a horizontally scrolling list of view objects, also ofter used with imageicons; the user can select an item to perform some action upon. The one main benefit of using the Gallery View is its snap-to-position feature. When the user stops scrolling, the images that end up being displayed are also snapped to the center of the screen. This means the user won’t be looking at half of two separate images at one time, and as a developer, you are also aware of exactly what the user is centered on.

Here in this example I have taken a GalleryView and assign some images to it. On selecting of any image, that selected image will show in a ImageView below GalleryView on the screen

1. Design Screen:

We will need only two controls a GalleryView and an ImageView. Get the XML code for that below.

Main.xml
    



         
         




2. Create Resources:

Source of images in GalleryView can be /res folder, an URL etc. I have put all images in /res/drawable folder. So copy and paste all your images under this folder.
[Note: All the file name should be in lower case]


3. Java Code:

GalleryViewDemo.java
package com.example.galleryview; 

import android.os.Bundle; 
import android.app.Activity; 
import android.view.Menu; 
import android.view.MenuItem; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.AdapterView; 
import android.widget.AdapterView.OnItemClickListener; 
import android.widget.Gallery; 
import android.widget.ImageView; 
import android.widget.Toast; 
import android.support.v4.app.NavUtils; 

public class GalleryViewDemo extends Activity { 

 ImageAdapter imageAdapter; 
 ImageView image; 
     
 @Override 
     public void onCreate(Bundle savedInstanceState) 
 { 
         super.onCreate(savedInstanceState); 
         setContentView(R.layout.activity_gallery_view_demo); 
        
         Gallery gallery = (Gallery)findViewById(R.id.gallery1); 
         image = (ImageView) findViewById(R.id.imageView1); 
        
         imageAdapter = new ImageAdapter(this); 
         gallery.setAdapter(imageAdapter); 
        
         gallery.setOnItemClickListener(new OnItemClickListener() 
  { 

    public void onItemClick(AdapterView parent, View v, int position, 
        long id) 
    { 
     // TODO Auto-generated method stub 
     Toast.makeText(GalleryViewDemo.this, " " + position,       Toast.LENGTH_SHORT).show(); 
     //v = imageAdapter.getView(position, v, parent); 
     image.setImageResource(imageAdapter.images[position]); 
    } 
          
  });        
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
        getMenuInflater().inflate(R.menu.activity_gallery_view_demo, menu); 
        return true; 
    }    
}
As you can see I've created an ImageAdapter class object to set images in GalleryView and an ImageView which will get the image as resource on selection from GalleryView. Now, below statement will create actual GalleryView with images loaded in it.

gallery.setAdapter(imageAdapter);

This statement will first call getCount() method of ImageAdapter and will get that how many images are there to set in GalleryView. Next it will call getView() method as many number of time as many images are there in image array in ImageAdapter class. Every time this method will return an Image which will set to GalleryView. This entire processs is hidden from developer. Ths setAdapter() will take care of this all.

Now, after setting GalleryView I've written a listener method setOnItemClickListener(). This will fire when user touch any image from GalleryView. I've set that selected image as resource of other ImageView object.

Take a look at ImageAdapter in detail.

Here android have some surprises in setting images to GalleryView. You can't just set resources to GalleryView like ListView. You'll need some special adapter to manage GalleryView. First you'll have to create an ImageAdapter class which will extends BaseAdapter. Some default methods of BaseAdapter will help you to set images to GalleryView. Take a look at ImageAdapter class given below.

ImageAdapter.java
package com.example.galleryview;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;

public class ImageAdapter extends BaseAdapter{

 Context context;
 int[] images = {R.drawable.image,R.drawable.image1,
   R.drawable.image2,R.drawable.image3,
   R.drawable.image4,R.drawable.image5,
   R.drawable.image6,R.drawable.image7,};
 
 public ImageAdapter(Context c)
 {
  this.context = c;
 }
 
 
 public int getCount() {
  // TODO Auto-generated method stub
  return images.length;
 }

 public Object getItem(int arg0) {
  // TODO Auto-generated method stub
  return null;
 }

 public long getItemId(int arg0) {
  // TODO Auto-generated method stub
  return 0;
 }

 public View getView(int position, View arg1, ViewGroup arg2) {
  // TODO Auto-generated method stub
  
  ImageView image = new ImageView(context);
  image.setImageResource(images[position]);
  
  return image;
 }
}

First I have created Context object and an array of IDs of images. In constructor will set value to context object. The below four methods inherit from BaseAdapter.

  • Public int getCount();
    • This method will return how many images are there in an array.
  • public Object getItem(int arg0)
    • This method will return an Object.
  • public long getItemId(int arg0)
    • This method will return ID of image.
  • public View getView(int position, View arg1, ViewGroup arg2)
    • This method will return an ImageView.

The above methods of ImageAdapter class will work as a source of GalleryView. GalleryView is nothing but a collection of Images. You just need to create ImageView objects as many as images you want to keep in GalleryView and finally you just put it in horizontal list which is your GalleryView.

The getView() method will return one by one images to the activity class where GalleryView physically located. Look at below code.

ImageView image = new ImageView(context);

This line will create an ImageView who's context is your activity class. The method getView() actually return image which need to set on GalleryView.

After implementing both java file and an XML, you'll get something like below.