wufoo
wufoo

Reputation: 14591

How do I implement a fixed & scrolled view in a layoutInflater?

I have a layout inflater and a custom arrayAdapter which create a scrolling listview. I want to keep the scrolling listview, but add a navigation bar (tablerow with image buttons or something) to the top and bottom which are independent of the scrolled list. How could I do that?

This is what I want to do:

+--------------------------------------+
|    fixed nav bar                     |
+--------------------------------------+
|            scroll listview item      |
|--------------------------------------|
|            scroll listview item      |
|--------------------------------------|
|            scroll listview item      |
|--------------------------------------|
|            scroll listview item      |
+--------------------------------------+
|    fixed nav bar                     |
+--------------------------------------+

This is how I'm instantiating the listAdapter, But I want the addHeaderView() to stay fixed when the the list scrolls:

String [] list_array = new String [mCursor.getCount ()];
View vh = getLayoutInflater ().inflate (R.layout.tabtwo_header, null);
ListView lv = getListView ();
lv.addHeaderView (vh);
setListAdapter (new dynAdap (this, android.R.layout.simple_list_item_1, list_array));

My xml layout for the listview:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_height="fill_parent"
   android:layout_width="fill_parent"
   android:orientation="vertical">

   <TextView
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_height="fill_parent"
      android:padding="10dip"
      android:layout_width="fill_parent"
      android:gravity="left|center"
      android:textSize="22sp"
      android:textStyle="bold"
      android:drawableRight="@drawable/next_icon"
      android:text="Name Name"
      android:id="@+id/tv_ListItem"
      android:background="@drawable/xml_tabtwo">
   </TextView>
</LinearLayout>

The ArrayAdapter:

public class dynAdap extends ArrayAdapter<String>
{
   String [] list;

   public dynAdap (Context context, int textViewResourceId, String [] objects)
   {
       super (context, textViewResourceId, objects);
    list = objects;
   }

   @Override
   public View getView (int position, View convertView, ViewGroup parent)
   {
    LayoutInflater inflater = getLayoutInflater ();
       View row = inflater.inflate (LAYOUT_TABTWO, parent, false);
    TextView tv1 = (TextView) row.findViewById (R.id.tv_ListItem);
    tv1.setText (list[position]);
    return row;
   }
}

Upvotes: 0

Views: 3049

Answers (2)

wufoo
wufoo

Reputation: 14591

Ok finally got this working. Maximus and OcuS, thanks for all your help. I was a big help. Also got lots of info and examples from these two websites:

Here is a working example. Hope it helps out anyone else who is trying to do the same thing.

scrolling listview with fixed header/footer

The files to do it:


  • myList.java

The main activity. Extends ListActivity and includes a custom adapter which is used to populate the list.


  • drawable/xml_listitem_shape.xml

This controls the Pressed, Selected and Normal states of the list items using gradient 'shapes' instead of images. The gradients allow for faster rendering, and are not specific to the device, so it gets you away from the multiple-image mess (hdpi, mdp, ldpi...)


  • layout/main.xml

Contains the layout for the Header, Footer and Listview objects. Does not use any selector files, but declares android:id/list as an ID for the listview object, which is required. Android will complain about not finding this ID if you do not do it.


  • layout/menu_item.xml

Contains only a TextView object for use by the dynAdap class (no layout needed). This file declares the xml_listitem_shape selector file as it's background, which defines how the listitem will appear in it's various states.


  • values/colors.xml

Color definitions used throughout the application. You can hard code your colors, but this file keeps things much cleaner.


myList.java

package com.test.listview;


import android.app.ListActivity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

public class myList extends ListActivity 
{
    public final String TAG = "** myList **";
    String[] mNames = new String[] {    
             "Linux", "Plan9", "Eclipse", "Java","Ubuntu", "Next", "Android", "Xoom", "Pascal", "Assembly",
             "C++", "Perl", "Bash", "Korn", "Int3", "CS:IP" };

    public void onCreate(Bundle icicle) 
    {
        super.onCreate(icicle);

        setContentView (R.layout.main);
        Button b1 = (Button) findViewById (R.id.button1);
        Button b2 = (Button) findViewById (R.id.button2);
        Button b3 = (Button) findViewById (R.id.button3);
        Button b4 = (Button) findViewById (R.id.button4);

        ListView listView = getListView();
        setListAdapter (new dynAdap (this, android.R.layout.simple_list_item_1, mNames));

        listView.setOnItemClickListener (oicl);

        b1.setOnClickListener (ocl);
        b2.setOnClickListener (ocl);
        b3.setOnClickListener (ocl);
        b4.setOnClickListener (ocl);

    }

    /*
     * listener for buttons
     */
    OnClickListener ocl = new OnClickListener()
    {

        @Override
        public void onClick (View v)
        {
            String b = new String ("");

            switch (v.getId ())
            {
                case R.id.button1:
                                                        b = "button1";
                break;

                case R.id.button2:
                                                        b = "button2";
                break;

                case R.id.button3:
                                                        b = "button3";
                break;

                case R.id.button4:
                                                        b = "button4";
                break;
            }

            Toast.makeText (myList.this, b, Toast.LENGTH_SHORT).show();
        }

    };


    /*
     * listener for listview clicks - pop up toast to show what was selected
     */
    OnItemClickListener oicl = new OnItemClickListener()
    {
        @Override
      public void onItemClick (AdapterView<?> parent, View view, int index,  long id)
      {
            Toast.makeText (myList.this, mNames[index], Toast.LENGTH_SHORT).show();
      }
    };


