Monday, December 6, 2010

Custom GridView in a dialog...!!

Everybody's aware that inside a dialog, a custom view can be set.

In this post, i am going to discuss how do we set a custom gridview as the custom view for dialog.

My requirement was to display a grid of options for the user to pick up a categories with a icons shown in a 3x3 matrix. User can choose a one by touching it. And the dialog had a title and at the right end a close button to dismiss the dialog.

I will take through step by steps.

1 - Dialog

onCreateDialog(int id) --> Is the function which will be called by framework,when an activity has implmented and showDialog(int id ) is called on activity's instance.
So we go ahead and implement this onCreateDialog(int id) function.

2 - Layouts

The view can be split into two parts.

- LinearLayout vertical orientation holding two elements.

- RelativeLayout - Title and Exit icons at the right extreme.
- GridView - Display 3x3 icons& text as a view.

CategoryDialog.xml
----------------------



<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout_root"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp"
>
<RelativeLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingTop="3dip" >
<ImageView android:id="@+id/close"
android:layout_width="30dip"
android:layout_height="30dip"
android:layout_alignParentRight="true"
android:layout_marginRight="3dp"
android:src="@drawable/exit"
/>
<TextView android:id="@+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_alignParentLeft="true"
android:layout_marginLeft="3dp"
android:textColor="#FFF"
android:textSize="20dip"
android:text="Choose Categories"/>
</RelativeLayout>

<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/gridview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:columnWidth="90dp"
android:numColumns="3"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:stretchMode="columnWidth"
android:gravity="center"/>
</LinearLayout>




3 - Creating Dialog

Lets use the AlertDialog and set the categoryDialog.xml layout to its setView() api to show the content. what we are exepecting.

Use inflater to create a view by inflating R.layout.categorydialog



AlertDialog.Builder builder;
Context mContext = this;
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.categorydialog,(ViewGroup) findViewById(R.id.layout_root));
builder = new AlertDialog.Builder(mContext);
builder.setView(layout);
dialog = builder.create();
return dialog;




4- Creating GridView.

View layout = inflater.inflate(R.layout.categorydialog,(ViewGroup) findViewById(R.id.layout_root));
GridView gridview = (GridView)layout.findViewById(R.id.gridview);
gridview.setAdapter(new ImageAdapter(this));

- Get the gridView instance from the inflated layout and set a adapter object to draw its content.

- We need to implement a BaseAdapter and when the adapter instance is set to GridView , GridView queries for how many elements and what are their each view to display in the Grid.

- Each view in the grid is Icon (image) and a text corresponding to the category. So we need to create one more layout xml file to hold these content.

categoryContent.xml
--------------------



<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp"
>
<ImageView android:id="@+id/categoryimage"
android:layout_width="50dip"
android:layout_height="50dip"
android:layout_alignParentRight="true"
android:layout_marginRight="3dp"/>
<TextView android:id="@+id/categoryText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_alignParentLeft="true"
android:layout_marginLeft="3dp"
android:textColor="#FFF"/>

</LinearLayout>



5 - Create a view inflating this layout xml file and set the LayoutParams for each cell size as 90x90.



convertView = mInflater.inflate(R.layout.categorycontent, null);
convertView.setLayoutParams(new GridView.LayoutParams(90, 90));


Note: Since this a view which will be set in GridView as one element of Grid, the layout params must be of type GridView.LayoutParams. This is very important otherwise, the programs will crash in run-time.




public class ImageAdapter extends BaseAdapter {
private Context mContext;
private LayoutInflater mInflater;
public ImageAdapter(Context c) {
mInflater = LayoutInflater.from(c);
mContext = c;
}
public int getCount() {
return mThumbIds.length;
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
// create a new ImageView for each item referenced by the
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) { // if it's not recycled,
convertView = mInflater.inflate(R.layout.categorycontent, null);
convertView.setLayoutParams(new GridView.LayoutParams(90, 90));
holder = new ViewHolder();
holder.title = (TextView) convertView.findViewById(R.id.categoryText);
holder.icon = (ImageView )convertView.findViewById(R.id.categoryimage);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.icon.setAdjustViewBounds(true);
holder.icon.setScaleType(ImageView.ScaleType.CENTER_CROP);
holder.icon.setPadding(8, 8, 8, 8);
holder.title.setText(categoryContent[position]);
holder.icon.setImageResource(mThumbIds[position]);
return convertView;
}
class ViewHolder {
TextView title;
ImageView icon;
}
// references to our images
private Integer[] mThumbIds = {
R.drawable.beer, R.drawable.hotel,R.drawable.shopping,
R.drawable.theatre,R.drawable.train, R.drawable.taxi,
R.drawable.gas, R.drawable.police,R.drawable.hospital
};

}
private String[] categoryContent = {
"Pubs", "Restuarants","shopping",
"theatre","train", "taxi",
"gas", "police","hospital"
};
}





griddialog.java
--------------------

Everybody's aware that inside a dialog, a custom view can be set.

In this post, i am going to discuss how do we set a custom gridview as the custom view for dialog.

My requirement was to display a grid of options for the user to pick up a categories with a icons shown in a 3x3 matrix. User can choose a one by touching it. And the dialog had a title and at the right end a close button to dismiss the dialog.

I will take through step by steps.

1 - Dialog

onCreateDialog(int id) --> Is the function which will be called by framework,when an activity has implmented and showDialog(int id ) is called on activity's instance.
So we go ahead and implement this onCreateDialog(int id) function.

2 - Layouts

The view can be split into two parts.

- LinearLayout vertical orientation holding two elements.

- RelativeLayout - Title and Exit icons at the right extreme.
- GridView - Display 3x3 icons& text as a view.

