I'm trying to create section headers for my ListView in a way that some list rows have headers and some do not. So what i have is three xml layout files. fragment_listview.xml contains the <ListView>
row_listview.xml contains the content for ListView rows
header_listview.xml is for the section headers.
Feeds.java is my model class.
So in my adapter i have something like this:
public class FeedsArrayAdapter extends ArrayAdapter<Feeds> {
private Context context;
private List<Feeds> feeds;
private LayoutInflater vi;
FeedsArrayAdapter(Context c, List<Feed> ff){ //initializes all the class member fields }
public void getView(int position, View convertView, ViewGroup parent){
Feeds f = feeds.get(position);
if(f.headerNeeded()){
convertView = vi.inflate(R.layout.header_listview, null);
TextView textViewHeader = (TextView) convertView.findViewById(R.id.feed_header);
textViewHeader.setText(new SimpleDateFormat("dd/MM/yyyy").format(feed.date));
}
else {
convertView = vi.inflate(R.layout.row_listview, null);
TextView textViewfeedHeading = (TextView) convertView.findViewById(R.id.feed_heading);
TextView textViewfeedSubheading = (TextView) convertView.findViewById(R.id.feed_subheading);
TextView textViewfeedDate = (TextView) convertView.findViewById(R.id.textViewDate);
ImageView imageViewfeedIcon = (ImageView) convertView.findViewById(R.id.feed_icon);
ImageView imageViewfeedBanner = (ImageView) convertView.findViewById(R.id.feed_banner);
textViewfeedHeading.setText(feed.title);
textViewfeedSubheading.setText(feed.subtitle);
textViewfeedDate.setText(new SimpleDateFormat("dd/MM/yyyy").format(feed.date));
}
return convertView;
}
So this gives us something like this:
---header1----
---header2----
___Row 3_____
___Row 4_____
What i want is:
-----header 1------
_____Row 1_______
-----header 2------
_____Row 2_______
_____Row 3_______
_____Row 4_______
If i try to inflate row.listview in if(true) I get an exception.
Any approach how to resolve this.
you can use Sticky Header Library here
yourListView.addHeaderView(yourHeaderView);
See http://developer.android.com/reference/android/widget/ListView.html#addHeaderView%28android.view.View%29
use expandable listview with BaseExpandableAdapter
Related
I've written this code from a tutorial.
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
// TODO Auto-generated method stub
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View row = inflater.inflate(R.layout.single_row, viewGroup,false);
TextView title = (TextView) row.findViewById(R.id.txtTitle);
TextView description = (TextView) row.findViewById(R.id.txtDescription);
ImageView image = (ImageView) row.findViewById(R.id.imgPic);
SingleRow temp = list.get(i);
title.setText(temp.title);
description.setText(temp.description);
image.setImageResource(temp.image);
return row;
}
In this line of code:
TextView title = (TextView) row.findViewById(R.id.txtTitle);
I think a TextView is copied to a variable of the same kind. and then in this line of code:
title.setText(temp.title);
we fill that variable with something. then the row variable which is a View and it's not related to 'title' variable is returned.
How it works? I thinks these variables have nothing to do here.
This code inflates a new view, settings it's contents. This means that you're creating a new view programatically. It's often used i.e. when populating a list, where you'll have number of rows, each identical in structure, but with different values.
Here is how it works:
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
// Get the inflater service
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// Inflate view with ID = R.layout.single_row into the row variable
View row = inflater.inflate(R.layout.single_row, viewGroup,false);
// Get child views of row: title, description and image.
TextView title = (TextView) row.findViewById(R.id.txtTitle);
TextView description = (TextView) row.findViewById(R.id.txtDescription);
ImageView image = (ImageView) row.findViewById(R.id.imgPic);
// This get's some template view which will provide data: title, description and image
SingleRow temp = list.get(i);
// Here you're setting title, description and image by using values from `temp`.
title.setText(temp.title);
description.setText(temp.description);
image.setImageResource(temp.image);
// Return the view with all values set. This view will be later probably added somewhere as a child (maybe into a list?)
return row;
}
That's the method used to return the view for a row in the listview. row variable is actually related to title, as you can see here.-
TextView title = (TextView) row.findViewById(R.id.txtTitle);
in other words, title is a TextView inside row object, and that code retrieves it to set its text. To sum up, the whole getView method is inflating a single_row View, and setting properties for all relevant children of row.
View row = inflater.inflate(R.layout.single_row, viewGroup,false);
You are inflating a layout single_row
TextView title = (TextView) row.findViewById(R.id.txtTitle);
Initializing textview which is in singlerow.xml
title.setText(temp.title);
Setting title to textview.
You are infalting a layout for each row in listview.
Also it is better to use a viewHolder pattern.
http://developer.android.com/training/improving-layouts/smooth-scrolling.html
Also you can move the below to the constructor of adapter class and declare inflater as a class member
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
The below link may be of interest to you
How ListView's recycling mechanism works
Hello Stack Overflow Android Users,
Please help with the following question:
Problem
I'm writing an a feature for an app that lists species of fish.
I'm using a custom ListView Adapter class (let's call this FishSpeciesListAdapter) for the adapter. I have 27 fish species
recorded as a default for the program as for now (you will eventually be able to add
some yourself as well). The problem is that when I link the adapter to the actual listview xml object, it seems to iterate over the same 5-6 species all the time.
The problem must lie within the custom adapter because I've tested the recorded species and all species are different within a List that I pass to the adapter.
Here's the code where I set the adapter:
this.n_fishSpeciesListView = FindViewById<ListView> (Resource.Id.xml_fishSpeciesListView);
this.n_fishSpeciesListView.Adapter = new FishSpeciesListAdapter (this,
this.n_model.SpecieManager.Species);
Here's the Custom ListView Adapter code:
public class FishSpeciesListAdapter : BaseAdapter
{
Context n_context;
List<AppCode.Specie> n_specieData;
public FishSpeciesListAdapter (Context context, List<AppCode.Specie> specieData)
{
this.n_context = context;
this.n_specieData = specieData;
}
public override int Count {
get { return this.n_specieData.Count; }
}
public override Java.Lang.Object GetItem (int position)
{
return null;
}
public override long GetItemId (int position)
{
return 0;
}
// create a new ImageView for each item referenced by the Adapter
public override View GetView (int position, View convertView, ViewGroup parent)
{
View v;
if(convertView==null){
LayoutInflater li = LayoutInflater.FromContext(parent.Context);
v = li.Inflate(Resource.Layout.Adapter_FishSpeciesIcon, null);
ImageView iconImage = (ImageView)v.FindViewById(Resource.Id.xml_adapter_fishSpeciesIconImage);
TextView nameText = (TextView)v.FindViewById(Resource.Id.xml_adapter_fishSpeciesNameText);
TextView scientificNameText = (TextView)v.FindViewById(Resource.Id.xml_adapter_fishSpeciesScientificNameText);
nameText.Text = this.n_specieData[position].Name;
scientificNameText.Text = this.n_specieData[position].ScientificName;
if (this.n_specieData[position].RelatedMedia.AttachedPhotos.Count < 1)
{
iconImage.SetImageResource(Resource.Drawable.Icon);
}
else
{
iconImage.SetImageBitmap(BitmapFactory.DecodeByteArray(this.n_specieData[position].RelatedMedia.AttachedPhotos[0], 0, this.n_specieData[position].RelatedMedia.AttachedPhotos[0].Length));
}
}
else
{
v = convertView;
}
return v;
}
}
So when I execute the above code, here's a screenshot of what I get:
As you can see there are duplicates where I'm am positive that there are at least 27 different species recorded in the passed List variable. Any help as to why this is and how I can fix this would be very helpful.
My Research
I've read that it may be reusing the "View currentView" variable in the GetView method of the adapter. I found that information out in this link. I just don't know how to fix this in my case. Code examples would be nice or detailed directions. Thank you for your time.
From what I see, you're using the convertView object wrong. This object is available in case any Views have been recycled (for example a list item scrolled out of view). It is available so that you don't have to inflate from your layout xml again (which is a costly process).
What you should do is inflate from your layout xml if convertView==null. Otherwise use the convertView object.
if(convertView==null){
LayoutInflater li = LayoutInflater.FromContext(parent.Context);
v = li.Inflate(Resource.Layout.Adapter_FishSpeciesIcon, null);
}
else{
v=convertView;
}
Then use v to set all your values and return the View.
ImageView iconImage = (ImageView)v.FindViewById(Resource.Id.xml_adapter_fishSpeciesIconImage);
TextView nameText = (TextView)v.FindViewById(Resource.Id.xml_adapter_fishSpeciesNameText);
TextView scientificNameText = (TextView)v.FindViewById(Resource.Id.xml_adapter_fishSpeciesScientificNameText);
nameText.Text = this.n_specieData[position].Name;
scientificNameText.Text = this.n_specieData[position].ScientificName;
if (this.n_specieData[position].RelatedMedia.AttachedPhotos.Count < 1)
{
iconImage.SetImageResource(Resource.Drawable.Icon);
}
else
{
iconImage.SetImageBitmap(BitmapFactory.DecodeByteArray(this.n_specieData[position].RelatedMedia.AttachedPhotos[0], 0, this.n_specieData[position].RelatedMedia.AttachedPhotos[0].Length));
}
return v;
you need to reuse convertView when it already exists, or create a new view when it doesn't. In all cases, you have to give your textViews/imageViews the right properties :
public override View GetView (int position, View convertView, ViewGroup parent)
{
if(convertView==null){
LayoutInflater li = LayoutInflater.FromContext(parent.Context);
convertView = li.Inflate(Resource.Layout.Adapter_FishSpeciesIcon, null);
}
ImageView iconImage = (ImageView)convertView.FindViewById(Resource.Id.xml_adapter_fishSpeciesIconImage);
TextView nameText = (TextView)convertView.FindViewById(Resource.Id.xml_adapter_fishSpeciesNameText);
TextView scientificNameText = (TextView)convertView.FindViewById(Resource.Id.xml_adapter_fishSpeciesScientificNameText);
nameText.Text = this.n_specieData[position].Name;
scientificNameText.Text = this.n_specieData[position].ScientificName;
if (this.n_specieData[position].RelatedMedia.AttachedPhotos.Count < 1)
{
iconImage.SetImageResource(Resource.Drawable.Icon);
}
else
{
iconImage.SetImageBitmap(BitmapFactory.DecodeByteArray(this.n_specieData[position].RelatedMedia.AttachedPhotos[0], 0, this.n_specieData[position].RelatedMedia.AttachedPhotos[0].Length));
}
}
return convertView;
}
i want to build an application with a listview or whatever.. that looks very attractive and have some images and many more.But i cant find a good way to have that. I exactly want my application's UI like this images:
(source: coenraets.org)
(source: coenraets.org)
i want to display my app like this images please suggest me how can i do this? please if u know some tutorials then give the links.
Yes. Just place one ImageView and TextView in one xml layout. And, inflate this layout into one layout which is having the ListView And, do the process there for getting images from webservice or locally stored
Here i provide some example links that may very useful to you -
Lazy load of images in ListView
ListView with images
How to display a list of images in a ListView in Android?
You need to build the layout you want in a XML file, the same way you would do for an Activity. Then just inflate the XML layout for each row in your ListView and set its values and images.
Example of one ArrayAdapter that I've inflated with my own view (picture, text and checkbox):
private class FriendListAdapter extends ArrayAdapter<User> {
public FriendListAdapter(Activity a, int textViewResourceId, List<User> items) {
super(a, textViewResourceId, items);
}
public class ViewHolder{
public TextView username;
public ImageView image;
public CheckedTextView ctv;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View v = convertView;
ViewHolder holder;
if (v == null) {
LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.invite_friend_row, null);
holder = new ViewHolder();
holder.username = (TextView) v.findViewById(R.id.username);
holder.username.setTypeface(tf);
holder.image = (ImageView) v.findViewById(R.id.image);
holder.ctv = (CheckedTextView) v.findViewById(R.id.checked);
v.setTag(holder);
}
else{
holder = (ViewHolder) v.getTag();
}
final User user = getItem(position);
if(user != null){
holder.username.setText(user.getName());
holder.ctv.setChecked(user.isChecked());
holder.image.setImageView(user.getImage());
}
return v;
}
}
You get the idea!
I created the Layout design using java code only not from the XML Layout Designs. The code I used is following
public View getView(int position, View convertView, ViewGroup parent) {
TextView tv = new TextView(mContext);
tv.setText(hotelList.get(position).name);
return tv;
}
How to use layoutInflator for creating layout fro this. I need 2 more textviews in a single list item. the whole list contains 10 different list items
Please provide some codes for this. Help appreciated
I have gone through this before by having my static class too. Check this out, it will help:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View rowView = convertView;
if ( rowView == null) {
LayoutInflater inflator = this._activity.getLayoutInflater();
rowView = inflator.inflate(R.layout.todolistlisting, null);
TodoListViewHolder viewHolder = new TodoListViewHolder();
viewHolder._name = (TextView) rowView.findViewById(R.id.tVTLName);
viewHolder._completed = (TextView) rowView.findViewById(R.id.tVTLCCount);
viewHolder._remaining = (TextView) rowView.findViewById(R.id.tVTLRCount);
rowView.setTag(viewHolder);
}
TodoListViewHolder holder = (TodoListViewHolder) rowView.getTag();
VO_TodoList votodolist = this._items.get(position);
holder._name.setText(votodolist._title);
holder._completed.setText(votodolist._completed);
holder._remaining.setText(votodolist._remaining);
return rowView;
}
TodoListViewHolder is my view component holder here. like your TextView.
I guess you know how to make XML layout for this layout. So just make the XML layout and get the object of the main layout using the following code:
LinearLayout mainLayout=(LinearLayout) View.inflate(R.layout.yourlayout); //if yourlayout.xml is the name of the xml file you made and put in the layout folder.
To get the child of the layout, let's say if it's a TextView with the id text, then the code would be:
TextView textView=(TextView)mainLayout.findViewById(R.id.text);
You can add view at runtime by using inflater like this
LinerLayout linearLayout = (LinearLayout)inflater.inflate(R.layout.news_categories_item, null);
TextView categoryValueTextView = (TextView)linearLayout.findViewById(R.id.news_category_item_value);
mMainLinearLayout.addView(categoryValueTextView);
Here i am inflating one text view which is there in another linear layout(this is simple linear layout which holds only textview) at runtime and adding it to my main linear layout.
you can get the inflater object in your acitivity by using getLayoutInflater(). And if you want to get inflater in adapter you have to pass inflater object to constructor of adapter from your activity.
I want to display list of check boxes with one ImageView and TextView in it.
+-----------+----------+----------+
| CHECK_BOX | ImageVew | TextView |
+-----------+----------+----------+
This list should be multiple selectable.
How to prepare This list?
How to get all selected check boxes and corresponding TextView value?
Can some one please provide sample code for this.
Thanks,
PP.
Create an adapter and bind it to a listview. The layout seems simple enough (LinearLayout with horizontal orientation). You will need to extend the BaseAdapter class.
Assume your class that holds the data looks something like this:
public class BasicClass {
// Holds the ID for the row
public int ID;
// Holds the resource ID for the imageview
public int ImageID;
// Holds the text for the textview
public String Text;
}
Your getView method will look something like this:
public View getView(final int position, View convertView, ViewGroup parent) {
View v = convertView;
final BasicClass e = (BasicClass) getItem(position);
if (v == null) {
LayoutInflater vi = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.checkbox_list_item, null);
}
TextView txtTitle = (TextView)v.findViewById(R.id.checkbox_list_item_txtTitle);
ImageView img = (ImageView)v.findViewById(R.id.checkbox_list_item_img);
final CheckBox chSelected = (CheckBox)v.findViewById(R.id.checkbox_list_item_cbSelected);
txtTitle.setText(e.Text);
img.setBackgroundDrawable(mContext.getResources().getDrawable(e.ImageID))
chSelected.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
//Logic comes here to add and remove the selected items to a ArrayList<BasicCLass>
}
});
return v;
}
Better to use Listview Custom adapters by extending BaseAdapter class.
Refer this links
For multiple selectable refer this