I'm new to Android programming. I can get simple ListViews to work in which I use an ArrayList of strings. I want to take a step upward in complexity and have my ListView be composed of simple Java objects like this:
class myItem {
public String name;
public Integer price;
public Integer weight;
}
The ListView only needs to display the name in the above object. It doesn't have to have multiple icons, or multiple clickable actions for each item.
But I don't know where to start. All of the examples I see on the WWW are much more complicated and require me to learn things that have nothing to do with this (like a database). Or each ListView items is displayed with multiple views like text and images and icons etc. and each is clickable for a different action. I don't need any of that, and I'm getting bogged down reading about unneeded features in order to get those examples to work.
Does anyone have an example of a simple ListView that contains simple Java objects (like the one above)?
But I don't know where to start.
Implement a public String toString() method on myItem. Then create an ArrayList<myItem> and use that instead of ArrayList<String>, populate that list with suitable myItem instances, and put the list into an ArrayAdapter<myItem> instead of an ArrayAdapter<String>. No other changes should be required -- whatever layout you are using for an ArrayAdapter<String> will work with your ArrayAdapter<myItem>.
In case you are new to Java, toString() is the standard Java method for returning a String representation of an object. The default behavior of ArrayAdapter is to call toString() on the object for the given list position and use that to fill in the row.
Related
As the question states I simply want to add more than one tag to an XML View. For example, say I want to set an array of strings AND a separate string from my resources. I know how to do them individually but I want to know if there's a way of attaching more than one tag to a view directly within the XML code.
Edit:
My plan was to have a LinearLayout (l#1) that contained a dynamic amount of of a different LinearLayout (l#2) and within that View there would be a Spinner and an EditText. I need one tag for the hint of the EditText and the other for the array of strings to populate the Spinner. In the entire layout there are a multiple l#1 each using l#2 to populate it dynamically and each needing different hints and string arrays based on what they are used for.
My next idea was to add a integer as a tag to represent l#1 and and use a Switch/Case block in my code to populate the children of l#2 with the right hints and string arrays.
I don't think this is possible in XML, but in code what you could do is create a custom object which holds the strings you require and set that as the tag.
class CustomTagObject {
public List<Strings> strings;
public String myString;
}
Then later
CustomTagObject tagObj = new CustomTagObject();
tagObj.strings = new ArrayList<Strings>("String 1", "String 2");
tagObj.myString = "String from resources";
view.setTag(tagObj);
If you explain why you want to hold these items as the tag, I may be able to help you find an alternative approach?
Above solution works, but the usage is wrong(it will add extra overhead on your end to manage the key/value map).
The better way to achieve above is to use an overloaded method of setTag which allows you to specify id associated with the value.
Method signature:
public void setTag(int key, Object tag)
I am new to Android programming and have a basic question.
I have created a ListActivity where each row in its ListView has a TextView and a RatingBar. I am able to display values in the TextView and RatingBar by reading them from a pre-populated database; I am doing this via a custom CursorAdapter and it's bindView() method, i.e.
public class MyCursorAdapter extends CursorAdapter {
...
public void bindView(View view, Context context, final Cursor cursor) {
TextView name = (TextView)view.findViewById(R.id.name);
name.setText(cursor.getString(cursor.getColumnIndex(MyDbAdapter.KEY_NAME)));
RatingBar rating = (RatingBar)view.findViewById(R.id.life_bar_rating);
rating.setRating(cursor.getFloat(cursor.getColumnIndex(MyDbAdapter.KEY_RATING_VALUE)));
}
...
}
Now, my problem is that in my ListActivity I want the user to be able to click a "Save" button so that all changes are saved to the database in one go?. How would I iterate through the adapter to get the row ID and rating values so they can be saved (or is there another better way of doing this?).
The reason why I want to do a save in one go is because I thought it would be bad practice to update the database every time the user makes a change to a single rating (even though this is easier) as this causes more wear and tear on flash memory. I may be wrong about this, but I thought that there are a limited number of reads and writes with flash memory.
Remember the Adapter's backing array? The one you used to initialize it? save that ;)
or if that doesn't work...
for(int i = 0; i < listView.getAdapter().getCount(); i++)
SaveThing(listView.getAdapter().getItem(i));
if you need SQLite examples of saving... tomorrow.
edit for same of keeping comments clean:
as far as that object thing goes - you're free to cast it to anything that's in the listview. the data type, not view type.
so for example, an arrayAdapter that works with strings still returns Objects. but you will most certainly cast them to Strings because you know that's what you put in. it's awkward but thats how it is.
I've got what I thought was a simple android UI design problem but I've been going around in circles for a couple of days. I have a REST service that I'm downloading XML from and displaying the XML in a form in an android app. I have a web page built and am mimicking this with android, same options, same URLs being sent to the REST service whether from android or the web pages. With HTML I can easily create checkbox groups and radiobutton/dropdowns for various id/display items, so for instance, I can display a planet option as:
<select name="planet"><option value="0">Mercury</option></select>
I wanted to do something similar in android where I had a pair of values, one an id and the other the user-friendly text to display. So I decided to create an adapter using android.util.Pair:
public class PairView extends Pair<String, String> {
public PairView(String first, String second) {
super(first, second);
}
public String toString() {
return second;
}
}
public class PairAdapter extends ArrayAdapter<PairView> {
}
So now I can put my id in pair.first and what to display to the user in pair.second.
My problem comes in that some of these options will be single-selects and some will be multi-selects. In html, that's not an issue, just use a checkbox group for multi, and radio buttons/dropdowns for single selects. In android however, it seems it's not so straight forward. I tried using Spinners for the adapters, but Spinner seems to only allow single selection. AlertDialog.Builder allows for single and multi-selections, but curiously I don't see an option for using an adapter for the multi-selection, just for single selections.
I guess what I really want is a consistent look for all my options, with radio buttons displayed for single selections and checkboxes displayed for multi selections, via an adapter so I can get the id's from the Pair for the items selected.
What approach should I use? A custom spinner with code added for multi-selections? AlertDialog.Builder and somehow make it use an adapter for multi-selections? Just create a plain Alert and wrap a ListView in it? Another option that is (hopefully) simpler?
I feel like I'm missing something very basic here.
I had a similar situation in an app I was making so would share what I opted for. I had different type of questions and depending on that I removed and added things in my activity. For radio buttons I used with elements in it. For multiple choice questions I wanted a checkbox based view so I added an empty within my layout and in code added CheckBox(s) to it.
As for the caption and value, for radio buttons and checkboxes you can set display text by setText and add any object/value as a tag. So what I used to do was something like this:
CheckBox option = new CheckBox(MyActivity.this);
option.setText("Option 1");
option.setTag(10);
Later on when you get the selected option, you can simply get its tag and use its value.
This is just one way of doing it which I found simple. Hope this helps
Following on from an earlier question I'm trying to get multiple (widgets or in this case WebViews) inside a GridView.
So I wasn't really sure how to go about it whether to make my own adapter (seemed scary at the time) or create an ArrayAdapter<WebView>.
I wasn't really sure if ArrayAdapter could accept it like this or if it only supported primitive types.
GridView contentGrid;
LinearLayout contentLayout;
WebWidget[] webWidgets;
WebWidget web1;
WebWidget web2;
WebWidget web3;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
web1 = new WebWidget(this, "http://www.google.ie");
web2 = new WebWidget(this, "http://www.facebook.com");
web3 = new WebWidget(this, "http://www.youtube.ie");
webWidgets = new WebWidget[]{web1,web2,web3};
contentGrid = (GridView) findViewById(R.id.contentGrid);
//Heres my attempt at an adapter for webview
ArrayAdapter<WebView> adapter = new ArrayAdapter<WebView>(this,
android.R.layout.simple_list_item_1, webWidgets);
contentGrid.setAdapter(adapter);
Unfortunately what comes out is the string version of the WebView.
So question is can I do it this way or am I better of making my own CustomAdapter?
NOTE: Could someone maybe point some information as to what the second constructor variable is? I.E android.R.layout.simple_list_item_1
No matter how you implement your Adapter, you cannot reliably put scrollable widgets in other scrollable widgets, at least where they scroll in the same direction. Since both WebView and GridView scroll vertically, you will get unreliable results trying to combine them this way.
With that, on to some of your statements and questions:
I wasn't really sure if ArrayAdapter could accept it like this or if it only supported primitive types.
An ArrayAdapter can adapt a Java array or an ArrayList of whatever data type you like.
Unfortunately what comes out is the string version of the webview...NOTE: Could someone maybe point some information as to what the second constructor variable is? I.E android.R.layout.simple_list_item_1
The second constructor variable is what you want the cells in your GridView to look like. In your case, you are specifying a built-in layout resource that is a TextView. Hence, you are telling Android you want all your grid cells to be TextView widgets. Android will call toString() on the objects in your array, pour that result into the TextView, and the TextViews will go in your grid cells.
If you want your ArrayAdapter to be returning things other than a TextView, you will need to override getView() and handle more of that yourself, possibly using a layout file of your own creation.
So question is can I do it this way or am i better of making my own CustomAdapter?
As noted at the outset of my answer, what you want simply will not work reliably.
Pretending for the moment that having WebViews in a GridView would work, the simplest solution would be for you to override getView() in your own subclass of ArrayAdapter, as I mentioned previously. Here is a free excerpt from one of my books that goes over this process.
I'm wondering a simple way to find back the object corresponding to the clicked item..
They're tons of examples on the web on how to figure out the ListView setup with the setListAdpater, but much less on how to well handle its listener.
Is "by position" the only way ?? I'm wondering a possibility to associate the objects itselves to the adapter, to not have to use their position in list (or even the displayed String!) to find back the Object referred by the clicked label..
Position is what is used always. The ListView works with using the position.
But if you want to access the ListAdapter and get a value out by providing a string, than you will have to extend ListView and implement that functionality yourself. You can overwrite the different methods that handle adding and removing and keep a HashMap where you keep the string representing the object. Then through a getObject(String key) you return the object that is in the hashmap for that key.