iamlukeyb
iamlukeyb

Reputation: 6557

Separated ListView with headers

I'm trying to create a dynamic list that fills itself using a json feed.
I want to add a header for each section, in the case a league name currently the json feed feeds through one league name, but I need to make the list dynamic in case another is added.

In future this is the sort of layout i'm looking for.

league name item item item league name 2 item item item

I tried to get it to work, but I get a NullPointerException and i'm not sure why?
Hope I have been concise enough, any help would be appriciated.

Here is my code so far:

Activity

try{

   JSONObject obj = new JSONObject(FullData);


   JSONObject objData = obj.getJSONObject("data");

   JSONArray jArray = objData.getJSONArray("structure");





   //   JSONArray DivisionsArray = oneObject.getJSONArray("divisions");



//      for (int d=0; d < DivisionsArray.length(); d++){

  //        JSONObject DivDict = DivisionsArray.getJSONObject(d);   
    //      leagues.add(DivDict.getString("name"));


    //}





   //setListAdapter ( new ArrayAdapter<String>(this, R.layout.single_item, leagues));

   //ListView list = getListView();
    //list.setTextFilterEnabled(true);

// Create the ListView Adapter
    adapter = new SeparatedListAdapter(this);
    ArrayAdapter<String> listadapter = new ArrayAdapter<String>(this, R.layout.list_item, notes);
     List<String> leagues = new ArrayList<String>();
    // Add Sections
    for (int i = 0; i < jArray.length(); i++)
        {

        JSONObject oneObject = jArray.getJSONObject(i);   
        leagues.add(oneObject.getString("league_website_name"));
        Log.d("lc", "leagues: " + leagues);
            adapter.addSection(leagues, listadapter);
        }




    // Get a reference to the ListView holder
    journalListView = (ListView) this.findViewById(R.id.list_item_title);

    // Set the adapter on the ListView holder
    journalListView.setAdapter(adapter);

    // Listen for Click events
    journalListView.setOnItemClickListener(new OnItemClickListener()
        {
            public void onItemClick(AdapterView<?> parent, View view, int position, long duration)
                {
                    String item = (String) adapter.getItem(position);
                    Toast.makeText(getApplicationContext(), item, Toast.LENGTH_SHORT).show();
                }
        });



    } catch (JSONException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    }
}

Separatedlistadapter

public class SeparatedListAdapter extends BaseAdapter
    {
        public final Map<String, Adapter> sections = new LinkedHashMap<String, Adapter>();
        public final ArrayAdapter<String> headers;
        public final static int TYPE_SECTION_HEADER = 0;

        public SeparatedListAdapter(Context context)
            {
                headers = new ArrayAdapter<String>(context, R.layout.list_header);
            }

        public void addSection(String section, Adapter adapter)
            {
                this.headers.add(section);
                this.sections.put(section, adapter);
            }

        public Object getItem(int position)
            {
                for (Object section : this.sections.keySet())
                    {
                        Adapter adapter = sections.get(section);
                        int size = adapter.getCount() + 1;

                        // check if position inside this section
                        if (position == 0) return section;
                        if (position < size) return adapter.getItem(position - 1);

                        // otherwise jump into next section
                        position -= size;
                    }
                return null;
            }

        public int getCount()
            {
                // total together all sections, plus one for each section header
                int total = 0;
                for (Adapter adapter : this.sections.values())
                    total += adapter.getCount() + 1;
                return total;
            }

        @Override
        public int getViewTypeCount()
            {
                // assume that headers count as one, then total all sections
                int total = 1;
                for (Adapter adapter : this.sections.values())
                    total += adapter.getViewTypeCount();
                return total;
            }

        @Override
        public int getItemViewType(int position)
            {
                int type = 1;
                for (Object section : this.sections.keySet())
                    {
                        Adapter adapter = sections.get(section);
                        int size = adapter.getCount() + 1;

                        // check if position inside this section
                        if (position == 0) return TYPE_SECTION_HEADER;
                        if (position < size) return type + adapter.getItemViewType(position - 1);

                        // otherwise jump into next section
                        position -= size;
                        type += adapter.getViewTypeCount();
                    }
                return -1;
            }

        public boolean areAllItemsSelectable()
            {
                return false;
            }

        @Override
        public boolean isEnabled(int position)
            {
                return (getItemViewType(position) != TYPE_SECTION_HEADER);
            }

        public View getView(int position, View convertView, ViewGroup parent)
            {
                int sectionnum = 0;
                for (Object section : this.sections.keySet())
                    {
                        Adapter adapter = sections.get(section);
                        int size = adapter.getCount() + 1;

                        // check if position inside this section
                        if (position == 0) return headers.getView(sectionnum, convertView, parent);
                        if (position < size) return adapter.getView(position - 1, convertView, parent);

                        // otherwise jump into next section
                        position -= size;
                        sectionnum++;
                    }
                return null;
            }

        public long getItemId(int position)
            {
                return position;
            }

        public void addSection(List<String> leagues,
                ArrayAdapter<String> listadapter) {
            // TODO Auto-generated method stub

        }

    }

list_complex.xml

<?xml version="1.0" encoding="utf-8"?>
<!-- list_complex.xml -->
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:paddingTop="10dip"
    android:paddingBottom="10dip"
    android:paddingLeft="15dip"
    >
    <TextView
        android:id="@+id/list_complex_title"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        />
    <TextView
        android:id="@+id/list_complex_caption"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceSmall"
        />
</LinearLayout> 

list_header.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/list_header_title"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:paddingTop="2dip"
    android:paddingBottom="2dip"
    android:paddingLeft="5dip"
    style="?android:attr/listSeparatorTextViewStyle" />

list_item.xml

<?xml version="1.0" encoding="utf-8"?>
<!-- list_item.xml -->
<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/list_item_title"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:paddingTop="10dip"
    android:paddingBottom="10dip"
    android:paddingLeft="15dip"
    android:textAppearance="?android:attr/textAppearanceLarge"
    />

Upvotes: 0

Views: 2115

Answers (2)

Chintan Raghwani
Chintan Raghwani

Reputation: 3370

I think

    ExpandableListView

can be useful for you you can see demo

http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/view/ExpandableList1.html

Upvotes: 1

Changwei Yao
Changwei Yao

Reputation: 13101

Merge your header layout and your list item layout

<RelativeLayout
    <TextView
        android:id="@+id/header
        android:visible="gone"/>
    <TextView
        android:id="@+id/your_content/>
</RelativeLayout>

When you want to show the section header,

set the header view of the first item of this section.

Upvotes: 0

Related Questions