ListView not contracting when header view set to View.GONE - android

I have a header view in a ListView I want to hide when not in use. I've included code that sets its visibility to View.GONE or View.VISIBLE depending on another control.
Unfortunately, the view I am trying to show and hide is laying out as though I were setting its visibility to View.INVISIBLE—that is, the ListView is allowing space for it even when it's hidden. How can I prevent this?
I have tried calling requestLayout() and it hasn't had any effect.
I am going to try one of the suggested solutions here:
Hide footer view in ListView?
namely, wrapping my header in a FrameLayout and letting the FrameLayout handle the layout change, not the ListView.
EDIT: I have found that basically the same bug occurs when I added a ViewPager subclass in which I had overridden onMeasure(int widthMeasureSpec, int heightMeasureSpec) as a header view: it was designed to lay itself out again when children were added, but the ListView displayed it wrongly. As a child of a LinearLayout, however, this worked fine.

I have added a FrameLayout as a parent view of the header tile I wish to hide. This means that when I hide the tile, the FrameLayout shrinks to fit it, and reports a height of zero to the ListView, which also shrinks. This is a pretty effective workaround, though a little weird.

Don't use View.VISIBLE or View.GONE for Showing and Hiding ListView Header and Footer.
Go Through removeHeaderView for help.
View v="YOUR VIEW";//Assume
You can remove Header like
your_list.removeHeaderView(v)
And you can add
your_list.addHeaderView(v);
Hope this help you.

That was my original code which was not working:
wv = new WebView(getActivity());
AbsListView.LayoutParams params = new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, AbsListView.LayoutParams.WRAP_CONTENT);
wv.setLayoutParams(params);
...
((ListView) mainListView).addHeaderView(wv);
I have placed my webview to framelayout and added this framelayout to listview with addHeaderView
FrameLayout fl = new FrameLayout(getActivity());
AbsListView.LayoutParams paramsFl = new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, AbsListView.LayoutParams.WRAP_CONTENT);
fl.setLayoutParams(paramsFl);
wv = new WebView(getActivity());
AbsListView.LayoutParams params = new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, AbsListView.LayoutParams.WRAP_CONTENT);
wv.setLayoutParams(params);
...
fl.addView(wv);
((ListView) mainListView).addHeaderView(fl);
after that when I set visibility of my webview to GONE header became not visible.

Related

Android - LayoutTransition hides views inside the animated view before closing it

I have a LinearLayout that contains several views - when I add or remove it from my view I used the default LayoutTransition.
I'm adding the view to my AppbarLayout - and I added the animations programmatically by setting a new LayoutAnimation on the appbar before adding the view and setting it to null after the view is added - I don't do it using the tag in the xml due to https://code.google.com/p/android/issues/detail?id=191170
The problem is that when i remove it from the view the default animation is done in two parts
all the views inside immediately disappear
the closing of the view is animated from bottom to top
Which change is needed to the LayoutTransition in order to have only the 2nd animation where the view is closed from bottom to top?
CommonsWare answer
Modify its LayoutParams to move it to the end position. Use
getLayoutParams() on the View, cast it to the appropriate type based
on its container, modify the LayoutParams object, then call
setLayoutParams() on the View to commit the changes.
Try this:
final LinearLayout container = (LinearLayout) findViewById(R.id.container);
LayoutTransition transition = container.getLayoutTransition();
transition.disableTransitionType(LayoutTransition.APPEARING);
transition.disableTransitionType(LayoutTransition.DISAPPEARING);

AdapterView (TwoWayView) margin of item

I'm using the TwoWayView library : https://github.com/lucasr/twoway-view to try and implement a horizontal ListView of sorts to overhaul what I had before. (HorizontalScrollView with a horizontally oriented LinearLayout that I add views to)
I want to have a margin before the first item, so there's a blank space at the left when the View is first created. But when scrolled, the blank space would be scrolled and disappear as well. When using a normal ListView it is essentially a HeaderView that I want.
When I implemented the scroll using HorizontalScrollView, I simply programmatically checked the first item and added the margin, which worked since its parent was LinearLayout and accepts margins. But I cannot do this in the getView() of the adapter used for this AdapterView since its LayoutParams do not inherit ViewGroup.MarginLayoutParams
I've also tried setting clipToPadding="false", but the views gets recycled too early, which is unacceptable since the padding I need is noticeably big.
Is there a way to achieve this behavior without moving all the HeaderView code from ListView into the TwoWayView library?
You can try something like this:
on getView(int pos, View convertView, ViewGroup parent){}
{
if (convertView == null)
{ ... }
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT , ViewGroup.LayoutParams.WRAP_CONTENT);
/// To set your margin, you just need to test the position :)
params.setMargins(left, top, right, bottom);
viewHolder.LinearLayout.setLayoutParams(params);
}
Hope this would help you.

