Where Technology meets magic

53 Posts
6 Posts
84 Posts
142 Posts
High Voltage
57 Posts
Image processing
5 Posts
4 Posts
3 Posts
27 Posts
11 Posts
7 Posts
3 Posts
21 Posts
19 Posts
9 Posts
9 Posts
91 Posts
2 Posts
23 Posts
Windows Mobile
11 Posts

Sponsored Links


Top Articles!

AVR SDCard FAT support with FatFS | 19559 Views | Rate 38.96
AVR SDCard FAT support with FatFS
Single Chip Computer | 1802 Views | Rate 29.54
Single Chip Computer
3V to 400V regulated inverter for Geiger counters | 2835 Views | Rate 18.65
3V to 400V regulated inverter for Geiger counters
Virtualmin Git return code 22 fatal: git-http-push failed | 76 Views | Rate 15.2
Virtualmin Git return code 22 fatal: git-http-push failed


News & Updates

2014-12-12, Virtualmin Git return code 22 fatal: git-http-push failed

2014-11-25, Electric Fence - 20KV pulses for perimeter defense

2014-10-29, Statie de monitorizare a radiatiei de fond in Timisoara

2014-10-29, uRADMonitor - Online Radiation monitoring station



Android GUI with Header+Scrollable Content+Footer

By Radu Motisan Posted on March 18th, 2011 , 1498 Views (Rate 1.09)

It happens quite often that we need to implement a custom interface, with a header and a footer, but in between the content is to big to fit the screen and then we need scrolling.
On Android this can be implemented in an elegant fashion, by using the RelativeLayout control. We create the Header, the Footer and then a layout for the middle content that we set to be RelativeLayout.ABOVE the footer and RelativeLayout.BELOW the Header. That's it!

Sample source code: HeaderContentFooterGUI

Note: To learn how to add a background, scroll to the bottom of this article.

The relevant part of code:

  2. //Create our top content holder
  3. RelativeLayout global_panel = new RelativeLayout (this);
  4. global_panel.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
  5. global_panel.setGravity(Gravity.FILL);
  7. // +++++++++++++ TOP COMPONENT: the header
  8. RelativeLayout ibMenu = new RelativeLayout(this);
  9. ibMenu.setId(idTopLayout);
  10. ibMenu.setBackgroundDrawable(getResources().getDrawable(R.drawable.line));
  11. int ibMenuPadding = (int) 6;
  12. ibMenu.setPadding(ibMenuPadding,ibMenuPadding,ibMenuPadding,ibMenuPadding);
  13. RelativeLayout.LayoutParams topParams = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
  14. topParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
  15. global_panel.addView(ibMenu,topParams);
  16. // textview in ibMenu : card holder
  17. TextView cTV = new TextView(this);
  18. cTV.setText("Header");
  19. cTV.setTextColor(Color.rgb(255,255,255));
  20. int nTextH = 18;
  21. cTV.setTextSize(nTextH);
  22. cTV.setTypeface(Typeface.create("arial", Typeface.BOLD));
  23. RelativeLayout.LayoutParams lpcTV = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
  24. lpcTV.addRule(RelativeLayout.CENTER_IN_PARENT);
  25. ibMenu.addView(cTV, lpcTV);
  26. // cancel button in ibMenu
  27. Button m_bCancel = new Button(this);
  28. m_bCancel.setId(idBack);
  29. m_bCancel.setOnClickListener((OnClickListener) this);
  30. m_bCancel.setText("Cancel");
  31. nTextH = 12;
  32. m_bCancel.setTextSize(nTextH);
  33. m_bCancel.setTypeface(Typeface.create("arial", Typeface.BOLD));
  34. RelativeLayout.LayoutParams lpbCancel =
  35. new RelativeLayout.LayoutParams(100,50);//LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
  36. lpbCancel.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
  37. lpbCancel.addRule(RelativeLayout.CENTER_VERTICAL);
  38. ibMenu.addView(m_bCancel, lpbCancel);
  40. // +++++++++++++ BOTTOM COMPONENT: the footer
  41. RelativeLayout ibMenuBot = new RelativeLayout(this);
  42. ibMenuBot.setId(idBotLayout);
  43. ibMenuBot.setBackgroundDrawable(getResources().getDrawable(R.drawable.line));
  44. ibMenuBot.setPadding(ibMenuPadding,ibMenuPadding,ibMenuPadding,ibMenuPadding);
  45. RelativeLayout.LayoutParams botParams = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
  46. botParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
  47. global_panel.addView(ibMenuBot,botParams);
  48. // textview in ibMenu : card holder
  49. TextView cTVBot = new TextView(this);
  50. cTVBot.setText("www.pocketmagic.net");
  51. cTVBot.setTextColor(Color.rgb(179,116,197));
  52. cTVBot.setTextSize(nTextH);
  53. cTVBot.setTypeface(Typeface.create("arial", Typeface.NORMAL));
  54. RelativeLayout.LayoutParams lpcTVBot = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
  55. lpcTVBot.addRule(RelativeLayout.CENTER_IN_PARENT);
  56. ibMenuBot.addView(cTVBot, lpcTVBot);
  58. // +++++++++++++ MIDDLE COMPONENT: all our GUI content
  59. LinearLayout midLayout = new LinearLayout (this);
  60. midLayout.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));
  61. midLayout.setOrientation(LinearLayout.VERTICAL);
  62. RelativeLayout.LayoutParams midParams = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
  63. midParams.addRule(RelativeLayout.ABOVE,ibMenuBot.getId());
  64. midParams.addRule(RelativeLayout.BELOW,ibMenu.getId());
  65. global_panel.addView(midLayout,midParams );
  66. //scroll - so our content will be scrollable between the header and the footer
  67. ScrollView vscroll = new ScrollView(this);
  68. vscroll.setFillViewport(false);
  69. midLayout.addView(vscroll);
  70. //panel in scroll: add all controls/ objects to this layout
  71. LinearLayout m_panel = new LinearLayout (this);
  72. m_panel.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));
  73. m_panel.setOrientation(LinearLayout.VERTICAL);
  74. vscroll.addView(m_panel);
  76. Button b[] = new Button[10];
  77. for (int i=0;i<10;i++) {
  78. b[i] = new Button(this);
  79. b[i].setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
  80. b[i].setText("But "+i);
  81. m_panel.addView(b[i]);
  82. }

Adding a background

You can set a background for the middle content region. The background will be fixed, eg. when scrolling the middle content, it will float over it (so you only need a background image of the size of the screen: back.png)

All you need is a single line of code:

  2. global_panel.setBackgroundDrawable(getResources().getDrawable( R.drawable.back));

Complete source:

More on PocketMagic:

Atmega8 and enc28J60 for ethernet support | 8558 Views | Rate 9.84
Atmega8 and enc28J60 for ethernet support
How to set the AVR Fusebits | 6273 Views | Rate 9.71
How to set the AVR Fusebits
Custom Rotary Knob Control for Android | 3909 Views | Rate 9.6
Custom Rotary Knob Control for Android
Programmatically Injecting Events on Android - Part 1 | 8652 Views | Rate 8.99
Programmatically Injecting Events on Android - Part 1
Variable 0..30V Regulated Power supply for 20A max | 14753 Views | Rate 8.38
Variable 0..30V Regulated Power supply for 20A max
Discussing security in online on TV News show | 2603 Views | Rate 8.34
Discussing security in online on TV News show

17 Responses to “Android GUI with Header+Scrollable Content+Footer”

  1. 1
    Android WebBrowser using WebView « PocketMagic:

    […]   « Android GUI with Header+Scrollable Content+Footer […]

  2. 2

    hi. do you have an xml version of the layout? thank you

  3. 3
    Radu Motisan:

    hi chitgoks, no – I don’t use xml anymore.

  4. 4

    Why u dont want to use xml????

  5. 5
    Radu Motisan:

    @Daler, because for complex applications you need more freedom.

  6. 6

    @Radu Motisan, freedom?? What about the speed?? will it affect to the speed of an app?

  7. 7

    I didn’t notice any speed issues.

  8. 8
    suresh devaraj:

    how to add list view instead of buttons..

  9. 9
    suresh devaraj:

    Please help me….How to add below List View instead buttons..
    ListView maListViewPerso = (ListView) findViewById();
    ArrayList<HashMap> listItem = new ArrayList<HashMap>();
    HashMap map;
    map = new HashMap();
    map.put(“titre”, “Movie Ticket”);
    map.put(“description”, “Movie Ticket Booking”);
    map.put(“img”, String.valueOf(R.drawable.reel_icon));

    map = new HashMap();
    map.put(“titre”, “Snow World”);
    map.put(“description”, “SnowWorld Tickets”);
    map.put(“img”, String.valueOf(R.drawable.reel_icon));

    map = new HashMap();
    map.put(“titre”, “Kissing Car”);
    map.put(“description”, “Kissing Car Tickets”);
    map.put(“img”, String.valueOf(R.drawable.reel_icon));

    map = new HashMap();
    map.put(“titre”, “Events”);
    map.put(“description”, “Events in Mall”);
    map.put(“img”, String.valueOf(R.drawable.reel_icon));

    map = new HashMap();
    map.put(“titre”, “Screens”);
    map.put(“description”, “Screens @ Abirami”);
    map.put(“img”, String.valueOf(R.drawable.reel_icon));

    SimpleAdapter mSchedule = new SimpleAdapter (this.getBaseContext(), listItem, R.layout.main_menu_list,
    new String[] {“img”, “titre”, “description”}, new int[] {R.id.img, R.id.titre, R.id.description});


  10. 10
    Patrick Krapf:

    I love your code and I hope you still read these messages. I prefer to do everything in code as well, which brings me to my question. I have just started using ExpandableListView and I cannot find any information on how to initialize and use it in code only. Do you know how? Let me be a bit more precise. I can use it all in code after I have used getExpandableListView() to attach itself to the xml file, but I do not want to use any xml.

  11. 11
    Radu Motisan:

    Hi Patrick,

    I would start with ExpandableListView list = new ExpandableListView ();

  12. 12
    Patrick Krapf:

    I tried that and it errors soon as setContentView() is used. (cannot find source)

  13. 13
    Radu Motisan:

    Unfortunately I am not familiar with the ExpandableListView , but feel free to post your code, maybe I can have a look at it.

  14. 14
    Patrick Krapf:

    I solved it! If you use:
    MyActivity extends ExpandableListActivity {……

    You must use ExpandableListView ev = getExpandableListView();

    which well look for your xml file to get your ExpandableListView id which must be setup like this: android:id=”@android:id/list” notice that the “@+id/….” is missing so you can not use findViewByID().

    If you using:
    MyActivity extends Activity {…..
    then you can use:
    ExpandableListView list = new ExpandableListView ();
    and everything should be fine.

  15. 15
    Patrick Krapf:

    I have used your basic layout of the header and footer with scrollable middle content to create an app, however I am noticing that when I scroll to the bottom there is, what looks like a spinning clock. A single clock arm that spins around about once a second. I remember reading about someone else having the same issue and they solved the problem, but did not think much of it because I was not having the problem. However, now I am and I cannot find the article. I cannot figure out what is causing this, can you help please?

  16. 16

    @Patrick can you include a screen shot? Or at least some hand drawn schematic? I’m not sure I understand what you are referring to.

  17. 17
    Patrick Krapf:

    Go to the app store and search for “AVON”. My app is titled “Order and Contacts” with my name beneath it. On the first screen if you scroll all the way down, the list well disappear, you well see the the spinning “clock arm”. It only appears on the first screen. My real issue is that the app well force close at times, or if you close the app and go back in, it well force close. I am trying to figure out why! Once you start the app it well begin to download the product information in the background. Nothing indicates when its done so please allow up to 15 minutes for it to complete before shuting down the app. It does this once every two weeks when a new campaign starts. On my phone I get the force close screen but the app keeps running just fine, however other people are reporting that they are getting booted out of the app completely. Please let me know what you think.

Thank you for commenting. Your comment won't show until approved, which can take some time.