2

I am having a hard time populating my ListView with dynamic items from my ArrayList and displaying them on the screen.

I have 2 xml files:
This is the activity file I want to populate my ListView with.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:id="@+id/activity_local_reps"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="airbornegamer.com.grgr4.ActivityLocalReps">

<ListView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/listView"
    android:layout_alignParentTop="true"
    android:layout_alignParentRight="true"
    android:layout_alignParentEnd="true" />

And my xml file I want to use to add an image/text to the listview:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<ImageView
    android:id="@+id/icon"
    android:layout_width="50dp"
    android:layout_height="50dp"
    android:layout_marginBottom="5dp"
    android:layout_marginLeft="5dp"
    android:layout_marginRight="5dp"
    android:layout_marginTop="5dp"
    android:src="@drawable/unknown_representative" />
<TextView
    android:id="@+id/Itemname"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="20sp"
    android:paddingTop="5dp"/>

In my file ActivityLocalReps.java:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_local_reps);
    //setting up data and populating repData.
    DisplayData(repData);
}    

public void DisplayData(LocalRepData repData){    
    allRepData = repData.queryAllNeededRepData();
    adapter=new ArrayAdapter<String>(this, R.layout.mylist, R.id.Itemname, allRepData);
}    

My allRepData has multiple elements in it, however the adapter does not seem to hook up the data to my listView. Any help would be great, thanks!

**Edit 1

public class LocalRepData {

Context mContext;

public LocalRepData(Context mContext) {
    this.mContext = mContext;
}    
//other methods and stuff........
}    

I'm using this class mostly for data retrieval, so currently I'm not extending anything there.

4 Answers 4

1

If LocalRepData is a class you created that contains info then I would say it is fine.

What you want to understand it seems is the relationship between a ListView and it's Adapter. So you build up a List<LocalRepData> theList;. Then you want to create a Custom Adapter for your ListView, so extend BaseAdapter and when you are instantiating the Adapter, you would want to pass in your list of LocalRepData. Inside your BaseAdapter you will grab each item from the List and grab its image and string, then attach them to your 2nd xml, and finally inflate the view, by returning it. So I will show you an example here of what I mean.

I create my own simple BaseAdapter, and use just a standard ListView. I use a container class with my items called WeatherLocation. WeatherLocation is just a class that stores the local weather of an area (weather, zipcode, description of the weather when it was parsed, etc...). What I will do is build up a List<WeatherLocations> weatherLocations, then pass it into my adapter. Once the adapter is instantiated it will grab each WeatherLocation (depending on the row being displayed) and inflate it.

List<WeatherLocation> savedList = dbHelper.getAllWeatherLocations();
    //savedList.add(new WeatherLocation(72, "04005", "Biddeford"));
    if(savedList.size() > 0){
        mWeatherLocationAdapter = new WeatherLocationAdapter(savedList, this, R.layout.view_weather_location);
        lvLocations.setAdapter(mWeatherLocationAdapter);
    }

You can see above that I build up my List of WeatherLocations and throw them, with my custom xml that I will be inflating for each view in the listview into my adapter when i instantiate it. Below is my custom adapter, only really 3 methods you care about, getCount, getItem, and getView(). GetCount and getView are the ones you absolutely have to focus on.