Remove header from listView

I'm having some problems when trying to remove the header from a listView. At first I use addHeaderView() to add it, but when I change to another layout I want it to disappear but removeHeaderView() doesn't work...
I also tried setting visibility to GONE and it doesn't disappear...
What can I do?
Thanks in advance
Try the approach mentioned below..
Android ListView#addHeaderView and ListView#addFooterView methods are strange: you have to add the header and footer Views before you set the ListView's adapter so the ListView can take the headers and footers into consideration -- you get an exception otherwise. Here we add a ProgressBar (spinner) as the headerView:
// spinner is a ProgressBar
listView.addHeaderView(spinner);
We'd like to be able to show and hide that spinner at will, but removing it outright is dangerous because we'd never be able to add it again without destroying the ListView -- remember, we can't addHeaderView after we've it's adapter:
listView.removeHeaderView(spinner); //dangerous!
So let's hide it! Turns out that's hard, too. Just hiding the spinner view itself results in an empty, but still visible, header area.
Now try to hide the spinner:
spinner.setVisibility(View.GONE);
Result: header area still visible with an ugly space:
The solution is to put the progress bar in a LinearLayout that wraps it's content, and hiding the content. That way the wrapping LinearLayout will collapse when its content is hidden, resulting in a headerView that is technically still present, but 0dip high:
<LinearLayout
xmlns:a="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<!-- simplified -->
<ProgressBar
android:id="#+id/spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
Then, set the layout as the header:
spinnerLayout = getLayoutInflater().inflate(R.layout.header_view_spinner, null);
listView.addHeaderView(spinnerLayout);
And when we need to hide it, hide the layout's content, not the layout:
spinnerLayout.findViewById(R.id.spinner).setVisibility(View.GONE);
Now the header disappears from view. No more ugly space at the top!
Most people don't like to use AddHeaderView, however I sometimes found it very convenient, to avoid modifying complex adapters, or if the headers are not very related to them.
With this easy trick you will be able to seamlessly remove/add headers:
I add an empty LinearLayout with orientation vertical, and height wrap_content, as the only Header View (let mListView be the target listView):
LinearLayout mCustomHeaders=new LinearLayout(context);
mCustomHeaders.setOrientation(LinearLayout.VERTICAL);
mListView.addHeaderView(mCustomHeaders);
mListView.setAdapter (.......)
Thenafter, I can add random stuff, anywhere, to the list as header, even when the list is full:
mCustomHeaders.add(myHeaderView1);
mCustomHeaders.add(myHeaderView2);
mCustomHeaders.add(myHeaderView3);
You can also delete all headers, anytime:
mCustomHeaders.removeAllViews(); // will erase all headers
You get the idea .... Hope it helps !
The problem is that you are always creating a new object when you do:
View headerView = someView
So the new view is not the same as the view already added as listView header, try this:
View headerView = inflater.inflate(R.layout.adapter_datatable_saleitem_header, null, false);
headerView.setTag(this.getClass().getSimpleName() + "header");
if (listView.getHeaderViewsCount() > 0) {
View oldView = listView.findViewWithTag(this.getClass().getSimpleName() + "header");
if (oldView != null) {
listView.removeHeaderView(oldView);
}
}
You can check if header count > 0 then remove the header and add it again.
its works fine for me.
View _headerView;
private void function HandleHeaderView(){
if(listView.getHeaderViewsCount() > 0)
{
listView.removeHeaderView(_headerView);
}
/* Add list view header */
_headerView = GetHeaderView();
listView.addHeaderView(_headerView);
}
private View GetHeaderView()
{
View header = getLayoutInflater().inflate(R.layout.header_layout, null);
// TODO: ...
return header
}
Where drawerLogoView is my headerview, here's what I do:
drawerLogoView = mInflater.inflate(R.layout.navigation_drawer_custom_layout, null);
mDrawerList.addHeaderView(drawerLogoView,null,false);
LinearLayout layOut = ((LinearLayout)drawerLogoView.findViewById(R.id.NavProfilePreviewLayout));
layOut.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, 0));
That way, it becomes invisible :D
To show it back, you can use this:
LinearLayout layOut = ((LinearLayout)drawerLogoView.findViewById(R.id.NavProfilePreviewLayout));
layOut.setLayoutParams(newRelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT));
If you are using addHeaderView(), you can't delete your header after that.
So, don't use addHeaderView(). Rather, create your own adapter that
blends your main roster of Views with your header. While my
MergeAdapter will not handle your specific case, you can use it to see
the concept of blending multiple row sources:
https://github.com/commonsguy/cwac-merge
I encountered this problem in a slightly disguised scenario: the ListView I was dealing with came from PreferenceFragment, and the header represents a PreferenceCategory. So, my freedom of setting up the ListView was severely limited. But there were two approaches (partly inspired by other answers on this page). One was to add a custom layout to my PreferenceCategory (using a class that extends android.preference.PreferenceCategory, see Custom PreferenceCategory Headings). But I found an easier workaround: for the first Preference in this PreferenceCategory, I override onCreateView():
#Override public View onCreateView(ViewGroup parent) {
parent.setTop(-parent.getChildAt(0).getTop());
return super.onCreateView(parent);
}

