If we have the need to present the various items with different layouts, we can do it in a simple way by using the excellent engineering of the base Adapter class, adapting it for our needs. Let's suppose to want to show an icon next to the textual item description if item text contains a given character sequence, let's say it starts with 'a' character to make a simple example.
First of all we need two View class derived objects to show the data into the ListView. The first one, 'SView1' in our example, simply derives from TextView class and it will be populated with text string passed as parameter in its constructor.
public class SView1 extends TextView {
TextView mText;
public SView1 (Context context, String text)
{
super(context);
setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
setText(text);
}
}
The second one, 'SView2', is slightly more complex and extends LinearLayout, a class designed to group and organize child Views. In SView2 we'll create two children objects, an ImageView to handle the icon, read from the resources, and a TextView which will contains the data strings.
public class SView2 extends LinearLayout {
String Title="";
TextView mText;
ImageView mView;
public SView2 (Context context, String text)
{
super(context);
this.setOrientation(HORIZONTAL);
setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
mView = new ImageView(mContext);
mView.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
mView.setImageResource(R.drawable.icon);
addView(mView);
mText = new TextView(context);
mText.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
addView(mText);
setText(text);
}
public void setText(String text)
{
mText.setText(text);
}
}
Now we have only to personalize the data hander, Adapter class. We can create a class that extends directly ArrayAdapter<> class. The data handling methods can be inherited from the superclass, by overloading only getView() method, called by parent ListView, at each data row visualization. What we will do in this method is only to check string content, and decide view type, SView1 or SView2 instantiate. Parent ListView can propose us to reuse an existent View object, if we want to use it, we should check that the proposed View type is coherent with data. Final step is in the Activity object: we should instantiate an Adapter e populate it with our data.
I was forgetting: yesterday RubyOnRails 2.0 was born, congratulations.
http://weblog.rubyonrails.org/2007/12/7/rails-2-0-it-s-done
Adapter:
public class SimpleStringAdapter extends ArrayAdapter
public SimpleStringAdapter(Context context, List
super(context,R.layout.a,Items);
}
public View getView(int position, View convertView, ViewGroup parent) {
String s = getItem(position);
boolean isType1 = true;
if( s==null )
s = "";
if(s.startsWith("a"))
{
isType1 = false;
}
if(isType1)
{
SView1 theView ;
if((null==convertView )||!(convertView instanceof SView1))
theView = new SView1(super.getContext(),s);
else
{
theView = (SView1)convertView;
theView.setText(s);
}
return theView ;
} else
{
SView2 theView ;
if((null==convertView )||!(convertView instanceof SView2))
theView = new SView2(super.getContext(),s);
else
{
theView = (SView2)convertView;
theView.setText(s);
}
return theView ;
}
}
}
Activity:
public class SimpleView extends ListActivity {
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
List
items.add("a riga 1");
items.add("a riga 2");
items.add("b riga 3");
items.add("a riga 4");
SimpleStringAdapter strings =
new SimpleStringAdapter(this, items);
setListAdapter(strings);
}
}
14 comments:
Excellent tutorial.
I greatly appreciate the effort you put into making this.
- acopernicus
That was exactly what I needed for my android inbox view . Thanks,
Toni
The content is nice, but the presentation here is royally screwed. I've got this nice widescreen monitor and the content of this block is about 1/3 the width of the screen and wrapped to an almost unreadable set of code. Why use a style that doesn't adjust to the width of the window? Why?
Oddly there isn't enough information to complete the code, what is this reference to R.layout.a? Nothing discusses what it entails and we are left to guess.
Nice idea, but needs work.
Just in the SimpleView class, erase this line: setContentView(R.layout.main);
And replace in the SimpleStringAdapter class constructor, the R.layout.a with R.layout.main
Maybe you'll need to put the package before R.layout.main something like this: mypackage.R.layout.main
It will work!!!
I can't make it working.
The last line of the Activity:
"setListAdapter(strings);"
launch an error "sorry the application ... has stopped unexpectedly. Please try again"
If I remove this line, no error appears but obviously nothing is displayed.
Do you know what can be the problem ?
Thanks.
If I remove the method getView of the SimpleStringAdapter, I don't have any error, as well. So, there must be something wrong in this method.
As Eclipse doesn't like "String s = getItem(position);", I replaced it by "String s = (String) getItem(position);"
@vince:
ArrayAdapter<String> is parametrized, so getItem() should return a String type without compiler errors.
Sorry for the problem, I have not recompiled against recent SDK.
I get a Runtime Exception: "Your content must have a ListView whose id attribute is 'android.R.id.lst'".
This is just what I need however super.getContext() is underfined in BaseAdapater (in SDK 1.5)
I have tried replacing it with parent.getContext() it made the view but crashed on exiting GetView.
what should replace it??
Steve
An update for SDK1.5:
I was able to recreate a project with same sources with an important difference: in the child view, the LinearLayout.LayoutParams must be substitued with ListView.LayoutParams.
The views should be like that:
... public SView1 (Context context,
String text)
{
super(context);
this.setOrientation(HORIZONTAL);
setLayoutParams(
new ListView.LayoutParams( ListView.LayoutParams.FILL_PARENT,
ListView.LayoutParams.WRAP_CONTENT));
This is one of the resourceful and out knowledgeable post.Your blog profile is also good.
Android app developers
Its a good blog and i anticipate best of Internet users are brand your information, so please create more blogs like this, because its good benefit for those peoples.
Post a Comment