The custom spinner adapter is similar to the custom list row & adapter, because we can use LayoutInflater.
(*edit: This code may not run as-is. Therefore, I have included project files associated with this post available for download at the end of this post.)
1) The spinner layout. This is how each row will look when the spinner is selected. In my example there are three text views as three rows.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" android:orientation="vertical">
<TextView
android:layout_height="wrap_content"
android:id="@+id/TextView01"
android:textSize="12px"
android:layout_width="match_parent"
android:textColor="#000000">
</TextView>
<TextView
android:layout_height="wrap_content"
android:id="@+id/TextView02"
android:layout_width="match_parent"
android:textSize="12px" android:textColor="#000000"></TextView>
<TextView
android:layout_height="wrap_content"
android:id="@+id/TextView03"
android:layout_width="match_parent"
android:textSize="12px"
android:textColor="#000000">
</TextView>
</LinearLayout>
2) The custom adapter
// CUSTOM SPINNER ADAPTER
public class MyCustomSpinnerAdapter extends ArrayAdapter<String> {
public MyCustomSpinnerAdapter(Context context, int textViewResourceId,
String[] objects) {
super(context, textViewResourceId, objects);
// TODO Auto-generated constructor stub
}
@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
return getCustomView(position, convertView, parent);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
return getCustomView(position, convertView, parent);
}
public View getCustomView(int position, View convertView,ViewGroup parent) {
// TODO Auto-generated method stub
// return super.getView(position, convertView, parent);
LayoutInflater inflater = getLayoutInflater();
ViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.customspinneritem, null);
holder = new ViewHolder();
holder.txt01 = (TextView) convertView.findViewById(R.id.TextView01);
holder.txt02 = (TextView) convertView.findViewById(R.id.TextView02);
holder.txt03 = (TextView) convertView.findViewById(R.id.TextView03);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.txt01.setText("Route")
holder.txt02.setText("Strength");
holder.txt03.setText("Form");
return convertView;
}
class ViewHolder {
TextView txt01;
TextView txt02;
TextView txt03;
}
} // end custom adapter
3) Calling the spinner & setting the adapter
Spinner spinner = (Spinner) findViewById(R.id.spinner1);
spinner.setPrompt("Select One");
spinner.setAdapter(new MyCustomSpinnerAdapter(this, 0, items));
spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
// your code here
}
@Override
>public void onNothingSelected(AdapterView<?> parentView) {
// your code here
}
});
4) Setting string items
String[] items = { "Route 1, Strength 1, Form 1", "Route 2, Strength 2, Form 2", "Route 3, Strength 3, Form 3" };
Downloads:
main.xml
customspinneritem.xml
CustomSpinnerActivity.java (select "qui")
Resources:
My previous Spinner post
Android Dev Tutorial - Hello Spinner
Custom List Row Layout w/ Adapter
Friday, January 28, 2011
Simple Spinner w/ Array Adapter
Very basic stuff here, people. If you haven't yet, get acquainted with android spinner using the dev tutorial.
1) Calling the spinner, defining the array adapter.
Spinner spinner= (Spinner) findViewById(R.id.spinner);
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<String>(
this, android.R.layout.simple_spinner_item, items);
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setPrompt("Select One");
spinner.setAdapter(spinnerArrayAdapter );
spnRoute.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parentView,
View selectedItemView, int position, long id) {
// your code here
}
@Override
public void onNothingSelected(AdapterView<?> parentView) {
// your code here
}
});
2) The string array
String[] items = { "lorem", "ipsum", "dolor", "sit", "amet"};
1) Calling the spinner, defining the array adapter.
Spinner spinner= (Spinner) findViewById(R.id.spinner);
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<String>(
this, android.R.layout.simple_spinner_item, items);
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setPrompt("Select One");
spinner.setAdapter(spinnerArrayAdapter );
spnRoute.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parentView,
View selectedItemView, int position, long id) {
// your code here
}
@Override
public void onNothingSelected(AdapterView<?> parentView) {
// your code here
}
});
2) The string array
String[] items = { "lorem", "ipsum", "dolor", "sit", "amet"};
Friday, January 14, 2011
Seriously, this is how I made a multi-column list item populated by strings!!
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/LinearLayout01"
android:layout_alignParentLeft="true"
android:layout_height="fill_parent"
android:orientation="vertical"
android:layout_width="fill_parent">
<TextView
android:layout_height="wrap_content"
android:id="@+id/TextView_Title"
android:text="Title"
android:textSize="15px"
android:layout_width="fill_parent"></TextView>
<LinearLayout
android:id="@+id/LinearLayout02"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:layout_height="wrap_content"
android:id="@+id/TextView_Item1"
android:text="Item1"
android:layout_width="wrap_content"
android:textSize="10px" android:layout_weight="1"/>
<TextView
android:layout_height="wrap_content"
android:id="@+id/TextView_Item2"
android:text="Item2"
android:layout_width="wrap_content"
android:textSize="10px" android:layout_weight="1"/>
<TextView
android:layout_height="wrap_content"
android:id="@+id/TextView_Item3"
android:text="Item3"
android:layout_width="wrap_content"
android:textSize="10px" android:layout_weight="1"/>
</LinearLayout>
</LinearLayout>
2) Build the custom adapter:
// CUSTOM TWO ROW LIST ADAPTER
static class EfficientAdapter extends BaseAdapter {
private LayoutInflater mInflater;
public EfficientAdapter(Context context) {
mInflater = LayoutInflater.from(context);
}
public int getCount() {
return title.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.listitem_addrx, null);
holder = new ViewHolder();
holder.txtTitle = (TextView) convertView.findViewById(R.id.TextView_Title);
holder.txtItem1 = (TextView) convertView.findViewById(R.id.TextView_Item1);
holder.txtItem2 = (TextView) convertView.findViewById(R.id.TextView_Item2);
holder.txtItem3 = (TextView) convertView.findViewById(R.id.TextView_Item3);
convertView.setTag(holder);
holder = (ViewHolder) convertView.getTag();
}
holder.txtTitle.setText(title.get(position));
holder.txtItem1.setText(one.get(position));
holder.txtItem2.setText(two.get(position));
holder.txtItem3.setText(three.get(position));
return convertView;
}
static class ViewHolder {
TextView txtTitle;
TextView txtItem1;
TextView txtItem2;
TextView txtItem3;
}
} // end custom adapter
3) Call the following items:
static ListView lv;
public static ListAdapter adapter;
String selected;
static final ArrayList<String> title = new ArrayList<String>();
static final ArrayList<String> one = new ArrayList<String>();
static final ArrayList<String> two = new ArrayList<String>();
static final ArrayList<String> three = new ArrayList<String>();
4) Set the list adapter:
lv = (ListView) getListView();
lv.setAdapter(new EfficientAdapter(this));
5) Add entries to list:
Either define a string array when you call the variables in step 3 or add items dynamically:
title.add(selected);
route.add(selected);
strength.add(selected);
form.add(selected);
lv.setAdapter(new EfficientAdapter(getBaseContext()));
References (& many, many thanks to):
Custom list row & adapter: http://www.androidpeople.com/android-custom-dynamic-listview/
Custom spinner row & adapter: http://android-er.blogspot.com/2010/12/custom-arrayadapter-for-spinner-with.html
Update with my version later...
Custom Button Using XML
1. Create a custombuttonlayout.xml file in the drawable folder
Selector: this element surrounds the entire xml. It defines this drawable as a selecter (e.g. buttons, list rows, or anything that can be "selected")
Items: There are three buttons states that must be defined: pressed, focused, normal. However, there are a total of seven states that can be defined(pressed, focused, selected, checkable, checked, enabled, and window_focused).These are defined as three separate "items". Due to the nature of the way java programs are read (basically from the top down) you need to define items in this specific order, with pressed first, focused next, and normal last to get the buttons to display correctly.
Gradient: Android buttons typically have a highlight/lowlight gradient, so you should define two colors, and the angle of the "shadow".
Stroke: I think this defines the outline style of the button? Not too sure...
Corners: creates a rounded button corner. The default android radius value is "5dp".
Padding: This defines the blank space between the button text and the button borders.
custombuttonlayout.xml
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_pressed="true">
<shape>
<gradient
android:startColor="#FFFF40"
android:endColor="#FFFFC0"
android:angle="270" />
<stroke
android:width="1dp"
android:color="#000000" />
<corners
android:radius="5dp" />
<padding
android:left="10dp"
android:top="15dp"
android:right="10dp"
android:bottom="15dp" />
</shape>
</item>
<item
android:state_focused="true">
<shape>
<gradient
android:endColor="#8080FF"
android:startColor="#C0C0C0"
android:angle="270" />
<stroke
android:width="1dp"
android:color="#4A494A" />
<corners
android:radius="5dp" />
<padding
android:left="10dp"
android:top="15dp"
android:right="10dp"
android:bottom="15dp" />
</shape>
</item>
<item>
<shape>
<gradient
android:endColor="#8080FF"
android:startColor="#C0C0C0"
android:angle="270" />
<stroke
android:width="1dp"
android:color="#000000" />
<corners
android:radius="5dp" />
<padding
android:left="10dp"
android:top="15dp"
android:right="10dp"
android:bottom="15dp" />
</shape>
</item>
</selector>
2. In the main.xml layout when you insert a button that you want to apply the layout to:
Define the button background source as the drawable/custombuttonlayout.xml from above.
excerpt from main.xml:
<Button
android:layout_width="wrap_content"
android:text="Sample Text"
android:id="@+id/Button01"
android:layout_height="wrap_content"
android:background="@drawable/custombuttonlayout"></Button>
Resources:
1) http://developer.android.com/guide/topics/resources/drawable-resource.html#StateList
2) http://developer.android.com/guide/topics/resources/color-list-resource.html
3) http://developer.android.com/reference/android/widget/Button.html
4) http://androiddrawableexplorer.appspot.com/
5) http://developer.android.com/guide/topics/resources/drawable-resource.html#Shape
Selector: this element surrounds the entire xml. It defines this drawable as a selecter (e.g. buttons, list rows, or anything that can be "selected")
Items: There are three buttons states that must be defined: pressed, focused, normal. However, there are a total of seven states that can be defined(pressed, focused, selected, checkable, checked, enabled, and window_focused).These are defined as three separate "items". Due to the nature of the way java programs are read (basically from the top down) you need to define items in this specific order, with pressed first, focused next, and normal last to get the buttons to display correctly.
Gradient: Android buttons typically have a highlight/lowlight gradient, so you should define two colors, and the angle of the "shadow".
Stroke: I think this defines the outline style of the button? Not too sure...
Corners: creates a rounded button corner. The default android radius value is "5dp".
Padding: This defines the blank space between the button text and the button borders.
custombuttonlayout.xml
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_pressed="true">
<shape>
<gradient
android:startColor="#FFFF40"
android:endColor="#FFFFC0"
android:angle="270" />
<stroke
android:width="1dp"
android:color="#000000" />
<corners
android:radius="5dp" />
<padding
android:left="10dp"
android:top="15dp"
android:right="10dp"
android:bottom="15dp" />
</shape>
</item>
<item
android:state_focused="true">
<shape>
<gradient
android:endColor="#8080FF"
android:startColor="#C0C0C0"
android:angle="270" />
<stroke
android:width="1dp"
android:color="#4A494A" />
<corners
android:radius="5dp" />
<padding
android:left="10dp"
android:top="15dp"
android:right="10dp"
android:bottom="15dp" />
</shape>
</item>
<item>
<shape>
<gradient
android:endColor="#8080FF"
android:startColor="#C0C0C0"
android:angle="270" />
<stroke
android:width="1dp"
android:color="#000000" />
<corners
android:radius="5dp" />
<padding
android:left="10dp"
android:top="15dp"
android:right="10dp"
android:bottom="15dp" />
</shape>
</item>
</selector>
2. In the main.xml layout when you insert a button that you want to apply the layout to:
Define the button background source as the drawable/custombuttonlayout.xml from above.
excerpt from main.xml:
<Button
android:layout_width="wrap_content"
android:text="Sample Text"
android:id="@+id/Button01"
android:layout_height="wrap_content"
android:background="@drawable/custombuttonlayout"></Button>
Resources:
1) http://developer.android.com/guide/topics/resources/drawable-resource.html#StateList
2) http://developer.android.com/guide/topics/resources/color-list-resource.html
3) http://developer.android.com/reference/android/widget/Button.html
4) http://androiddrawableexplorer.appspot.com/
5) http://developer.android.com/guide/topics/resources/drawable-resource.html#Shape
Monday, December 13, 2010
Date Picker Frustrations
The date picker for the scheduler part of my app has somehow completely disappeared from existence. Did I dream that this was a working widget and never bothered to try it out in real life!? Anyhow, I'm trying to implement a date picker from an options menu click event inside a tabhost and the code is giving me a load of problems. Damn you, ambiguously written android dev tutorial!
The result -- I think trying to implement a date picker in tabhost is impossible. Something about the content view... had to work around the problem by adding a "select a date" button into the activity controlling that particular tab and removing the troublesome item from the options menu.
The result -- I think trying to implement a date picker in tabhost is impossible. Something about the content view... had to work around the problem by adding a "select a date" button into the activity controlling that particular tab and removing the troublesome item from the options menu.
Friday, December 3, 2010
Saving State on Orientation Change
Problem:
Form loses state on orientation change. This is due to onCreate being called on orientation change. This affects pages with forms half-filled out becoming blank.
Solution:
In Manifest.xml, go to Application tab, select the Activity in question (yes, you have to do this for EVERY activity you want to protect). For Config Changes select “keyboardHidden” and “orientation”. Worked for me.
Repainting a ListView Adapter from a Separate Activity
Basically, I have a page with a search box. You search for something, get the results in the form of a list on a pop-up dialog (which has its own activity). When you select one of the results, the dialog closes, and the item is added to the original page with the search box. You can repeat this, ad nauseum. *NOTE* This method requires an API level of at least 1.6.
PageOne.java
Be sure to declare variables for the strings and adapter before onCreate. Static makes it available to use by other activities in the package:
static List<String> strings; ListView lv; static ListAdapter adapter;
Define these variables inside onCreate:
strings = new ArrayList<String>();
lv = getListView();
adapter = new ArrayAdapter<String>(this, R.layout.list_item, R.id.label, strings);
lv.setAdapter(adapter);
PageTwo.java
In the onClick method, add code to transform selected item to a string value. Then, adds the item to the String Array in PageOne. Last, notifyDataSetChanged on the adapter used in pageone:
@Override
public void onListItemClick(ListView parent, View v, int position, long id) {
selected = ((TextView) v).getText().toString();
PageOne.strings.add(selected);
((ArrayAdapter<String>) PageOne.adapter).notifyDataSetChanged();
this.finish();
}
PageOne.java
Be sure to declare variables for the strings and adapter before onCreate. Static makes it available to use by other activities in the package:
static List<String> strings; ListView lv; static ListAdapter adapter;
Define these variables inside onCreate:
strings = new ArrayList<String>();
lv = getListView();
adapter = new ArrayAdapter<String>(this, R.layout.list_item, R.id.label, strings);
lv.setAdapter(adapter);
PageTwo.java
In the onClick method, add code to transform selected item to a string value. Then, adds the item to the String Array in PageOne. Last, notifyDataSetChanged on the adapter used in pageone:
@Override
public void onListItemClick(ListView parent, View v, int position, long id) {
selected = ((TextView) v).getText().toString();
PageOne.strings.add(selected);
((ArrayAdapter<String>) PageOne.adapter).notifyDataSetChanged();
this.finish();
}
Subscribe to:
Comments (Atom)