public class WeatherLocationAdapter extends BaseAdapter{
private List <WeatherLocation> mLocations;
private Context mContext;
private int rowForLocationToInflate;
private LayoutInflater inflater;
private SettingsManager mSettingsMananger;

public WeatherLocationAdapter(List<WeatherLocation> mLocations, Context mContext, int rowForLocationToInflate) {
    this.mLocations = mLocations;
    this.mContext = mContext;
    this.rowForLocationToInflate = rowForLocationToInflate;
    inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    // to grab the saved zipcode (selected zipcode)
    mSettingsMananger = new SettingsManager(mContext);
}

private void addLocation(WeatherLocation newLocation){
    mLocations.add(newLocation);
}

@Override
public int getCount() {
    return mLocations.size();
}

@Override
public WeatherLocation getItem(int position) {
    return mLocations.get(position);
}

@Override
public long getItemId(int position) {
    return 0;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
        //TODO build a viewholder

        // Inflate up
        View rowView = inflater.inflate(rowForLocationToInflate, parent, false);

        // Link up
        TextView tvZipcode = (TextView) rowView.findViewById(R.id.tvZipCode);
        TextView tvCity = (TextView) rowView.findViewById(R.id.tvCity);
        TextView tvTemp = (TextView) rowView.findViewById(R.id.tvDegree);

        // we will do logic here to pick the image
        TextView tvDesc = (TextView) rowView.findViewById(R.id.tvDesc);
        TextView tvTime = (TextView) rowView.findViewById(R.id.tvTimeStamp);
        ImageView ivWeather  =  (ImageView) rowView.findViewById(R.id.ivWeather);
        TextView tvSelected = (TextView) rowView.findViewById(R.id.tvCurrentlySelected);

        tvZipcode.setText(mLocations.get(position).getZipcode());
        tvCity.setText(mLocations.get(position).getCity());
        tvTemp.setText(String.valueOf(mLocations.get(position).getTemperature()));
        tvDesc.setText(mLocations.get(position).getDesc());

        // whats currently selected.
        if(mSettingsMananger.getZipCode().equals(mLocations.get(position).getZipcode())){
            tvSelected.setText("Currently Selected");
        }

        // Format the saved time.
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(mLocations.get(position).getTime_stamp());
        String time = checkForMilitaryTime(cal.getTime().getHours(), cal.getTime().getMinutes());
        tvTime.setText(time);

        // Decide what image to display - based off the description we got back.
        String desc = mLocations.get(position).getDesc();
        if(desc.equals("sky is clear")){
            ivWeather.setImageDrawable(mContext.getResources().getDrawable(R.drawable.ic_action_sun));
        }
        else if(desc.equals("few clouds")){
            ivWeather.setImageDrawable(mContext.getResources().getDrawable(R.drawable.ic_action_cloudy));
        }
        else if(desc.equals("broken clouds")){
            ivWeather.setImageDrawable(mContext.getResources().getDrawable(R.drawable.ic_action_cloudy));
        }
        else if(desc.equals("light intensity shower rain")){
            ivWeather.setImageDrawable(mContext.getResources().getDrawable(R.drawable.ic_action_rain));
        }



        return rowView;
}

You can see in the getView() thats where all the work happens, everytime a item on a listview is displayed, getview() needs to inflate that view. So you can see that each view in that XML is being grabbed and I am attaching my Strings to their respected items.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank Daedalus, I am going to try to implement this following your example soon. I'll let you know how it goes.
Daedalus, with your help and following this tutorial: ezzylearning.com/tutorial/… I was able to make magic happen, thanks!
0

instead

 adapter=new ArrayAdapter<String>(this, R.layout.mylist, R.id.Itemname, allRepData);

Use Custom ArrayAdapter of your LocalRepData Type and implement getView() method and other methods as needed for custom adapters. That will work.

1 Comment

Thanks, but I still have an issue implementing this with my other class, which is mostly used for data retrieval. I edited my question above. I don't see how they tie together yet.
0

Looks like you are using a custom adapter, you inflate the item in the adapters getview. Where you would attach the data to the 2nd xml your showing. So you got a list of LocalRepData and each localrepdata has a string and image. Tie them in the getView method of the adapter. Your oncreate doesnt show you building up your repData. Got to make sure its noy empty.

1 Comment

repData is populated with another call I'm not showing above. It comes back with a list of 5 string items. Currently I don't have a custom adapter in LocalRepData. Since I'm doing a bunch of API calls in there it seems I may need to move that logic into another supporting class and extend LocalRepData and use getView there. Dose that seem right?
0

If you are going to use multiple widgets in your listview's listitems such as EditText and ImageView, then you have to extend using ArrayAdapter and populate them in the getView() method.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.