Android - Aligning a view (button) within another View in code?

I have a custom view which will be jar'ed up and added into another project. In the view I want to give an option of a button.
Here is what I have in the CustomView class.
final CustomView currentView = (CustomView) findViewById(this.getId());
RelativeLayout.LayoutParams params = (new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,RelativeLayout.LayoutParams.WRAP_CONTENT ));
params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
closeButton.setLayoutParams(params);
currentView.addView(closeButton);
This is all wrapped in a RelativeLayout Tag as well as the other objects of the application
Everything compiles however in the CustomView the Button is aligning left instead of right.Any Ideas???
I would guess the problem is your CustomView. It probably doesn't take the entire width of the window, and is just wide enough to fill its children (which, in your case, is the close button). Make sure your CustomView has a fill_parent horizontal layout.
Since your CustomView extends WebView, which, in turn, extends AbsoluteLayout, you can't expect it to handle RelativeLayout's parameters. Instead, it's best you put your customview and your close button inside a RelativeLayout and position them properly.
When adding your closeButton to your currentView you need to supply the LayoutParams as an argument as well in order for them to take effect.
Basically, switch
currentView.addView(closeButton);
with
currentView.addView(closeButton, params);
Since the width of your button is set to wrap_content, you could also try setting its layout_gravity to right.
params.gravity = Gravity.RIGHT;

dynamically adding a view to activity layout

I have a custom view (an extension of a TextView) that I want to dynamically add to my Layout (don't want to include it in the main.xml file).
The book says to fetch the RelativeLayout using findViewById() in my java code then create a new instance of my custom view, then use addView on the RelativeLayout to add the new view.
I'm not getting any errors, but when I click my button to add the new view, nothing is happening (view isn't being added). Do I need to set additional properties on my custom view (layout width, layout height for example) in order for it to be shown?
EDIT: adding code
// changed to an imageview as I thought it might be easier to see an image
RelativeLayout rel = (RelativeLayout) findViewById(R.id.rellay);
MyCustomImageView mciv = new MyCustomImageView(null);
mciv.setId(5);
LayoutParams p = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
mciv.setLayoutParams(p);
mciv.setImageResource(R.drawable.someImage);
rel.Addview(mciv);
Please post your code where you add the view.
But yes, you might be missing the params for width and height. Try something like
LayoutParams p = new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.FILL_PARENT);
txtView.setLayoutParams(p);
or what you would like the width and height to be. Also in xml layout, layout_width and layout_height are required attributes.

Categories

Resources