Skip to content

Android: Creating a custom Adapter for GridView (ButtonAdapter)

by mat on September 8th, 2010

Background
Adapters are great, it’s a fact. After you get over the initial learning curve you will realise you love them (almost as much as a six sided companion). This is my attempt at a casual explanation of how to create your own custom adapter, in this example we will create a ButtonAdapter similar to something you might see in a soundboard (yawn).

Example of a grid adapter in use

Example of a grid adapter in use

Advantages of an adapter

  • Dynamic – Can expand to any number of elements rather than statically coding each individual view.
  • Elegant – Makes your code petite and quite clear to understand once you get over the initial difficulty
  • Beautiful – Now you don’t have to control how many items there are in rows or columns, android will automatically fill up the screen in the best way possible. This also means you don’t need to redesign your application for horizontal and vertical orientations.

Creating a ButtonAdapter

So we’re going to dive straight into the deep end and create our own ButtonAdapter class that extends the BaseAdapter class. If you are doing this in eclipse you can write the first line and then it will offer to autocreate (implement) the missing methods for you (if you highlight the error). This code goes inside your Activity in your java file but not inside your oncreate method.

public class ButtonAdapter extends BaseAdapter {
 private Context mContext;

 // Gets the context so it can be used later
 public ButtonAdapter(Context c) {
  mContext = c;
 }

 // Total number of things contained within the adapter
 public int getCount() {
  return filenames.length;
 }

  // Require for structure, not really used in my code.
 public Object getItem(int position) {
  return null;
 }

 // Require for structure, not really used in my code. Can
 // be used to get the id of an item in the adapter for 
 // manual control. 
 public long getItemId(int position) {
  return position;
 }

 public View getView(int position, 
                           View convertView, ViewGroup parent) {
  Button btn;
  if (convertView == null) {  
   // if it's not recycled, initialize some attributes
   btn = new Button(mContext);
   btn.setLayoutParams(new GridView.LayoutParams(100, 55));
   btn.setPadding(8, 8, 8, 8);
   } 
  else {
   btn = (Button) convertView;
  }
  exus
  btn.setText(filesnames[position]); 
  // filenames is an array of strings
  btn.setTextColor(Color.WHITE);
  btn.setBackgroundResource(R.drawable.button);
  btn.setId(position);

  return btn;
 }
}

So the important methods are getCount and getView. getCount returns the number of objects (in our case buttons) that will be needed in this adapter. getView returns an object (again a button in our case) so that it can be used.

Both these functions reference an array that I have referered to as filenames this is a string array (String[]) which looks something like the following:

public String[] filesnames = { 
			"File 1", 
			"File 2",
			"Roflcopters"
			};

Creating an OnClickListener

You can add the following to your getView method to setup a new onclick listener for your buttons so that they can react to button presses.

  // Set the onclicklistener so that pressing the button fires an event
  // We will need to implement this onclicklistner.
  btn.setOnClickListener(new MyOnClickListener(position));

For this to work we need to implement our own OnClickListner which I have named MyOnClickListener (for lack of a better name) this is the same as a normal onclick listner except we pass an integer so that we can tell which button called our onClick method (you could get the id from the view passed, but this method is useful when expanding your program later on).


class MyOnClickListener implements OnClickListener
{
 private final int position;

 public MyOnClickListener(int position)
 {
  this.position = position;
 }

 public void onClick(View v)
 {
  // Preform a function based on the position
  someFunction(this.position)
 }
}

Implementing this adapter

Now implementing the adapater is very simple, add a few imports and load a grid view from an xml file. Then we simply set the gridview’s adapter to be a new ButtonAdapter and it will automatically do the rest for us.

// You will need the following imports

import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.GridView;

// In your oncreate (or where ever you want to create your gridview)
GridView gridview = (GridView) findViewById(R.id.gridview);
gridview.setAdapter(new ButtonAdapter(this));

And hopefully your all done, you could then go on to add a context menu(menu on long press) to your buttons. If you have any questions or want something explaining a bit better, just ask!

