1 page.title=Grid 2 parent.title=Layouts 3 parent.link=layout-objects.html 4 @jd:body 5 <div id="qv-wrapper"> 6 <div id="qv"> 7 <h2>In this document</h2> 8 <ol> 9 <li><a href="#example">Example</a></li> 10 </ol> 11 <h2>Key classes</h2> 12 <ol> 13 <li>{@link android.widget.GridView}</li> 14 <li>{@link android.widget.ImageView}</li> 15 <li>{@link android.widget.BaseAdapter}</li> 16 <li>{@link android.widget.AdapterView.OnItemClickListener}</li> 17 </ol> 18 </div> 19 </div> 20 <p>{@link android.widget.GridView} is a {@link android.view.ViewGroup} that displays items in a 21 two-dimensional, 22 scrollable grid. The grid items are automatically inserted to the layout using a {@link 23 android.widget.ListAdapter}.</p> 24 25 <img src="{@docRoot}images/ui/gridview.png" alt="" /> 26 27 28 <h2 id="example">Example</h2> 29 <p>In this tutorial, you'll create a grid of image thumbnails. When an item is selected, a 30 toast message will display the position of the image.</p> 31 32 33 <ol> 34 <li>Start a new project named <em>HelloGridView</em>.</li> 35 <li>Find some photos you'd like to use, or <a 36 href="{@docRoot}shareables/sample_images.zip">download these sample images</a>. Save the image files 37 into the project's 38 <code>res/drawable/</code> directory.</li> 39 <li>Open the <code>res/layout/main.xml</code> file and insert the following: 40 <pre> 41 <?xml version="1.0" encoding="utf-8"?> 42 <GridView xmlns:android="http://schemas.android.com/apk/res/android" 43 android:id="@+id/gridview" 44 android:layout_width="fill_parent" 45 android:layout_height="fill_parent" 46 android:columnWidth="90dp" 47 android:numColumns="auto_fit" 48 android:verticalSpacing="10dp" 49 android:horizontalSpacing="10dp" 50 android:stretchMode="columnWidth" 51 android:gravity="center" 52 /> 53 </pre> 54 <p>This {@link android.widget.GridView} will fill the entire screen. The attributes are rather 55 self explanatory. For more information about valid attributes, see the {@link 56 android.widget.GridView} reference.</p> 57 </li> 58 <li>Open <code>HelloGridView.java</code> and insert the following code for the 59 {@link android.app.Activity#onCreate(Bundle) onCreate()} method: 60 <pre> 61 public void onCreate(Bundle savedInstanceState) { 62 super.onCreate(savedInstanceState); 63 setContentView(R.layout.main); 64 65 GridView gridview = (GridView) findViewById(R.id.gridview); 66 gridview.setAdapter(new ImageAdapter(this)); 67 68 gridview.setOnItemClickListener(new OnItemClickListener() { 69 public void onItemClick(AdapterView<?> parent, View v, int position, long id) { 70 Toast.makeText(HelloGridView.this, "" + position, Toast.LENGTH_SHORT).show(); 71 } 72 }); 73 } 74 </pre> 75 <p>After the {@code main.xml} layout is set for the content view, the 76 {@link android.widget.GridView} is captured from the layout with {@link 77 android.app.Activity#findViewById(int)}. The {@link 78 android.widget.GridView#setAdapter(T) setAdapter()} method then sets a custom adapter ({@code 79 ImageAdapter}) as the source for all items to be displayed in the grid. The {@code ImageAdapter} is 80 created in the next step.</p> 81 <p>To do something when an item in the grid is clicked, the {@link 82 android.widget.AdapterView#setOnItemClickListener(OnItemClickListener) setOnItemClickListener()} 83 method is passed a new {@link android.widget.AdapterView.OnItemClickListener}. This anonymous 84 instance defines the {@link 85 android.widget.AdapterView.OnItemClickListener#onItemClick(AdapterView,View,int,long) 86 onItemClick()} callback method to show a {@link android.widget.Toast} that displays the index 87 position (zero-based) of the selected item (in a real world scenario, the position could be used to 88 get the full sized 89 image for some other task).</p> 90 91 </li> 92 <li>Create a new class called <code>ImageAdapter</code> that extends {@link 93 android.widget.BaseAdapter}: 94 <pre> 95 public class ImageAdapter extends BaseAdapter { 96 private Context mContext; 97 98 public ImageAdapter(Context c) { 99 mContext = c; 100 } 101 102 public int getCount() { 103 return mThumbIds.length; 104 } 105 106 public Object getItem(int position) { 107 return null; 108 } 109 110 public long getItemId(int position) { 111 return 0; 112 } 113 114 // create a new ImageView for each item referenced by the Adapter 115 public View getView(int position, View convertView, ViewGroup parent) { 116 ImageView imageView; 117 if (convertView == null) { // if it's not recycled, initialize some attributes 118 imageView = new ImageView(mContext); 119 imageView.setLayoutParams(new GridView.LayoutParams(85, 85)); 120 imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); 121 imageView.setPadding(8, 8, 8, 8); 122 } else { 123 imageView = (ImageView) convertView; 124 } 125 126 imageView.setImageResource(mThumbIds[position]); 127 return imageView; 128 } 129 130 // references to our images 131 private Integer[] mThumbIds = { 132 R.drawable.sample_2, R.drawable.sample_3, 133 R.drawable.sample_4, R.drawable.sample_5, 134 R.drawable.sample_6, R.drawable.sample_7, 135 R.drawable.sample_0, R.drawable.sample_1, 136 R.drawable.sample_2, R.drawable.sample_3, 137 R.drawable.sample_4, R.drawable.sample_5, 138 R.drawable.sample_6, R.drawable.sample_7, 139 R.drawable.sample_0, R.drawable.sample_1, 140 R.drawable.sample_2, R.drawable.sample_3, 141 R.drawable.sample_4, R.drawable.sample_5, 142 R.drawable.sample_6, R.drawable.sample_7 143 }; 144 } 145 </pre> 146 <p>First, this implements some required methods inherited from {@link 147 android.widget.BaseAdapter}. The constructor and {@link 148 android.widget.Adapter#getCount()} are self-explanatory. Normally, {@link 149 android.widget.Adapter#getItem(int)} should return the actual object at the specified position in 150 the adapter, but it's ignored for this example. Likewise, {@link 151 android.widget.Adapter#getItemId(int)} should return the row id of the item, but it's not 152 needed here.</p> 153 154 <p>The first method necessary is {@link android.widget.Adapter#getView(int,View,ViewGroup) 155 getView()}. This method creates a new {@link android.view.View} for each image added to the {@code 156 ImageAdapter}. When this is called, a {@link android.view.View} is passed in, which is normally a 157 recycled object (at least after this has been called once), so there's a check to see if the 158 object is null. If it <em>is</em> null, an {@link android.widget.ImageView} is instantiated and 159 configured with desired properties for the image presentation:</p> 160 <ul> 161 <li>{@link android.view.View#setLayoutParams(ViewGroup.LayoutParams)} sets 162 the height and width for the View—this ensures that, no matter the size of the drawable, each 163 image is resized and cropped to fit in these dimensions, as appropriate.</li> 164 <li>{@link android.widget.ImageView#setScaleType(ImageView.ScaleType)} declares that images should 165 be cropped toward the center (if necessary).</li> 166 <li>{@link android.widget.ImageView#setPadding(int,int,int,int)} defines the padding for all 167 sides. (Note that, if the images have different aspect-ratios, then less 168 padding will cause for more cropping of the image if it does not match 169 the dimensions given to the ImageView.)</li> 170 </ul> 171 172 <p>If the {@link android.view.View} passed to {@link 173 android.widget.Adapter#getView(int,View,ViewGroup) getView()} is <em>not</em> null, then the local 174 {@link android.widget.ImageView} is initialized with the recycled {@link android.view.View} 175 object.</p> 176 177 <p>At the end of the {@link android.widget.Adapter#getView(int,View,ViewGroup) getView()} method, 178 the {@code 179 position} integer passed into the method is used to select an image from the {@code mThumbIds} 180 array, which is set as the image resource for the {@link android.widget.ImageView}.</p> 181 <p>All that's left is to define the {@code mThumbIds} array of drawable resources.</p> 182 </li> 183 <li>Run the application.</li> 184 </ol> 185 186 <p>Try experimenting with the behaviors of the {@link android.widget.GridView} and {@link 187 android.widget.ImageView} elements by adjusting their properties. For example, instead of using 188 {@link android.view.View#setLayoutParams(ViewGroup.LayoutParams)}, try using 189 {@link android.widget.ImageView#setAdjustViewBounds(boolean)}. </p> 190 191 192