I have an Activity where there is a Linear Layout which occupies nearly half of the screen and below that I need to keep a listview which has hold any number of items. Now initially I was doing like this
<ScrollView>
<LinearLayout>
</LinearLayout>
<ListView>
</ListView>
</ScrollView>
But reading all the threads I think it is not really a good idea keeping listview inside Scrollview. Also I am facing a lot of issues like the height of the Listview is not proper.
So how do I keep the layout and listview inside the same activity without using ScrollView?
It is not recommended to include a scrolling View (ListView) inside a ScrollView. What you want to achieve can be done by adding a HeaderView which can be inflated from another XML.
LinearLayout ll = inflater.inflate(R.layout.my_layout, null);
listView.addHeaderView(ll);
i have a ListView whose children toggle visibility on clicked. Each item has two children and only one is visible at a time, the other is gone, If the item is clicked the visibilities of its children are toggled.
The quite unfortunate thing is that one child is taller than the other so the height of the listview needs to be altered at each toggle but this doesn't happen. The height stays fixed.
I have tried playing with LayoutParams but got nothing out of it.
How can I fix this?
After a lot and a lot of trial and error, I managed to get this to work simple by altering the LayoutParams of the listview after changing the visibility of the views.
view.setVisibility(View.GONE);
LinearLayout layout = (LinearLayout) view.getParent();
layout.getChildAt(0).setVisibility(View.VISIBLE);
((ListView) layout.getParent()).getLayoutParams().height =
LinearLayout.LayoutParams.MATCH_PARENT;
Note that an item in my ListView looks like this
<LineaLayout>
<LinearLayout
onclick="alterVisibility">
</LinearLayout>
<LinearLayout
onclick="alterVisibility"
visibility="gone">
</LinearLayout>
</LinearLayout>
I have a form with a number of EditView fields in it. The data for these fields are loaded from a database (in the onCreate() method). The last object on the screen should be a ListView that should show all related data records to the record being show. All the data is correctly loading, and the adapter for this seems to work ok. It loads the correct data, it formats the data correctly into the two-line layout specified by the .xml used by the adapter.
The problem is that the ListView on the screen is "shrunk" to show only one item, and adds a scrollbar if there's more items. I expected the ListView to expand in size to show all records, and the screen itself being scrollable (everything is wrapped inside a ScrollView).
So, the XML looks like this:
<ScrollView
android:layout_height="wrap_content"
android:id="#+id/ScrollView1">
<RelativeLayout
android:layout_height="wrap_content"
android:id="#+id/RelativeLayout1">
<EditView
android:id="#+id/EditView1>
</EditView>
<ListView
android:id="#+id/ListView1
android:layout_height="wrap_content"
android:layout_below="#id/EditView1>
android:divider="#b5b5b5"
android:dividerHeight="1dp" />
I then use a custom BaseAdapter to fill data into the ListView
listView = (ListView) findViewById(R.id.ListView1);
dbRecords = db.getAllRecordsByRecordId(recordId);
CBA_Records adapter = new CBA_Records(this, dbRecords);
listView.setAdapter(adapter);
This is all the same stuff that I've done before, except this is all wrapped inside the scrollview. The reason for this is that there might be more fields than will fit on a smaller screen (or horizontal screen), so the screen must be scrollable. And, the listview must also be there ...
Any suggestions?
A little more onto what invertigo said. ListView inside a ScrollView is not recommended.
Make your ListView the root, and set it's width and height to "match_parent". Put the other stuff that's above the ListView (the header) in a separate xml. Then inflate the new xml file for the header use the addHeaderView() method to add it as a header to the ListView (it looks like you want everything to scroll).
ListView is vertically scrolling automatically, so you now have two vertical scroll areas, which do you expect to consume the scroll event? Either set your ListView to a static height (not recommended), or design your layout so only the area you want to scroll (ie the ListView) has scrolling capabilities and remove the ScrollView. Also set your base layout, in this case the RelativeLayout, to height=match-parent, and ListView height=0dp weight=1 to prevent the ListView from being "shrunk".
Alternatively, take a look at this solution if you dont want the ListView scrolling independantly: android listview display all available items without scroll with static header
This is my list i want My problem is when i scroll list view then the check boxes(which are the items of this List ) are automatically checked
ex - if i checked first then 4 automatically being checked.
My first goal:
1. want to stretch my list to full i will wrap it into Scrollview how
2. i can prevent it to automatically checked
.
<ListView
android:id="#+id/ListViewProducts"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_column="0"
android:layout_span="2"
android:clickable="true"
android:isScrollContainer="true"
android:saveEnabled="true"
android:scrollbarAlwaysDrawVerticalTrack="true"
android:scrollbarSize="10sp"
android:scrollbars="vertical" >
</ListView>
Create your own BaseAdapter.
Keep in mind, that ALL views in your listview you see are temporary. They will be recycled when you'll scroll away. The reason is - you can have >9000 elements in your list. So, the way you create views must depend on some kind of (!) data.
Here is nince tutorial on how to create your own list.
Make X-th checkbox depend on X-th boolean in the list. A bit confusing first time I know, but this is the best way.
class MyAdapter extends BaseAdapter{
List<boolean> myCheckBoxes;
boolean getItem(int arg0){
return myCheckBoxes.get(arg0);
}
View getView(int arg0, View arg1, ViewGroup arg2){
...
...//See article
myView.setChecked(getItem(arg0));
...
return myView;
}
And in your activity
ListView myListView;
...
myListView.setAdapter(new MyAdapger(...));
You can't put a listview into a scrollview, two views scrolling in the same direction will not work nicely. Just put the listview in your non scrolling layout (frame- , list-, relativelayout).
Use an Adapter that sets every listview's row's views according to the data to be displayed.
ListView already extends ScrollView and doesn't need to have another one to surround it.
try looking at this post on creating custom listView items. you can implement a checkBox in them and make is have android:checked="false"
ListVew already extends ScrollView no need to implement it on ListView
for AutoCheck follow this link:
Check box checked Automatically in listview when scrolling the list.
There's no need to implement scrollview in listview becoz it is already extends to scrollview.
I think your listview is not able to handle the recycling of items properly.So to solve this problem go through the below link.
Getting an issue while checking the dynamically generated checkbox through list view
I have a ListView. The data behind it is fetched from the Internet, in sets of 10-30 items whenever the user scrolls all the way to the bottom. In order to indicate that it is loading more items, I used addFooterView() to add a simple view that displays a "Loading..." message and a spinner. Now, when I'm out of data (no more data to fetch), I want to hide that message. I tried to do:
loadingView.setVisibility(View.GONE);
Unfortunately, while that does hide the view, it leaves space for it. I.e. I end up with a big blank space where the "Loading" message used to be. How can I go about properly hiding this view?
I can't use removeFooterView() because I may need to show it again, in which case I can't call addFooterView() again because an adapter has already been set on the ListView, and you can't call addHeaderView() / addFooterView() after setting an adapter.
It seems that you are allowed to call addHeaderView() / addFooterView() after setAdapter() as long as you call one of those methods at least once before. That is a rather poor design decision from Google, so I filed an issue. Combine this with removeFooterView() and you have my solution.
+1 for the other two answers I got, they're valid (and arguably more correct) solutions. Mine, however, is the simplest, and I like simplicity, so I'll mark my own answer as accepted.
Try setting the footer's height to 0px or 1px before hiding it. Alternatively, wrap the footer view in a wrap_content height FrameLayout and hide/show the inner view, leaving the FrameLayout visible; the height should wrap properly then.
in my case addFooterView / removeFooterView() cause some artefacts.
And I found other solution. I used FrameLayout as FooterView. And when I want to add Footer I called mFrameFooter.addView(myFooter); and mFrameFooter.removeAllViews(); for remove.
FrameLayout frameLayout = new FrameLayout(this);
listView.addFooterView(frameLayout);
......
......
//For adding footerView
frameLayout.removeAllViews();
frameLayout.addView(mFooterView);
//For hide FooterView
frameLayout.removeAllViews();
The Droid-Fu library has a class designed for having a loading footer show and hide: ListAdapterWithProgress.
Works well in my project:
1.Add footer view first
mListView.addFooterView(mFooterView);
mListView.setAdapter(mAdapter);
2.Set visibility
mFooterView.setVisibility(View.GONE);
mFooterView.setPadding(0, 0, 0, 0);
3.Set invisibility
mFooterView.setVisibility(View.GONE);
mFooterView.setPadding(0, -1*mFooterView.getHeight(), 0, 0);
As #YoniSamlan pointed out, it can be achieved in a simple way. You have to specify
android:layout_height="wrap_content"
in the ViewGroup that contains the "Load More" button. Doesn't have to be FrameLayout, see below for a simple -working- example that uses a LinearLayout.
Both images show a screen that is scrolled all the way to the bottom. First one has a visible footer that wraps around the "load more" button. Second images shows that the footer collapses if you set button's visibility to GONE.
You can show again the footer (inside some callback) by changing the visibility:
loadMore.setVisibility(View.VISIBLE); // set to View.GONE to hide it again
Perform listView initialization as usual
// Find View, set empty View if needed
mListView = (ListView) root.findViewById(R.id.reservations_search_results);
mListView.setEmptyView(root.findViewById(R.id.search_reservations_list_empty));
// Instantiate footerView using a LayoutInflater and add to listView
footerView = ((LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE))
.inflate(R.layout.load_more_footer_view, null, false);
// additionally, find the "load more button" inside the footer view
loadMore = footerView.findViewById(R.id.load_more);
loadMore.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
fetchData();
}
});
// add footer view to the list
mListView.addFooterView(footerView);
// after we're done setting the footerView, we can setAdapter
adapter = new ReservationsArrayAdapter(getActivity(), R.layout.list_item_reservations_search, reservationsList);
mListView.setAdapter(adapter);
load_more_footer_view.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="#+id/load_more"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="9dp"
android:gravity="center"
android:layout_gravity="center"
android:background="#drawable/transparent_white_border"
android:textColor="#android:color/white"
android:text="#string/LOAD_MORE"/>
It should be a bug of Android.
You don't need to remove or add footer view dynamically. You just need to create an unspecified height parent Layout (either inflate it from an xml file or create it programatically) and then add your view which you want to hide or show into it.
And you can set the view, but NOT the parent Layout, to VISIBLE or GONE or something else now. It works for me.
Used
footer.removeAllViews();
This does not remove footer but flushes children.
You again have to repopulate children. Can check by
footer.getChildCount()<2
I also found that is possible call onContentChanged() (if you use ListActivity) to force recreate ListView if I need add HeaderView to them after setAdapter() call, but it is very ugly hack.
I have created a ListView that handles this. It also has an option to use the EndlessScrollListener I've created to handle endless listviews, that loads data until there's no more data to load.
You can see these classes here:
https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/helper/ListViewWithLoadingIndicatorHelper.java
- Helper to make it possible to use the features without extending from SimpleListViewWithLoadingIndicator.
https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/listener/EndlessScrollListener.java
- Listener that starts loading data when the user is about to reach the bottom of the ListView.
https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/view/SimpleListViewWithLoadingIndicator.java
- The EndlessListView. You can use this class directly or extend from it.
I have small hack way to resolve this problem for everywhere.
Put listview and footer view (just sub layout) in parent layout like LinnearLayout, remember that footerview below listview.
Controller this footer view gone and visibility like nomal view. And done!
first I am adding my footer to the listview,like this
listView.addFooterView(Utils.b);
Then on button click , I remove the view,
listView.removeFooterView(Utils.b);
I am adding the footer everytime when I am hitting the async,and theus the're no duplicate entry.I could aslo check for the count and so it like this,
if(listView.getFooterViewsCount() > 0){//if footer is added already do something}
When you want to remove the footer in ListView just call
listView.addFooterView(new View(yourContext));
It will add a dummy empty view which will not reserve any space