Android Simple Image Gallery

In this post we are going to use the gallery control t construct a simple image gallery.
the layout is like the previous post.

remeber that the Gallery control is populated by an adapter, so we will create a custom adapter that contains ImageViews to display the images.
our custom adapter must inherit from BaseAdapter class
package mina.android.GalleryDemo;

import java.util.ArrayList;
import java.util.List;

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 Con;
 //array to hold the values of image resources
 int [] Resources;
 List views;
 
 public ImageAdapter(Context con,int[] resources)
 {
  Con=con;
  Resources=resources;
  views=new ArrayList(resources.length);
 }
 
 @Override
 public int getCount() {
  // TODO Auto-generated method stub
  return Resources.length;
 }

 @Override
 public Object getItem(int position) {
  // TODO Auto-generated method stub
  return views.get(position);
  //return position;
 }

 @Override
 public long getItemId(int position) {
  // TODO Auto-generated method stub
  //return views.get(position).getId();
  return position;
 }

 @Override
 public View getView(int position, View convertView, ViewGroup parent) {
  // TODO Auto-generated method stub
  ImageView img=new ImageView(Con);
  img.setImageResource(Resources[position]);
  views.add(img);
  
  return img;
 }

}


then in our activity onCreate Method:
int []res=new int[]{R.drawable.wc,R.drawable.wc2,R.drawable.wc3,R.drawable.wc4,R.drawable.wc5};
        ItemsInGallery=res.length;
        ImageAdapter imgAdapter=new ImageAdapter(this, res);
        gallery.setAdapter(imgAdapter);

and that was our simple Image gallery.
download the application from here

Reactions: 

Android Gallery Control

In Android the Gallery control is a selection control that displays items in a horizontal gallery. the items in the gallery appear beside each other. they can appear separated by a pre-defined space.

remember that there is a sample demo application for the gallery to download at the end of the post

we can use the gallery to display String items using a simple ArrayAdapter.
so let's see how to create a gallery that displays the word "Hello" in several languages:

the layout:
<?xml version="1.0" encoding="utf-8"?>
<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:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="Gallery Demo"
    />
    <Gallery
    android:id="@+id/gallery"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content"
    android:gravity="center_horizontal"
    android:spacing="100px"
    
    />
</LinearLayout>

and in the OnCreate method
@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        gallery=(Gallery)findViewById(R.id.gallery);
        //String array holding the values
        String [] text=new String[]{"Hello","Hi","Alloha","Bonjour","Hallo","¡Hola"};
        //Array adapter to display our values in the gallery control
        ArrayAdapter arr=new ArrayAdapter(this, android.R.layout.simple_gallery_item, text);
gallery.setAdapter(arr);
}

the gallery will be like this

we can increse the spacing between the items by increasing the value of android:spacing property.

we can display a scroll bar to indicate the position of the current selected item in the gallery like this:
<Gallery
    android:id="@+id/gallery"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content"
    android:gravity="center_horizontal"
    android:spacing="100px"
    android:scrollbars="horizontal"
    android:scrollbarFadeDuration="0"
    android:scrollX="100px"
    />




setting the android:scrollbarFadeDuration="0" makes the scroll bar always visible.

The android:scrollX property defines the initial scroll offset of the scroll bar which is the initial distance that the gallery is scrolled for.

Handling Gallery Events
since the gallery is a selction Control (a adapter view) so it can register a OnItemSelectedListener to handle the selection of items within the gallery.

final String [] text=new String[]{"Hello","Hi","Alloha","Bonjour","Hallo","¡Hola"};
gallery.setOnItemSelectedListener(new OnItemSelectedListener() {

   @Override
   public void onItemSelected(AdapterView parent, View view,
     int position, long id) {
    // TODO Auto-generated method stub
    TextView txt=(TextView)findViewById(R.id.txt);
    txt.setText(text[position].toString());
   }

   @Override
   public void onNothingSelected(AdapterView parent) {
    // TODO Auto-generated method stub
    
   }
  });