    /*
     * This is a custom list adapter to set the color and text content of each list item
     */
    public class dynAdap extends ArrayAdapter<String>
    {
        String [] list;

        public dynAdap (Context context, int textViewResourceId, String [] objects)
        {
            super (context, textViewResourceId, objects);
            list = objects;
        }

        @Override
        public View getView (int position, View convertView, ViewGroup parent)
        {
            LayoutInflater inflater = getLayoutInflater ();

            // return the view associated with the TextView in the menu_item.xml file
            View row = inflater.inflate (R.layout.menu_item, parent, false);
            TextView tv1 = (TextView) row.findViewById (R.id.tv_item); 
            tv1.setText (list[position]);
            return row;
        }
    }
}

xml_listitem_shape.xml

<?xml version="1.0" encoding="utf-8"?>
<selector
    xmlns:android="http://schemas.android.com/apk/res/android">

   <!-- pressed state of item -->
    <item android:state_pressed="true" >
        <shape>
            <gradient
                android:startColor="@color/DkRed"
                android:endColor="@color/Red"
                android:angle="270" />
            <stroke
                android:width="3dp"
                android:color="@color/LightGreen" />
            <corners
                android:radius="3dp" />
            <padding
                android:left="10dp"
                android:top="10dp"
                android:right="10dp"
                android:bottom="10dp" />
        </shape>
    </item>

   <!-- focused state of item -->
    <item android:state_selected="true" >
        <shape>
            <gradient
                android:endColor="@color/Silver"
                android:startColor="@color/Gray"
                android:angle="270" />
            <stroke
                android:width="3dp"
                android:color="@color/Red" />
            <corners
                android:radius="3dp" />
            <padding
                android:left="10dp"
                android:top="10dp"
                android:right="10dp"
                android:bottom="10dp" />
        </shape>
    </item>

   <!-- normal state of item -->
    <item>        
        <shape>
            <gradient
                android:endColor="@color/White"
                android:startColor="@color/Silver"
                android:angle="270" />
            <stroke
                android:width="3dp"
                android:color="@color/LightBlue" />
            <corners
                android:radius="3dp" />
            <padding
                android:left="10dp"
                android:top="10dp"
                android:right="10dp"
                android:bottom="10dp" />
        </shape>
    </item>
</selector>

main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:orientation="vertical">
   <RelativeLayout
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:id="@+id/top_control_bar">
      <TableRow
         android:id="@+id/tableRow1"
         android:layout_height="wrap_content"
         android:layout_width="fill_parent"
         android:background="@color/LightBlue"
         android:gravity="center"
         android:padding="5dip">
         <Button
            android:text="Button"
            android:id="@+id/button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"></Button>
         <Button
            android:text="Button"
            android:id="@+id/button2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"></Button>
         <Button
            android:text="Button"
            android:id="@+id/button3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"></Button>
      </TableRow>
   </RelativeLayout>
   <LinearLayout
      android:id="@+id/bottom_control_bar"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:layout_alignParentBottom="true"
      android:background="@color/LightBlue"
      android:padding="10dip">
      <Button
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:text="Add Item"
         android:id="@+id/button4" />
   </LinearLayout>
   <ListView
      android:id="@android:id/list"
      android:layout_width="fill_parent"
      android:layout_height="0dip"
      android:choiceMode="multipleChoice"
      android:layout_below="@id/top_control_bar"
      android:layout_above="@id/bottom_control_bar"
      android:background="@color/Silver">
   </ListView>
</RelativeLayout>

menu_item.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:textStyle="bold"
   android:paddingTop="20dip"
   android:paddingBottom="20dip"
   android:layout_gravity="center"
   android:gravity="center"
   android:textColor="#000000"
   android:background="@drawable/xml_listitem_shape"
   android:text="Fooooooo"
   android:textSize="22dip"
   android:id="@+id/tv_item" />

colors.xml

<resources>
   <color
      name="transparent">#00000000</color>

   <!-- colors used in application -->
   <color
      name="Black">#000000</color>
   <color
      name="DkRed">#660000</color>
   <color
      name="Red">#b70101</color>
   <color
      name="White">#f7f5e8</color>
   <color
      name="Silver">#c8c5bb</color>
   <color
      name="Gray">#6e6a5b</color>
   <color
      name="Yellow">#f6f900</color>
   <color
      name="Orange">#ff9000</color>
   <color
      name="LightGreen">#00ff00</color>
   <color
      name="Green">#085c00</color>
   <color
      name="Gold">#ccaf00</color>
   <color
      name="LightBlue">#0077ff</color>
   <color
      name="Blue">#000077</color>
   <color
      name="LightCyan">#00ffff</color>
   <color
      name="Cyan">#007777</color>

</resources>

Upvotes: 2

Maximus
Maximus

Reputation: 8431

If you use a LinearLayout with the top View having weight of 0, the ListView having a weight of 1 and the bottom View having a weight of 0, it would work just fine.

I always forget the Header and Footer views of a ListView, so OcuS's post is definitely a way to go, especially if you're extending ListActivitiy.

In any event, here's a VERY simple layout example. The TextViews could be replaced with lot's of other things... an additional horizontal LinearLayout for example.

Remember, this is the layout you'd set as your content view in your main activity. If your main activity is extending ListActivity you would not use this.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
<TextView android:id="@+id/toplabel"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:layout_weight="0"
    android:gravity="center_horizontal"
    android:text="Test"/>
<ListView android:id="@+id/listview"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:layout_weight="1" />
<TextView android:id="@+id/bottomtext"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
        android:layout_weight="0" />
</LinearLayout>

Upvotes: 1

Related Questions