CategoryDialog.xml
----------------------



package com.android.griddialog;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;

public class griddialog extends Activity {
public final int CATEGORY_ID =0;
private Context mContext;
Dialog dialog;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContext = getApplicationContext();
setContentView(R.layout.main);
Button button = (Button)findViewById(R.id.categories);
button.setOnClickListener(new Button.OnClickListener(){
public void onClick(View v) {
showDialog(CATEGORY_ID);
}
});
}
protected Dialog onCreateDialog(int id) {

switch(id) {

case CATEGORY_ID:

AlertDialog.Builder builder;
Context mContext = this;
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.categorydialog,(ViewGroup) findViewById(R.id.layout_root));
GridView gridview = (GridView)layout.findViewById(R.id.gridview);
gridview.setAdapter(new ImageAdapter(this));

gridview.setOnItemClickListener(new OnItemClickListener()
{
public void onItemClick(AdapterView parent, View v,int position, long id) {
Toast.makeText(v.getContext(), "Position is "+position, 3000).show();
}
});

ImageView close = (ImageView) layout.findViewById(R.id.close);
close.setOnClickListener(new View.OnClickListener() {
public void onClick(View v){
dialog.dismiss();
}
});

builder = new AlertDialog.Builder(mContext);
builder.setView(layout);
dialog = builder.create();
break;
default:
dialog = null;
}
return dialog;
}

public class ImageAdapter extends BaseAdapter {
private Context mContext;
private LayoutInflater mInflater;
public ImageAdapter(Context c) {
mInflater = LayoutInflater.from(c);
mContext = c;
}
public int getCount() {
return mThumbIds.length;
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
// create a new ImageView for each item referenced by the
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) { // if it's not recycled,
convertView = mInflater.inflate(R.layout.categorycontent, null);
convertView.setLayoutParams(new GridView.LayoutParams(90, 90));
holder = new ViewHolder();
holder.title = (TextView) convertView.findViewById(R.id.categoryText);
holder.icon = (ImageView )convertView.findViewById(R.id.categoryimage);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.icon.setAdjustViewBounds(true);
holder.icon.setScaleType(ImageView.ScaleType.CENTER_CROP);
holder.icon.setPadding(8, 8, 8, 8);
holder.title.setText(categoryContent[position]);
holder.icon.setImageResource(mThumbIds[position]);
return convertView;
}
class ViewHolder {
TextView title;
ImageView icon;
}
// references to our images
private Integer[] mThumbIds = {
R.drawable.beer, R.drawable.hotel,R.drawable.shopping,
R.drawable.theatre,R.drawable.train, R.drawable.taxi,
R.drawable.gas, R.drawable.police,R.drawable.hospital
};

}
private String[] categoryContent = {
"Pubs", "Restuarants","shopping",
"theatre","train", "taxi",
"gas", "police","hospital"
};


}

16 comments:

  1. But you hardcode the width and height of the images.

    convertView.setLayoutParams(new GridView.LayoutParams(90, 90));

    Does this work for different screen sizes? The images will remain 90x90 and the space between them increases? How about smaller screens, if 90x90 is too big, how does it look?

    ReplyDelete
  2. thanx a lot !!!this was really helpful.keep up the good work bro...

    ReplyDelete
  3. Yes you are correct, it doesnt work for different screen sizes. You can pass the width of the dialog as a parameter to the adapter constructor and use the width / 3 and you can set the individual grid element size to be equal for different screen resolutions.!!!

    public ImageAdapter(Context c,int width) {

    }

    Hope this helps...!!

    ReplyDelete
  4. This comment has been removed by the author.

    ReplyDelete
  5. I have a problem, I don't know why, but the text does not display under the icons. All the same I like you. Sorry for bad English

    ReplyDelete
  6. oh, everything is ok now. I'm had to change hight in :D :D

    convertView.setLayoutParams(new GridView.LayoutParams(90, 90));

    ReplyDelete
  7. Hi everything is fine. But i need to add one additionl information as popup menu. When i select any one items at that time view the popup menu in the Custom GridView dialog. I need solution. Thanks.

    ReplyDelete
  8. Hi, I have 36 edittexts in gridview. How can I fit the gridview to the screen without scrollbar. I have searched many things, but didn't find answer. Please help me out. Thanks in advane

    --Apoorv

    ReplyDelete
  9. If no scroll bar, then you need to use weight parameter and set layout_height="0dip" and layout_weight="1" for each gridview element. It should fit it all the gird view elements within the screen.

    ReplyDelete
  10. I have a problem, in my app i have made a color picker dialog(that extends dialog) then when user clicks on any color i want that particular color to be shown on my main activity, But when in OnItemClickListener methos, i am sending the pocition of that item, Intent is not working.

    Any Solution?
    Pls Help!.

    Thanks in advance!.

    ReplyDelete
  11. Hi mani this program is forced closed in this second activity is not called please help me

    ReplyDelete
  12. hello sir, I'm starting to learn android and this Tutorial of your helps me a lot your the only one show how to create this grid view. I'm just confused about the Hard coded GRID and the onclick listener. Can you please finish your tutorial it helps me a lot in my project in school.

    ReplyDelete
  13. I simply want to say I’m very new to blogs and actually loved you’re blog site. Almost certainly I’m going to bookmark your blog post . You absolutely come with great well written articles. Thanks a lot for sharing your blog.

    Android training in chennai with placement | Android Training in chennai |Android Training in Velachery

    ReplyDelete
  14. Thank you very much for sharing your knowledge with everyone, could you help me I need to place a spinner in a recyclerview, you have some tutorial or link in which to do this process, I appreciate all your help.android development course fees in chennai | android app development training in chennai

    ReplyDelete