now the final step is to add two navigation buttons: Next and Previous to navigate throught the items in the gallery.
the layout is gonna be like this:
<?xml version="1.0" encoding="utf-8"?>
<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:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="Gallery Demo"
    android:id="@+id/txt"
    />
    <Gallery
    android:id="@+id/gallery"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content"
    android:gravity="center_horizontal"
    android:spacing="100px"
    android:scrollbars="horizontal"
    android:scrollbarFadeDuration="0"
    android:scrollX="100px"
    />
    <LinearLayout
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:orientation="horizontal"
     android:layout_marginTop="5px"
     >    
     <Button 
     android:text="Previous"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:id="@+id/btnPrev"
     android:onClick="onClick"
      />
      <Button 
     android:text="Next"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:id="@+id/btnNext"
     android:onClick="onClick"
      />

    </LinearLayout> 
    
</LinearLayout>


now in order to keep track of the index of the currently selected item we need to define two variables
//Variable to store the number of items in the gallery
 int ItemsInGallery=0;
 int CurrentIndex=0;

and the navigation buttons click handlers:
@Override
 public void onClick(View v) {
  // TODO Auto-generated method stub
  switch(v.getId())
  {
  case R.id.btnNext:
   //Increase the index
   CurrentIndex++;
   //if reached the end of the gallery, then start from the first item
   if(CurrentIndex>ItemsInGallery-1)
    CurrentIndex=0;
   gallery.setSelection(CurrentIndex,true);
   txt.setText(String.valueOf(CurrentIndex));
   break;
  case R.id.btnPrev:
   //Decrease the index
   CurrentIndex=CurrentIndex-1;
   //If reached the first item, then return to the last item in the gallery
   if(CurrentIndex<0)
    CurrentIndex=ItemsInGallery-1;
   gallery.setSelection(CurrentIndex,true);
   txt.setText(String.valueOf(CurrentIndex));
   break;
  }
 }
you can download a sample program from here

Reactions: 

How to rotate the Android Emulator ?

To rotate the Android Emulator, just disable the Num Lock key and and use the 7 and the 9 in the num pad to rotate the emulator and change its layout from portrait to landscape.

If you are working on a laptop you can do the same thing by pressing  Fn(Function)+7 or Fn+9.

Reactions: 

Android Intents: Part3: Intent Filters

Android components like activities can also serve implicit intents. but to do so they have to filter all implicit intents in order to serve only the intents they desire to serve. this is done using intent filters.

Suppose you want to create an activity that acts as the default dialer activity. You must associate an intent filter with this activity in order to that this activity serve the dial intents only.

Let's demonstrate a simple example which is creating an application with one activity that we want to make it a dialer activity.

Create a new android project, create an activity and name it Dialer.

In the AndroidManifest.xml file of this application add the following to the Dialer activity:
<intent-filter android:priority="100" >
            <action android:name="android.intent.action.DIAL"  />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:scheme="tel"/>
            </intent-filter>
to become:
<activity android:name=".Dialer"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter android:priority="100" >
            <action android:name="android.intent.action.DIAL"  />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:scheme="tel"/>
            </intent-filter>
        </activity>
Now what we have done is adding an intent filter to that activity. this intent filter has the following properties:
  1. Action: the type of implicit intents that this activity responds to. in our case it is the dial action. higher numbers represent higher priority.
  2. Priority: about the priority of that activity over other activities that respond to the same type of intents.
  3. Category: Implicit intents have built-in categories. in order that an implicit intent be captured by our activity, the implicit intent category must match our activity category.
  4. Data: adds data specification scheme to the intent filter.
So if any other application has the following module to launch the dialer:
Intent in=new Intent(Intent.ACTION_DIAL, Uri.parse("tel:000"));
     startActivity(in);
The user will see the following dialog offering him/her the choice between the default dialer and our custom dialer.

Reactions: