Hiding the Header view in ListView - android

I'm trying to add a header view to my list, and hide it all the time unless we scroll to it (like the pull-to-refresh mechanism). The problem is: if the list is not tall enough to fill the screen - the header view is shown on top of the list.
Is there a way to hide it, and make it visible only when we scroll to it? I've been trying a lot of stuff, but I can't figure out a good and simple way to do so.
Thanks

Here's a blog post describing a simple way of hiding and showing the header view.
The idea is to to put the content you wish to hide in a LinearLayout that wraps it, and hiding the content only. That way, the wrapping LinearLayout will collapse when its content is hidden, resulting in a headerView that is technically still present, but 0dip high.
Note: If you would try to hide the content without the enclosing layout, you would be left with unwanted space in the header view.
An example layout with a spinner representing the content:
<LinearLayout
xmlns:a="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<ProgressBar
android:id="#+id/spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
Then you can hide the spinner (content) as follows:
spinnerLayout.findViewById(R.id.spinner).setVisibility(View.GONE);

You could look into ListView.setOverscrollHeader() or ListView.setOverscrollFooter(). Is this the behavior you are looking for?
If not, could you post some code showing what you have so far?
EDIT:
Ok so I looked into Overscrolling headers/footers and you're right, I don't think that's what you want at all.
Instead you should probably look into the Pull to Refresh mechanism from the Twitter app that others have tried to emulate. You can look into the answers from this question.
The most promising answer seems to be the custom ListView written by Johan Nilson, the code for which can be found here:
https://github.com/johannilsson/android-pulltorefresh
EDIT #2:
I took a look at the PullToRefresh custom ListView and what you want to do is probably possible, though not necessarily easy. Allow me to explain.
The PullToRefreshListView is essentially just a hack that exploits the optional Header in standard ListViews. The hidden "Pull To Refresh" that you see is really just the header of the ListView. When the list is displayed, this line is executed:
setSelection(1);
This scrolls the list to the first item on the list, effectively hiding the Header. When the List is short enough to be displayed entirely on screen, no scrolling is necessary, hence the "Tap to Refresh" button.
When this "Tap to Refresh" is visible, the pull to refresh mechanism is disabled, but it's easy enough to fix that. The pull to refresh effect is accomplished by increasing the top padding of the header view so that it appears that you are pulling the list down (when really it's more accurate to say that the Header is pushing the rest of the list down).
The amount of padding added is controlled by the applyHeaderPadding() function on line 199 of the source code. In that function there is an if statement on line 220 that only applies the padding when the list is in RELEASE_TO_REFRESH mode:
if (mRefreshState == RELEASE_TO_REFRESH)
{
//Some code that eventually adds padding to the header...
}
If you eliminate this condition or change it to apply padding no matter what mode you are in you can drag to refresh even if the list is short and the header says "Tap to Refresh"
if (true)
{
//Some code that eventually adds padding to the header...
}
However, this doesn't exactly create the effect you're looking for. If the list is short, you can drag it down to refresh, but the "Tap to Refresh" header is still shown. Now the problem is "How can I hide the header until the dragging motion begins?" This is a difficult problem on it's own, with several Stack Overflow questions dedicated to it.
If you want a header, you must add it BEFORE you set the adapter for the ListView, otherwise you get all sorts of errors.
I had some success with this, but I haven't come up with anything stable, because my solution is a kind of nasty hack on top of the already hacked PullToRefreshListView. I set an empty FrameLayout as the header and added the original pull to refresh header to that Frame Layout. Then, as I dragged the list, I edited the height in the LayoutParameters of the Frame Layout to grow and shrink much like the padding had originally. It sort of worked, but would eventually force close, and I haven't figured out why yet.
Anyway, if I get it to work I'll post the code, otherwise someone wiser than I might propose a solution based on the info I just provided.

Here is a solution for the current PullToRefreshListView (updated November 4, 2011):
https://github.com/johannilsson/android-pulltorefresh
based on the Hiding Header Views article:
http://pivotallabs.com/users/joe/blog/articles/1759-android-tidbits-6-22-2011-hiding-header-views
1) Copy pull_to_refresh_header.xml from the library's res/layout to your app's res/layout.
2) Edit your app's pull_to_refresh_header.xml. Wrap topmost RelativeLayout in a LinearLayout and then wrap the LinearLayout in a RelativeLayout again. Why? Topmost layout must be RelativeLayout because that's what's expected in code, second level layout must be LinearLayout because that's the only layout that collapses with View.GONE. Third level layout must be the same as original top-level RelativeLayout (except id) to preserve look.
3) Preserve same id on top RelativeLayout (pull_to_refresh_header), give second level LinearLayout an id of your choosing, give third level RelativeLayout another id (pull_to_refresh_header2 for example).
4) Move all padding from the topmost RelativeLayout to the second RelativeLayout.
5) In your code use findViewById and your LinearLayout id to set visibility to View.GONE. The LinearLayout will collapse, and if you moved all padding values appropriately to the inner RelativeLayout the header should take no space at all.

Related

How do I make UI elements fill the entire Android Screen

I am trying to add a bar similar to the "Today" bar here, but I cannot figure out how to force the width to match the screen. I am just using a simple textview (if there is a better way.. that's awesome, please tell it to me, but i cant find anything for it)
Here is what is happening with match_parent or fill_parent I recolored the textview to show the margins (that I dont want)
match_parent should fill the entire screen.
Check your parent activity layout or your fragment layout and you should find your margins there.
BTW, if you have a list of items like the one in the picture and you want it to have sections (like 'today', 'yesterday', etc) you should probably use recyclerview with headers instead of text view. Check this library for this, it's pretty easy:
https://github.com/cymcsg/UltimateRecyclerView

What is the best way to implement Header support in GridView?

Everyone knows that GridView does not supports headers and footers like a ListView.
There is a few ways to implementing this:
Use a ListView and form columnt manually via ViewGroups. It not works for me, because it's require a lot of layout operations like measuring and layouting, and it's difficult to implement draw selector on top.
Use special adapter. It works fine with a footer: we should fill last cells with a Space and manually insert after them out footer with width that equals GridView width. But this not works with headers: although header is stretched, next cells float on it.
Use a GridLayout. GridLayout is good, but what about performance with 500-1000 cells? AdapterView supports caching and reusing Views, as far as I know, this is not possible with GridLayout.
Extend GridView and write custom class, that allows to draw a header before the grid content. It's difficult, but it's should work very fast. Let's try to figure out how to do this:
Measure the header. It's very simple, I have not questions about this.
Layout header in the top of the grid. We also should consider with scrolling position to allow move header with whole grid content, so my first question is: how to know where bottom border should be located while scrolling?
Layout whole grid content after the header. How to do that? I've newer do this before.
Dispatch draw to the header view too and resolve overscrolling effect if it's not work well.
Handle the scroll event and refresh header position.
So what you can suggest me? How to do header offset? Is it right to invoke relayouting with every scroll event?
I searched an answer on a same situation with a GridView (but for a FooterView).
I've read attentively your suggestions and some from other websites. I had the same reflexion. I found a simple way as your tip: "Use special adapter. It works fine with a footer..." and this answer by #RaulSoto helped me a lot. But when I tried to update my gridview, I had a NPE, because my footer was not like the layout of my items and I had a custom filter which recalculated the getCount() method, but without understand that another view was added.
Finally, I found only solution which works: a custom class.
Create your own class as you said: "Extend GridView and write custom class" but don't extend GridView. You should extend with ListView and measure the entire width, the column width and the number of columns. I think, it's less difficult that to extend GridView, calculate the height of the header view and move it as you move your gridview or refresh the header each time you handle a scroll event..
I searched to do it in this way and I took this little project on GitHub: HFGridView by Sergey Burish. It was exactly what I need, no more.
I only added a custom attrs file in my app and customize a bit his project to have the expected result (especially, it was to have one column in portrait, two in landscape mode, refering to the numColumns attribute in my layout).
And when I try, just for test, to add a HeaderView and refresh the content with adding new items, the header view stays at the top of my gridview list, without refreshing himself.
So, I think you should search to create your class as GridView extends ListView. Refer you to the HFGridView by SBurish, it is very simple to understand how it does.
Hope this helps you with your purpose.

Make Header View (not Section Header) of ListView Stick on Top

I have a ListView with a HeaderView.
I want one of the views in the HeaderView to stick on top.
I've seen a lot of examples for sticky Section Headers.
I also looked at StickyScrollViewItems but since I'm using a ListView, I cannot use a ScrollView.
Is there a library available for this or should I just override the OnScrollListener of the ListView?
Thanks.
I have just written a load of code that does this that I cant share for contractoral reasons. Basically follow the approach outlined here and apply to a listview rather than a scroll view.
Main points are
Create a wrapper view that contains your floating/sticky header and your listview as siblings
Use a proxy method when adding headers with an isSticky boolean - if is sticky then add a fake blank header to the listview of the same size and your intended header view to the floating header wrapper (use a relative layout here)
Set a scroll listener of the listview that tracks the top px position of the dummy header view in the list and setting this as a top margin of the floating header that sits inside a relative layout
Handle all the annoying edge cases / OEM overscroll crap to get it to work in all situtions (like this for samsung)
Remember to set the initial position of the floating/pinned header after the listview has been layed out.
I feel its a little bit involved and takes some tweaking to get right - this is a time where i envy iOS and any iOS devs will think your slacking as it takes a while to implement :D
All the Open libs out there at time of writing are using scroll views or list view headers. This issue with these approaches are that list views recycle views (so unlike scroll views you cant just keep a ref to the dummy view) and also the current libs seem duplicate the sticky views using adapter getView methods and so on - which is no good for dynamic list view header views as they are not recycled and can only have one parent, so reparenting would be annoying (and in my case has a lot of functionality so I defo dont want to create two views of the same type and shoehorn the current libs to fit my solutions)
I don't know of any library that lets you do this but what I do for a header is to use a RelativeLayout for my xml that will have the ListView. Then create your header view however you want and give it the property
android:layout_alignParentTop="true"
then give your ListView
android:layout_below="#id/idOfHeaderView
This is the easiest way I know of to dock a header view at the top. It has worked for me every time. I hope this helps.

Android - keeping a single element contained on screen

I'm experimenting to see if the layout scheme I want to use is possible. I want to have an XML layout that's scrollable. Within that scrollable layout, I want to have a single line going horizontally across the screen (I used just a View with a fixed height and different color). When that horizontal line reaches the top of the screen, and as I scroll down through the layout, I want it to stop and remain at the top of the screen while being able to scroll through everything below it.
I've been messing around in XML trying to get it to work, basically putting a bunch of junk before it and after it.
Any ideas as to how that might work? Would I have to do something fancy with the java code to fix the red line at the top when the scroll position reaches a certain point? Your help would be greatly appreciated.
I am assuming you want something like Gmail app where when you scroll a mail the header sticks on top... To do this, you need 2 views. You have your regular scroller below and overlay a fixed view on top (you can use a relative layout to do this). When your cell goes past a certain spot, you want to populate and set the visibility of the fixed view to VISIBLE. This would give the impression that the view you want to 'stick' to the top really just got stuck rather than scrolled out of view. You'll have to work out the opposite scrolling scenario too based on the location and height of the scrolled cell/view.
HTH

how to order the elements in relative layout

friend's
I have a task to place the horizontal scroll or swipe menu tabs in my application i did it where the appears top of the header,but my problem is to place the scroll menu has below the header
i have RelativeLayout where it contains two elements one after another,
TextView - for header
Gallery - for Scroll menu items
from the above code Gallery content been set from my activity,
for example the output i'm getting
looks, scroll menus(Gallery) - Header
(text view defined the above layout)
========================================
but i need it has
Header (text view defined the above layout) -
scroll menus(Gallery)
how can i get it.
thanks in advance.
If you had read at least one time the documentation (the same way for what Maragues said, please mark question as answered when they are otherwise people will not answer you anymore) you should have seen that there are xml attributes to RelativeLayouts like android:layout_below ...
Check this link
Is there something about LinearLayout that makes it unsuitable?

Categories

Resources