Android Chapter05 ListBased Widgets
Android Chapter05 ListBased Widgets
List-Based Widgets: • When the set of values to choose from is large, other Android List-Based
Widgets are more appropriate.
Lists, Grids, and Scroll Views
• Example of List-Based Widgets include:
Victor Matos
• ListViews,
Cleveland State University
• Spinner,
• GridView
• Image Gallery
• ScrollViews, etc.
Portions of this page are reproduced from work created and shared by Google and used according to terms
described in the Creative Commons 3.0 Attribution License. 5-2
5-5 5-6
Parameters:
1. The current activity’s context (this)
2. The TextView layout indicating how an individual row should be
written ( android.R.id.simple_list_item_1 ).
3. The actual data source (Array or Java.List containing items to be
shown).
5-7 5-8
Using ListActivity + ArrayAdapter Using ListActivity + ArrayAdapter
Example1A: Layout Example1A: MainActivity ( using a ListActivity ! )
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" package csu.matos;
xmlns:tools="http://schemas.android.com/tools" CAUTION:
android:layout_width="match_parent" import ... A ListActivity is not a “plain”
android:layout_height="match_parent"
android:orientation="vertical">
Pay attention to the use of predefined Activity. It is bound to a built-in
Android components: public class ListViewDemo extends ListActivity { ListView called @android:id/list
<TextView @android:id/list
android:id="@+id/txtMsg" TextView txtMsg;
android:layout_width="match_parent" @android:id/empty
android:layout_height="wrap_content" String[] items = { "Data-0", "Data-1", "Data-2", "Data-3",
android:background="#ffffff00" See Appendix A for a description of "Data-4", "Data-5", "Data-6", "Data-7" };
android:text="Using ListViews..."
android:textSize="16sp" /> @android:id/list
// next time try an empty list such as:
// String[] items = {};
<ListView
android:id="@android:id/list" Data
android:layout_width="match_parent"
Android’s built-in list layout
Source
android:layout_height="match_parent" >
</ListView>
<TextView
android:id="@android:id/empty" Used for empty lists
...
android:layout_width="match_parent" Fragment already defined in
<ListView
android:layout_height="wrap_content"
android:id="@android:id/list" Layout: activity_main.xml
android:background="#ffff0000"
android:layout_width="match_parent"
android:text="empty list" /> android:layout_height="match_parent" >
</ListView>
</LinearLayout> ...
5-9 5 - 10
2. Now open the res/values/styles folder. Look for the entry <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
<style name="AppTheme" parent="android:Theme.Light" /> android:layout_width="match_parent"
android:layout_height="match_parent"
which indicates to use the “Light” theme (white background instead of android:orientation="vertical" >
black). <TextView
android:id="@+id/txtMsg"
android:layout_width="match_parent"
3. Remove from the manifest the entry android:theme. android:layout_height="wrap_content"
android:background="#ffffff00"
android:text="Using ListViews..."
4. Remove from the onCreate method the statement: android:textSize="16sp" />
getListView().setBackgroundColor(Color.GRAY); <ListView try:
android:id="@+id/my_list" wrap_content
android:layout_width="match_parent" to see limitations
3. Run the application again. Observe its new look. android:layout_height="match_parent" >
</ListView>
</LinearLayout>
5 - 15 5 - 16
Using Activity + ArrayAdapter Using Activity + ArrayAdapter
Example1B: Instead of using a ListActivity (as we did on the previous Example 1B – MainActivity 2 of 2
example) we now employ a regular Android Activity. Observe that you myListView.setOnItemClickListener(new OnItemClickListener() {
must ‘wired-up’ the ListView to a Java proxy, and later bind it to an Adapter. @Override
public void onItemClick(AdapterView<?> av, View v,
Example 1B – MainActivity 1 of 2 int position, long id) {
public class ListViewDemo2 extends Activity { String text = "Position: " + position
String[] items = { "Data-0", "Data-1", "Data-2", "Data-3", + "\nData: " + items[position];
"Data-4", "Data-5", "Data-6", "Data-7" };
ListView myListView;
txtMsg.setText(text);
TextView txtMsg;
}
@Override });
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myListView = (ListView) findViewById(R.id.my_list); To provide a listener to the ListView control add the fragment above to the
ArrayAdapter<String> aa = new ArrayAdapter<String>(this,
onCreate method.
android.R.layout.simple_list_item_1,
// R.layout.my_text, //try this later...
items);
myListView.setAdapter(aa);
txtMsg = (TextView) findViewById(R.id.txtMsg);
}//onCreate
} 5 - 17 5 - 18
3. Selected
• Android’s Spinner is equivalent to a drop-down selector. value
• Spinners have the same functionality of a ListView but take less screen
space.
5 - 23 5 - 24
Using the Spinner Widget The GridView Widget
Example2: Spinner Demo - MainActivity 2 of 2
5 - 25 5 - 26
5 - 27 5 - 28
The GridView Widget The GridView Widget
Example3A: GridView Demo - Layout Example3A: GridView Demo – MainActivity 1 of 2
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/LinearLayout1" public class ArrayAdapterDemo3 extends Activity {
android:layout_width="match_parent"
android:layout_height="match_parent" TextView txtMsg;
android:orientation="vertical"
android:padding="2dp" String[] items = { "Data-0", "Data-1", "Data-2", "Data-3",
tools:context=".MainActivity" >
<TextView
"Data-4", "Data-5", "Data-6", "Data-7" };
android:id="@+id/txtMsg" @Override
android:layout_width="match_parent" public void onCreate(Bundle savedInstanceState) {
android:layout_height="wrap_content" super.onCreate(icicle);
android:background="#ff0000ff" setContentView(R.layout.activity_main);
android:textSize="24sp"
android:textStyle="bold"
android:textColor="#ffffffff"
txtMsg = (TextView) findViewById(R.id.txtMsg);
android:padding="2dip" />
<GridView
android:id="@+id/grid"
android:background="#77ffff00"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:verticalSpacing="5dip"
android:horizontalSpacing="5dip"
android:numColumns="auto_fit"
android:columnWidth="100dip"
android:stretchMode="spacingWidth" />
</LinearLayout>
5 29
- 29 5 - 30
grid.setAdapter(adapter);
• Suggestions matching the typed prefix are shown in a selection list.
grid.setOnItemClickListener(new OnItemClickListener() {
• The user can choose from the suggestion list or complete typing the
@Override
public void onItemClick(AdapterView<?> container, View v, word.
int position, long id) {
txtMsg.setText(items[position]);
} • The android:completionThreshold property is used to trigger the
}); displaying of the suggestion list. It indicates the number of characters to
}//onCreate
watch for in order to match prefixes.
}// class
NOTE: For other features of the TextView control see Appendix B
5 - 31 5 - 32
The AutoComplete TextView Widget The AutoComplete TextView Widget
Example4: AutoComplete Demo - Layout
Example 4.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
A list of selected xmlns:tools="http://schemas.android.com/tools"
words beginning android:layout_width="match_parent"
android:layout_height="match_parent" >
with “wor” or “set”
Tap to select
is being watched. <TextView
this option android:id="@+id/txtMsg"
android:layout_width="match_parent"
If any of these android:layout_height="wrap_content"
prefixes (3 letters) android:textSize="20sp"
android:textColor="#ffffffff"
are entered the android:background="#ff0000ff" >
TextWatcher </TextView>
mechanism shows <AutoCompleteTextView
an option list. android:id="@+id/autoCompleteTextView1"
android:hint="type here..."
android:completionThreshold="3" Wait 3 chars to work
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/txtMsg"
android:layout_marginTop="15dp"
android:ems="10" />
5 - 33 </RelativeLayout> 5 - 34
}//class
5 - 35 5 36
- 36
The HorizontalScrollView Widget The HorizontalScrollView Widget
Example5: HorizontalScrollView Demo
HorizontalScrollViews allow the user to
graphically select an option from a set of • In this example we place a
small images called thumbnails +. HorizontalScrollView
at the top of the screen, this view will
The user interacts with the viewer using show a set of thumbnail options.
two simple actions:
1. Scroll the list (left ⟷ right)
2. Click on a thumbnail to pick the option
• The user may scroll through the images and
it offers. finally tap on a particular selection.
In our example, when the user clicks on a • A better quality version of the selected
thumbnail the app responds by displaying a picture will be displayed in an ImageView
high-resolution version of the image widget placed below the horizontal scroller.
Thumbnail makers
MakeAThumbnail ©. Available at http://makeathumbnail.com
Last visited June 30, 2017.
The free high quality images used in this example were obtained from https://pixabay.com/
5 - 39 5 - 40
The HorizontalScrollView Widget The HorizontalScrollView Widget
Example5: Populating The HorizontalScrollView Widget Example5: HorizontalScrollView Demo – Layout 1 of 2
<?xml version="1.0" encoding="UTF-8"?>
1. Our HorizontalScrollView will expose a list of frames, each containing an <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
icon and a caption below the icon. android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ffffffff"
android:orientation="vertical"
2. The frame_icon_caption.xml layout describes the formatting of icon and android:padding="2dp" >
its caption. This layout will be inflated in order to create run-time GUI <TextView
objects. android:id="@+id/txtMsg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
3. After the current frame is filled with data, it will be added to the growing android:background="#ff00ff00"
android:text="scroll and click to select ..."
set of views hosted by the scrollViewgroup container (scrollViewgroup is android:textAppearance="?android:attr/textAppearanceLarge" />
nested inside the horizontal scroller). <HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
4. Each frame will receive an ID (its current position in the scrollViewgroup) android:background="#44aaaaaa" >
as well as an individual onClick listener. <LinearLayout
android:id="@+id/viewgroup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="10dip" >
</LinearLayout>
5 - 41 </HorizontalScrollView> 5 - 42
<TextView
android:id="@+id/caption"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:background="#33ffff00"
android:gravity="center"
android:textSize="20sp" />
</LinearLayout>
This layout will be used by an inflater to dynamically create new views. These views will
5 - 43 be added to the linear layout contained inside the HorizontalScrollerView. 5 - 44
The HorizontalScrollView Widget The HorizontalScrollView Widget
Example5: App’s Structure - Eclipse’s Package Explorer Example5: App’s Structure - Android Studio Package Explorer
5 - 45 5 - 46
<TextView <TextView
android:layout_width="match_parent" android:id="@+id/txtSoloMsg"
android:layout_height="wrap_content" android:layout_width="match_parent"
android:background="#ff0000ff" android:layout_height="wrap_content"
android:padding="3dp" android:textColor="@android:color/white"
android:text="Scrool screen, tap to choose" android:background="#ff0000ff" />
android:textColor="#ffffffff"
android:textSize="20sp" /> <ImageView
android:id="@+id/imgSoloPhoto"
<GridView android:layout_width="match_parent"
android:id="@+id/gridview" android:layout_height="0dip"
android:layout_width="match_parent" android:layout_gravity="center|fill"
android:layout_height="match_parent" android:layout_weight="2" />
android:layout_margin="1dp"
android:columnWidth="100dp" <Button
android:gravity="center" android:id="@+id/btnSoloBack"
android:horizontalSpacing="5dp" android:layout_width="100dip"
android:numColumns="auto_fit" android:layout_height="wrap_content"
android:stretchMode="columnWidth" android:layout_gravity="center_horizontal"
android:verticalSpacing="10dp" /> android:text="Back" />
</LinearLayout> </LinearLayout>
5 - 53 5 - 54
Using The GridView Widget to Show Images Using The GridView Widget to Show Images
Example6: GridView Images Demo – res/values/dimens/ Example6: App’s Structure – Eclipse’s Package Explorer
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="gridview_size">100dp</dimen>
</resources>
Best Practice: Defining the GridView’s high and width dimensions on dips is safer than in pixels.
Later on, images can be automatically scaled to devices of various densities.
On the left:
int gridsize = context.getResources()
.getDimensionPixelOffset(R.dimen.gridview_size);
imageView.setLayoutParams(new
GridView.LayoutParams(gridsize, gridsize));
On the right:
imageView.setLayoutParams(new
GridView.LayoutParams(100, 100));
//frame captions
String[] items = {"Photo-1", "Photo-2", "Photo-3", "Photo-4", "Photo-5",
"Photo-6", "Photo-7", "Photo-8", "Photo-9", "Photo-10", "Photo-11",
"Photo-12", "Photo-13", "Photo-14", "Photo-15", "Photo-16", "Photo-17",
"Photo-18", "Photo-19", "Photo-20", "Photo-21", "Photo-22", "Photo-23",
"Photo-24", "Photo-25", "Photo-26", };
5 - 57 5 - 58
Using The GridView Widget to Show Images Using The GridView Widget to Show Images
Example6: MainActivity 2 of 5 Example6: MainActivity 3 of 5
//frame-icons ( 100X100 thumbnails ) //large images (high quality pictures)
Integer[] thumbnails = {R.drawable.small_blossom_918453_1280 Integer[] largeImages = {R.drawable.large_blossom_918453_1280
, R.drawable.small_building_922529_1280 , R.drawable.large_building_922529_1280
, R.drawable.small_cat_914110_1280 , R.drawable.large_cat_914110_1280
, R.drawable.small_church_648430_1280 , R.drawable.large_church_648430_1280
, R.drawable.small_coffee_744151_1280 , R.drawable.large_coffee_744151_1280
, R.drawable.small_coffee_917613_1280 , R.drawable.large_coffee_917613_1280
, R.drawable.small_dubrovnik_512798_1280 , R.drawable.large_dubrovnik_512798_1280
, R.drawable.small_egg_943413_1280 , R.drawable.large_egg_943413_1280
, R.drawable.small_firefighters_696167_1280 , R.drawable.large_firefighters_696167_1280
, R.drawable.small_flower_870557_1280 , R.drawable.large_flower_870557_1280
,R.drawable.small_football_888015_1280 ,R.drawable.large_football_888015_1280
,R.drawable.small_isolated_219954_1280 ,R.drawable.large_isolated_219954_1280
,R.drawable.small_jetty_593401_1280 ,R.drawable.large_jetty_593401_1280
,R.drawable.small_jetty_598198_1280 ,R.drawable.large_jetty_598198_1280
,R.drawable.small_paraglider_701440_1280 ,R.drawable.large_paraglider_701440_1280
,R.drawable.small_pelican_336583_1280 ,R.drawable.large_pelican_336583_1280
,R.drawable.small_pelican_901004_1280 ,R.drawable.large_pelican_901004_1280
,R.drawable.small_pier_440339_1280 ,R.drawable.large_pier_440339_1280
,R.drawable.small_purpursonnenhut_861592_1280 ,R.drawable.large_purpursonnenhut_861592_1280
,R.drawable.small_roofs_919460_1280 ,R.drawable.large_roofs_919460_1280
,R.drawable.small_south_africa_927281_1280 ,R.drawable.large_south_africa_927281_1280
,R.drawable.small_stone_arch_828730_1280 ,R.drawable.large_stone_arch_828730_1280
,R.drawable.small_sunset_815270_1280 ,R.drawable.large_sunset_815270_1280
,R.drawable.small_tangerine_850432_1280 ,R.drawable.large_tangerine_850432_1280
,R.drawable.small_travel_857086_1280 ,R.drawable.large_travel_857086_1280
,R.drawable.small_tree_779827_1280 ,R.drawable.large_tree_779827_1280
,R.drawable.small_turtle_863336_1280 }; ,R.drawable.large_turtle_863336_1280 };
5 - 59 5 - 60
Using The GridView Widget to Show Images Using The GridView Widget to Show Images
Example6: MainActivity 4 of 5 Example6: MainActivity 5 of 5
});
}// showBigScreen
}//Activity
5 - 61 5 - 62
Using The GridView Widget to Show Images Using The GridView Widget to Show Images
Example6: Custom Adapter - MyImageAdapter 1 of 2 Example6: Custom Adapter - MyImageAdapter 2 of 2
// This custom adapter populates the GridView with a visual
// representation of each thumbnail in the input data set. // create a view for each thumbnail in the data set
// It also implements a method -getView()- to access public View getView(int position, View convertView, ViewGroup parent) {
// individual cells in the GridView.
private Context context; // main activity’s context // if possible, reuse (convertView) image already held in cache
Integer[] smallImages; // thumbnail data set if (convertView == null) {
// new image in GridView formatted to:
public MyImageAdapter(Context mainActivityContext,
// 100x75 pixels (its actual size)
Integer[] thumbnails) {
// center-cropped, and 5dp padding all around
context = maiActivityContext;
smallImages = thumbnails;
imageView = new ImageView(context);
}
imageView.setLayoutParams( new GridView.LayoutParams(100, 75) );
// how many entries are there in the data set? imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
public int getCount() { imageView.setPadding(5, 5, 5, 5);
return smallImages.length;
} } else {
imageView = (ImageView) convertView;
// what is in a given 'position' in the data set? }
public Object getItem(int position) {
return smallImages[position]; imageView.setImageResource(smallImages[position]);
}
// what is the ID of data item in given 'position‘? return imageView;
public long getItemId(int position) { }
return position;
} }//MyImageAdapter
5 - 63 5 - 64
Using The GridView Widget to Show Images Using The GridView Widget to Show Images
Example6: Custom Adapter - MyImageAdapter 2 of 2 Results generated by Example6 running on different devices
// create a view for each thumbnail in the data set, add it to gridview
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
} else {
imageView = (ImageView) convertView;
} Image taken from the Image displayed on a Nexus7 (1028x728) tablet.
imageView.setImageResource(smallImages[position]);
Emulator The GridView’s clause:
imageView.setId(position);
android:numColumns="auto_fit"
return imageView;
}//getView determines the best way to fill up each row.
5 - 65 5 - 66
}//MyImageAdapter
Using The GridView Widget to Show Images Using The GridView Widget to Show Images
Example6B: Example6B:
An Experiment - Changing from GridView to ListView An Experiment - Changing from GridView to ListView
Modify the previous example to show the set of thumbnails The new app should
in a ListView instead of a GridView. As before when a display the following
thumbnail is tapped a high-quality image is shown in a new screen. screens.
3. In the custom Image adapter make the following change to indicate the new
imageView should be added to a ListView (instead that a GridView)
imageView.setLayoutParams(new ListView
.LayoutParams(100, 75) );
4. Keep the rest of the adapter code unchanged. 5 - 67 5 - 68
Using The Spinner Widget (again…) Using The Spinner Widget (again…)
Example7: Spinner Demo2 - Layout1 (activity_main)
This is a simple variation of the
<?xml version="1.0" encoding="utf-8"?>
previous example. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
A list of choices is offered through a android:orientation="vertical"
drop-down spinner control. android:padding="3dp" >
<TextView
android:layout_width="match_parent"
The user taps on a row and an android:layout_height="wrap_content"
image for the selected choice is android:background="#ff0000ff"
android:text="Car selector"
displayed on a new screen. android:textColor="#ffffffff"
android:textSize="20sp"
android:textStyle="bold" />
<Spinner
android:id="@+id/spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dip" />
</LinearLayout>
5 - 70
Using The Spinner Widget (again…) Using The Spinner Widget (again…)
Example7: Spinner Demo2 - Layout2 (solo_picture) Example7: Spinner Demo2 - MainActivity 1 of 3
<?xml version="1.0" encoding="utf-8"?> public class MainActivity extends Activity implements
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" AdapterView.OnItemSelectedListener {
android:layout_width="match_parent" // GUI controls in the main screen
android:layout_height="match_parent" Spinner spinner;
android:padding="3dp"
android:orientation="vertical" >
// GUI controls in the solo_picture screen
<TextView TextView txtSoloMsg;
android:id="@+id/txtSoloMsg" ImageView imageSelectedCar;
android:layout_width="match_parent" Button btnBack;
android:layout_height="wrap_content"
android:textStyle="bold" // captions to be listed by the spinner
android:textColor="#FFFFFFFF" String[] items = { "Select a vehicle", "car1", "car2", "car3", "car4",
android:padding="3dp" "car5", "car6", "car7", "car8" };
android:background="#ff0000ff" /> // object IDs of car pictures
Integer[] carImageArray = new Integer[] { R.drawable.car_photo_1,
<ImageView
android:id="@+id/imgSoloPhoto"
R.drawable.car_photo_2, R.drawable.car_photo_3,
android:layout_width="match_parent" R.drawable.car_photo_4, R.drawable.car_photo_5,
android:layout_height="0dip" R.drawable.car_photo_6, R.drawable.car_photo_7,
android:layout_gravity="center|fill" R.drawable.car_photo_8, };
android:layout_weight="2" /> Bundle myStateInfo;
<Button @Override
android:id="@+id/btnBack" protected void onCreate(Bundle savedInstanceState) {
android:layout_width="100dip" super.onCreate(savedInstanceState);
android:layout_height="wrap_content" myStateInfo = savedInstanceState;
android:layout_gravity="center_horizontal"
android:text="Back" /> setContentView(R.layout.activity_main);
</LinearLayout>
5 - 71 5 - 72
Using The Spinner Widget (again…) Using The Spinner Widget (again…)
Example7: Spinner Demo2 - MainActivity 2 of 3 Example7: Spinner Demo2 - MainActivity 3 of 3
spinner = (Spinner) findViewById(R.id.spinner);
spinner.setAdapter(new ArrayAdapter<String>(this, // next two methods implement the spinner listener
android.R.layout.simple_spinner_dropdown_item, @Override
items)); public void onItemSelected(AdapterView<?> parent, View v, int position, long id) {
spinner.setOnItemSelectedListener(this);
//ignore position 0. It holds just a label ("SELECT A VEHICLE...")
}// onCreate if (position > 0) {
// display screen showing image of the selected car showBigImage(position - 1);
private void showBigImage(int position) { }
// show the selected picture as a single frame }
setContentView(R.layout.solo_picture);
txtSoloMsg = (TextView) findViewById(R.id.txtSoloMsg); @Override
imageSelectedCar = (ImageView) findViewById(R.id.imgSoloPhoto); public void onNothingSelected(AdapterView<?> parent) {
txtSoloMsg.setText("Car selected: car-" + position); // DO NOTHING - needed by the interface
}
imageSelectedCar.setImageResource(carImageArray[position]);
}
btnBack = (Button) findViewById(R.id.btnBack);
btnBack.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// redraw the main screen showing the spinner
onCreate(myStateInfo);
}
});
}// showBigScreen
5 - 73 5 - 74
}//MyCustomAdapter
5 - 75 5 - 76
Custom-made ListViews Custom-made ListViews
Example8: Designing Custom-Rows Example8: Designing Custom-Rows
In our example each UI row will show an icon (on the left side) and text
following the icon to its right side.
Custom row
Icon Text
5 - 77 5 - 78
<TextView
android:id="@+id/txtMsg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ff0000ff"
android:text="Your selection is ..."
android:textColor="#ffffffff"
android:textSize="24sp"
android:textStyle="bold" />
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ListView>
</LinearLayout>
5 - 79 5 - 80
Custom-made ListViews Custom-made ListViews
Example8: Layout2 – custom_row_icon_label.xml Example8: Custom ListView Demo – MainActivity 1 of 3
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" public class MainActivity extends ListActivity {
android:layout_width="fill_parent" TextView txtMsg;
android:layout_height="wrap_content" // The n-th row in the list will consist of [icon, label]
android:orientation="horizontal" > // where icon = thumbnail[n] and label=items[n]
String[] items = { "Data-1", "Data-2", "Data-3", "Data-4", "Data-5",
<ImageView "Data-6", "Data-7", "Data-8", "Data-9", "Data-10", "Data-11",
android:id="@+id/icon" "Data-12", "Data-13", "Data-14", "Data-15" };
android:layout_width="100dp"
android:layout_height="75dp" Integer[] thumbnails = { R.drawable.pic01_small, R.drawable.pic02_small,
android:layout_marginRight="3dp" R.drawable.pic03_small, R.drawable.pic04_small,
android:src="@drawable/ic_launcher" /> R.drawable.pic05_small, R.drawable.pic06_small,
R.drawable.pic07_small, R.drawable.pic08_small,
<TextView R.drawable.pic09_small, R.drawable.pic10_small,
android:id="@+id/label" R.drawable.pic11_small, R.drawable.pic12_small,
android:layout_width="match_parent" R.drawable.pic13_small, R.drawable.pic14_small,
android:layout_height="75dp" R.drawable.pic15_small };
android:background="#22ffff00"
android:textSize="20sp" /> @Override
protected void onCreate(Bundle savedInstanceState) {
</LinearLayout> super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txtMsg = (TextView) findViewById(R.id.txtMsg);
5 - 81 5 - 82
5 - 83 }// CustomAdapter 5 - 84
Custom-made ListViews Using the SD card
Example8: The LayoutInflater Class Example 9: Storing Images on the SD card
(A Variation on Example5)
• The LayoutInflater class converts an XML layout specification into an In previous examples, images were kept in
actual tree of View objects. The objects inflated by code are appended main storage using the application’s
to the selected UI view. It typically works in cooperation with an memory space.
ArrayAdapter.
This time we will use the external disk
(SD-card) to store the app’s data (arguably
• A basic ArrayAdapter requires three arguments: current context, layout
a better space/speed tradeoff practice).
on which output rows are shown, source data items (data to feed the
rows). Assume the user has already transferred a
copy of the pictures to the SD folder
• The overridden getView() method inflates the row layout by
/Pictures/thumbnails/
custom allocating icons and text taken from data source in the user
designed row.
• Once assembled, the View (row) is returned.
• This process is repeated for each item supplied by the ArrayAdapter.
• See Appendix C for an example of a better built custom-adapter
using the ViewHolder design strategy.
5 - 85 5 - 86
Using the SD card Using the SD card In this app we use the
same layouts already
introduced in Example5
//GUI controls
The folder /Pictures/large/ contains a TextView txtMsg;
high-quality image for each thumbnail. ViewGroup scrollViewgroup;
These larger pictures are shown after the //each frame in the HorizontalScrollView has [icon, caption]
ImageView icon;
user makes a selection using the scroller. TextView caption;
5 - 87 5 - 88
Using the SD card In this app we use the
same layouts already Using the SD card In this app we use the
same layouts already
introduced in Example5 introduced in Example5
5 - 89 }//onCreate 5 - 90
// convert SD image file(jpg, png,...) into a drawable, then show into ImageView
File sdLargePictureFolder = new File(pathLargePictureFolder);
File[] largePictureArray = sdLargePictureFolder.listFiles();
File largeImageFile = largePictureArray[frameId];
imageSelected.setImageDrawable(Drawable.createFromPath(
largeImageFile.getAbsolutePath()));
}//ShowLargeImage
}//Activity
Appendix B: EditText Boxes & Keyboarding Appendix B: EditText Boxes & Keyboarding
TextViews can use either XML elements or Java code to tell the type of
textual data they should accept. For example:
XML
android:inputType="phone"
Java
editTextBox.setInputType(
android.text.InputType.TYPE_CLASS_PHONE);
Knowing the inputType has an impact on virtual keyboards (the software can
expose the best layout for the current input class)
5 - 97 5 - 98
Appendix B: EditText Boxes & Keyboarding Appendix B: EditText Boxes & Keyboarding
Example10: Using multiple XML attributes
XML Usage – inputType Classes android:inputType="text|textCapWords"
<EditText
... <?xml version="1.0" encoding="utf-8"?>
<LinearLayout Use “pipe” symbol |
android:inputType=“numberSigned|numberDecimal” android:layout_width="match_parent" to separate the
... /> android:layout_height="match_parent"
android:background="#ffcccccc" options.
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android" >
In this example a
<TextView soft text keyboard
android:layout_width="match_parent"
android:layout_height="wrap_content" will be used.
android:background="#ff0000ff"
android:text="inputType: text|textCapWords"
android:textStyle="bold" Each word will be
android:textSize="22sp" />
capitalized.
<EditText
android:id="@+id/editTextBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5dip"
android:textSize="18sp"
Reference: android:inputType="text|textCapWords" />
http://developer.android.com/reference/and </LinearLayout>
roid/R.styleable.html#TextView_inputType 5 - 99 5 - 100
Appendix B: EditText Boxes & Keyboarding Appendix B: EditText Boxes & Keyboarding
Example10: Using android:inputType= " text|textCapWords" Example10: Using android:inputType= " text|textCapWords"
After tapping the EditText After first letter is typed the After entering space the English and Spanish are the You may speed up typing by Selected word is introduced in
box to gain focus, a soft keyboard automatically keyboard repeats cycle user’s selected languages tapping on an option from the EditText box
keyboard appears showing switches to LOWER case mode beginning with UPPER case, in this device the list of suggested words
CAPITAL letters then LOWER case letters. 5 - 101 (bilingual choices) 5 - 102
Appendix B: EditText Boxes & Keyboarding Appendix B: EditText Boxes & Keyboarding
Example 11: Using
Example 12: Using Example 13: Using
android:inputType="number|numberSigned|numberDecimal"
android:inputType="textPassword" android:inputType="textEmailAddress"
Additional symbols
5 - 105 5 - 106
Appendix B: EditText Boxes & Keyboarding Appendix B: EditText Boxes & Keyboarding
Example 16: Using android:inputType="time" Example 16: Using android:inputType="time"
When clicked, the Auxiliary button DONE Other options for
will removed the keyboard from the screen android:imeAction=“. . .”
(default behavior).
are
You may change the button’s caption and
set a listener to catch the click event on the
Auxiliary button. To do that add the
following entry to your XML specification of
the EditText box:
android:imeAction="actionSend"
editTextBox
.setOnEditorActionListener()
to do something with the event.
5 - 107 5 - 108
Appendix B: EditText Boxes & Keyboarding Appendix B: EditText Boxes & Keyboarding
Disable Soft Keyboarding on an EditText View
Example 17: Using android:inputType="datetime"
• To disable the action of the soft keyboard on an EditText
you should set its input type to null, as indicated below:
editTextBox.setInputType( InputType.TYPE_NULL );
• To temporarily hide the virtual keyboard, call the following method:
Soft keyboard displays a numerical layout.
public void hideVirtualKeyboard() {
Context context = getActivity().getApplicationContext();
Only digits and date/time valid characters ((InputMethodManager) context
are allowed. .getSystemService(Activity.INPUT_METHOD_SERVICE))
.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);
Examples of valid dates are: }
12/21/2012 12:12
• To display the virtual keyboard, call the method:
12/31/2011
12:30 public void showVirtualKeyboard() {
Context context = getActivity().getApplicationContext();
((InputMethodManager) context
.getSystemService(Activity.INPUT_METHOD_SERVICE))
.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);
}
5 - 109 5 - 110
Appendix C. Custom List Supported by a BaseAdapter Appendix C. Custom List Supported by a BaseAdapter
In this example a list holding rows showing multiple lines of text and images, is
populated with a custom made BaseAdapter that uses the ViewHolder strategy for
better performance.
An onClick listener is set to recognize the
user’s tapping on the image to the right side,
and another listener is set for clicking
anything from the rest of the row.
Click
on
Click image
on
row
The strategy of reusing these scrapviews is known as the ViewHolder Design Pattern.
It cuts down on the number of times you have to inflate a row-layout and then get
access to its internal widgets by calling the ‘findViewById()’ method.
When reusing the scrapviews (made available as ‘convertView’) all you need to do is
move the appropriate data to the internal widgets and set their onClick listeners.
5 - 113 5 - 114
Layout list_gui_row.xml shows a custom-made row holding two lines of text and two Layout list_gui_row.xml shows a custom-made row holding two lines of text and two
images. images.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" <TextView
android:layout_width="match_parent" android:id="@+id/rowTextView2"
android:layout_height="match_parent" android:layout_width="wrap_content"
android:orientation="horizontal" android:layout_height="wrap_content"
android:padding="16dp" > android:text="@string/text2"
android:textAppearance="?android:attr/textAppearanceSmall" />
<ImageView </LinearLayout>
android:id="@+id/rowImageView1"
android:layout_width="50dp" <ImageView
android:layout_height="50dp" android:id="@+id/rowImageView2"
android:contentDescription="@string/image_left" android:layout_width="50dp"
android:src="@drawable/ic_pic_left" /> android:layout_height="50dp"
<LinearLayout android:contentDescription="@string/image_right"
android:layout_width="0dp" android:src="@drawable/ic_launcher" />
android:layout_height="match_parent"
android:layout_marginLeft="20dp" </LinearLayout>
android:layout_weight="2"
android:orientation="vertical" >
<TextView
android:id="@+id/rowTextView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/text1"
android:textAppearance="?android:attr/textAppearanceLarge" /> 5 - 115 5 - 116
Appendix C. Custom List – MainActivity.java 1 of 1 Appendix C. Custom List – CustomBaseAdapter.java 1 of 5
The main activity exposes a ListView. A custom adapter is tied to the ListView. The The getView method in this extended BaseAdapter inflates a supplied row layout, gets
adapter gets a reference to a test ‘database’ and the custom row layout. access to its internal widgets, fills them with data and set listeners on some of them.
public class CustomBaseAdapter extends BaseAdapter {
public class MainActivity extends ActionBarActivity {
DATABASE database_records; Context context;
int layoutToBeInflated;
@Override List<DATABASE.DbRecord> dbList;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); public CustomBaseAdapter(Context context, List<DATABASE.DbRecord>
setContentView(R.layout.activity_main); databaseList, int resource) {
this.context = context;
ListView listview = (ListView) findViewById(R.id.listView1); this.dbList = databaseList;
layoutToBeInflated = resource;
//create an instance of our fake database: {[text1, text2, icon]} }
List database = new DATABASE().dbList;
@Override
CustomBaseAdapter adapter = new CustomBaseAdapter( this, public int getCount() {
database, return dbList.size();
R.layout.list_row_gui }
);
listview.setAdapter(adapter); @Override
public DATABASE.DbRecord getItem(int position) {
return dbList.get(position);
}//onCreate }
5 - 117 5 - 118
// use View-Holder pattern to reduce calls to inflate, findViewById // identify this row with the POJO holder just created
// holder is a POJO for the GUI rows [textview1,textview2, img1, img2] row.setTag(holder);
MyViewHolder holder;
} else {
// hopefully convertView is a scrapview already made (but out of sight) // row was already created- no need to inflate and invoke findViewById
View row = convertView; // getTag() returns the object originally stored in this view
holder = (MyViewHolder) row.getTag();
// has this row-layout been already created? }
if (row == null) {
// first time this row has to be created: (1) inflate custom layout // enter(or restore) data that goes in this frame (from database 'position')
// holding images and text, (2) invoke findViewById to access its DATABASE.DbRecord dbRec = getItem(position);
// sub-components holder.textview1.setText(dbRec.text1);
LayoutInflater inflater = ((Activity) context).getLayoutInflater(); holder.textview2.setText(dbRec.text2);
holder.imageview1.setImageResource(dbRec.img1);
row = inflater.inflate(layoutToBeInflated, null); holder.imageview2.setImageResource(R.drawable.ic_launcher);
// row listener (user clicks on any other part of the row) }// CustomMadeListener
row.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(context,
"ROW CLICKED - " + position, 1).show();
}
});
return row;
}// getView
5 - 121 5 - 122