64 Comments
  1. buttonAdapter:
    package com.example.test;

    import android.content.Context;
    import android.graphics.Color;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.BaseAdapter;
    import android.widget.Button;
    import android.widget.GridView;

    public class ButtonAdapter extends BaseAdapter {
    private Context mContext;
    public String [] fName = { “File 1″, “File 2″, “Roflcopters” };

    // Gets the context so it can be used later
    public ButtonAdapter (Context c) {
    mContext = c;
    }

    // Total number of things contained within the adapter
    public int getCount () {
    return 8;
    }

    // Require for structure, not really used in my code.
    public Object getItem (int position) {
    return null;
    }

    // Require for structure, not really used in my code. Can
    // be used to get the id of an item in the adapter for
    // manual control.
    public long getItemId (int position) {
    return position;
    }

    public View getView (int position, View convertView, ViewGroup parent) {
    Button btn;

    if (convertView == null) {
    // if it’s not recycled, initialize some attributes
    btn = new Button (mContext);
    btn.setLayoutParams (new GridView.LayoutParams (190, 190));
    btn.setPadding (1, 1, 1, 1);
    } else {
    btn = (Button) convertView;
    }

    // btn.setText(filesnames[position]);
    // filenames is an array of strings
    //btn.setTextColor (Color.WHITE);
    //btn.setBackgroundResource (R.drawable.sample_2);

    //btn.setBackgroundColor (Color.BLACK);
    btn.setHighlightColor (Color.GREEN);
    btn.setId (position);

    return btn;
    }
    }

    Home:
    package com.example.test;

    import android.app.Activity;
    import android.content.Intent;
    import android.os.Bundle;
    import android.view.Menu;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.AdapterView;
    import android.widget.AdapterView.OnItemClickListener;
    import android.widget.GridView;
    import android.widget.Toast;

    public class home extends Activity implements OnItemClickListener {
    public final static String EXTRA_MESSAGE1 = “com.example.text.MESSAGE”;

    public void onCreate (Bundle savedInstanceState) {
    super.onCreate (savedInstanceState);
    setContentView (R.layout.activity_home);

    GridView gridview = (GridView) findViewById (R.id.gridview);
    gridview.setAdapter (new ButtonAdapter (this));

    /*gridview.setOnItemClickListener (new OnItemClickListener () {
    public void onItemClick (AdapterView parent, View v, int position, long id) {
    Toast.makeText (home.this, “” + position, Toast.LENGTH_LONG).show ();

    //Intent intent = new Intent (this, alarm.class);
    // String message = “Position:” + position;
    //intent.putExtra (EXTRA_MESSAGE1, message);
    // startActivity (intent);
    //}
    //});
    * */

    }

    @Override
    public void onItemClick (AdapterView parent, View v, int position, long id) {
    Intent intent = new Intent (this, alarm.class);
    String message = “Position:” + position;
    intent.putExtra (EXTRA_MESSAGE1, message);
    startActivity (intent);
    }

    }

    The onItemClick doesn’t work and neither does the commented ‘setOnItemClickListener’ when it isn’t commented out and ‘onItemClick’ is commented. What am I doing wrong?

  2. AMir permalink

    hi. thanks for your great tutorial. i used it and it worked great. but i have a problem. i want to set context menus for each button . is it possible and how can i do it?

    thanks

  3. AMir permalink

    sorry i should have said these in my last comment. i read your article about creating context menus, but it used a simple button, the thing i don’t know is that when am i suppose to call registerForContextMenu() for each btn? (should i do it when i’m creating button in getView() ?) and where am i suppose to override onCreateContextMenu method? (button adapter or in my activity?)

    btw, i don’t have the buttons IDs how can i find them?

    thanks

  4. kiruthika permalink

    for adding buttons dynamically to grid view…

    main.xml:

    main.java:

    package com.authorwjf;

    import java.util.ArrayList;

    import android.app.Activity;
    import android.os.Bundle;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.ViewGroup;
    import android.widget.BaseAdapter;
    import android.widget.Button;
    import android.widget.GridView;
    import android.widget.Toast;

    public class Main extends Activity implements OnClickListener {

    private ArrayList mButtons = new ArrayList();

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    Button cb = null;

    for (int i =0; i<12; i++) {
    cb = new Button(this);
    cb.setText(Integer.toString(i));
    cb.setBackgroundResource(R.drawable.fancy_button_selector);
    cb.setOnClickListener(this);
    cb.setId(i);
    mButtons.add(cb);
    }

    GridView gridView = (GridView) findViewById(R.id.gridview);
    gridView.setAdapter(new CustomAdapter(mButtons));

    }

    @Override
    public void onClick(View v) {
    Button selection = (Button)v;
    Toast.makeText(getBaseContext(), selection.getText()+ " was pressed!", Toast.LENGTH_SHORT).show();
    }
    public class CustomAdapter extends BaseAdapter {

    private ArrayList mButtons = null;

    public CustomAdapter(ArrayList b)
    {
    mButtons = b;
    }

    @Override
    public int getCount() {
    return mButtons.size();
    }

    @Override
    public Object getItem(int position) {
    return (Object) mButtons.get(position);
    }

    @Override
    public long getItemId(int position) {
    //in our case position and id are synonymous
    return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
    Button button;
    if (convertView == null) {
    button = mButtons.get(position);
    } else {
    button = (Button) convertView;
    }
    return button;
    }
    }
    }

  5. How can i add the buttons to a different layout???

  6. Thanks man.
    it helps a lot..

  7. Every weekend i used to pay a visit this web page,
    because i want enjoyment, since this this site
    conations in fact good funny information too.

  8. Zarin permalink

    Hi, I want to add different text to the buttons. How can I do that?

  9. Zarin permalink

    cb.setText(Integer.toString(i));

    in this, I should add different text to the buttons.

Trackbacks & Pingbacks

  1. Android: Gridview force closes
  2. Can GridView contain some default images? : Android Community - For Application Development
  3. Layout puzzle development in Android - Tech Forum Network
  4. Child / Item total listener gridview android? | Zepp
  5. circular scrollview in Android | Yegge Answers

Leave a Reply

Note: I am currently writing my thesis so probably wont have time to reply to your comment
Note: XHTML is allowed. Your email address will never be published.

Subscribe to this comment feed via RSS