Multiple ListViews and the Empty View - android

i have an Fragment which contains 2 ListViews. I try to set the EmptyView for each of them.
I tried to add them via XML using #id/android:empty and via Code, both times their get ignorend.
Anyone got it working with two ListViews and diffent Empty View ?

It is working, you have to make sure that the View (for the empty state) is added to your layout, where the ListView is in.
Also, the Adapter for your ListView have to be null or isEmpty() must be true to display the empty view.
If you have still problems, post some code.

I think #Leandros is on the right track, you need to make sure that each list is set up correctly. It sounds like there might be a mismatch when you are defining #id/android:empty twice in the same xml. You may need to give them unique ids, then hook them up them in the java.
Your xml might look something like this:
...
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<ListView
android:id="#+id/list1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="#+id/empty1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="List 1 is empty"
/>
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<ListView
android:id="#+id/list2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="#+id/empty2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="List 2 is empty"
/>
</LinearLayout>
...
Then in the fragment, you'll need to grab the views and attach them.
...
ListView list1 = (ListView)findViewById(R.id.list1);
View empty1 = findViewById(R.id.empty1);
list1.setEmptyView(empty1);
ListView list2 = (ListView)findViewById(R.id.list2);
View empty2 = findViewById(R.id.empty2);
list2.setEmptyView(empty2);
...
And if you really want a more complicated empty view, you could include another layout in your xml instead of the TextView.
...
<include layout="#layout/empty"
android:id="#+id/list1"
/>
...
<include layout="#layout/empty"
android:id="#+id/list2"
/>
...
I hope this helps!

Related

Android - How to store an extra hidden information(s) (by tag) in layout

I have a layout like this-
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<!-- Linearlaout which acts as ListView in this case -->
<LinearLayout
android:id="#+id/Main_View_Reference"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
android:contentDescription="This is a container reference for main list items"
</LinearLayout>
</ScrollView>
And another layout for inflating the "LinearLayout" part of this layout like this,
<?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="match_parent"
android:background="#android:color/white"
android:id="#+id/Level_3_Layout"
android:orientation="vertical" >
<TextView
android:id="#+id/Level_3_Item_Name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/background_light"
android:text="Itame Name"
android:textColor="#android:color/black"
android:textSize="18sp" />
<TextView
android:id="#+id/Level_3_Item_Price"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/background_light"
android:text="Item Price"
android:textColor="#android:color/black"
android:textSize="13sp" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#android:color/darker_gray" />
</LinearLayout>
What I want to do is I want to assign a tag value for the dynamic inflated layouts created from second part.
So, I want to set extra hidden information for each created (inflated) layout with Java to store some extra information so that I can retrive them in next time when I need them like HTML's hidden field.
Is there any way in android?
Thanks for helping.
I'm not rally sure what did you mean by 'dynamic', but I assume you want to assign not just the value, but also the key for that 'hidden field' of yours.
If my assumptions is correct, then you could utilize this method:
yourView.setTag(int id, Object object);
I know you're reluctant to use setTag but in this use case, I think it is the most suited thing to do. Do note the int id though, using that you could assign as may tag as you want (as long they all possess different id) thus making it pretty dynamic.
Should you want to retrieve a tag you had assigned using the aforementioned method, you call this:
yourView.getTag(int id);
Hope this helps!
If this is still not what you wanted, I'm afraid the only option would be to extend your desired View and then customizing it to your needs.
For layouts use android:tag="", e.g.
....
<View
android:tag="YOUR_HIDDEN_THINGIE"
.../>
or after you have called your view
View v = findViewBy(R.id.myview);// could be any view widget
v.setTag(myobject);
also note that when you use android:tag in layout, when your layout is inflated your Tag will persist, and you can retrieve it by v.getTag()

ReUse in a ListView inside a ListView (or and adapter inside an adapter)

I have heard in stackover that it is possible to put a listview inside a listview or a listview inside a scrollview and therefore an adapter inside an adapter . The inner scrollable element will lose the scroll property.
But What about reuse?
If it is a listview inside a listview and both have their own listadapter or a derived base... do they both are able to reuse their own items? or just one of them?
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<Button
android:text="Artists"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:visibility="visible" />
<ListView
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<Button
android:text="Albums"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<ListView
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<Button
android:text="Tracks"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<ListView
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<Button
android:text="Playlists"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<ListView
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</ListView>
</FrameLayout>
I guess what you need is implemented by commonsguy's Mergeadapter: https://github.com/commonsguy/cwac-merge.
This takes Adapters and Views and displays them as one merged Listview.
MergeAdapter accepts a mix of Adapters and Views and presents them as
one contiguous whole to whatever ListView it is poured into. This is
good for cases where you have multiple data sources, or if you have a
handful of ordinary Views to mix in with lists of data, or the like.
Simply create a MergeAdapter and call addAdapter(), addView(), or
addViews() (latter accepting a List), then attach your adapter
to the ListView.
There is also MergeSpinnerAdapter for use with Spinner widgets.
This is which I've chosen for my case, that I need a horizontal RecyclerView inside my ListView.
The idea is to treat the inner view (e.g.RecyclerView) as one of your ListView items:
create your RecyclerView in ViewHolder
findViewById() & set its LinearLayoutManager in getView(), if (convertView == null)
set RecyclerView's Adapter in getView()
control your RecyclerView in its adapter.
Hope it helps you.

Android Separate Empty VIews for ListVIews

I want to make multiple empty views for a list view and set them programmatically.
So I 've got a listview in an ListActivity. The way my client wants the app, I have a header bar in the app, so the layout looks like this
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/providerListLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<include
android:id="#+id/headerBar_ref"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
layout="#layout/header_with_dashboard_button" />
<include
android:id="#+id/loadingView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
layout="#layout/loading_view" />
<RelativeLayout
android:id="#+id/listViewWrapper"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_below="#id/headerBar_ref" >
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="#id/headerBar_ref" >
</ListView>
</RelativeLayout>
So I have the 2 empty views in separate xml files. In the list Activity I try to set the empty view like so:
RelativeLayout rootLayout = (RelativeLayout) findViewById(R.id.listViewWrapper);
RelativeLayout noFavsLayout = (RelativeLayout) this
.getLayoutInflater().inflate(emptyViewLayoutId,
rootLayout);
getListView().setEmptyView(noFavsLayout);
But when I do this, the empty view is there ALL the time. I've also tried to to add the view using addContentView(), but that takes over the whole screen. I've not been able to find a solution on S/O yet
Based on reading http://wiresareobsolete.com/2010/08/adapting-to-empty-views/, the actual mechanism for showing the empty view is that the adapter checks to see if the list is empty, and then sets the visibility of either the ListView or empty view to View.GONE, then sets the other one to View.VISIBLE. For this to work properly, both views have to be in the same parent view. In your example, this would mean something like
<RelativeLayout
android:id="#+id/listViewWrapper"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_below="#id/headerBar_ref" >
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="#android:id/empty"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="This list is empty."
/>
</RelativeLayout>
(Note that I removed "layout_below" from your ListView, it was the only item in the relative layout, so it didn't need that reference. Also, the view has been added in the XML, you should not have to inflate it in the java.)
Now if you want to programmatically set a different empty view (for instance after performing a search), you could add another view to your relative layout, with another id (such as noResults)... and discover that it's always displayed.
<TextView
android:id="#+id/noResults"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="No results were returned."
/>
So in your onCreate() you'll need to find that view and set its visibility to gone as well.
ListView listView = (ListView)findViewById(android.R.id.list);
View empty = findViewById(android.R.id.empty);
listView.setEmptyView(empty);
View noResults = findViewById(R.id.no_results);
noResults.setVisibility(View.GONE);
Then whenever you change the empty view for your list, you'll want to set the visibility of the other view to GONE to make sure only one is getting displayed.
listView.setEmptyView(noResults);
empty.setVisibility(View.GONE);
I hope this helps!

Android - exceptions when trying to display a list with multiple columns

I had a list with one column which worked with an adapter, and it worked. Now I am trying to make it into two columns, and I am getting exceptions.
I am following this tutorial which seems to be the simplest: http://www.heikkitoivonen.net/blog/2009/02/15/multicolumn-listview-in-android/
I have a Java Activity that I declare like this:
public class SeeAllQuestionsActivity extends ListActivity
and here is a bit of code:
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
FlurryAgent.onStartSession(this, "8CA5LTZ5M73EG8R35SXG");
setContentView(R.layout.all_question_page);
...
Here is the all_question_page xml
<?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"
android:padding="3px"
>
<include android:id="#+id/header"
layout="#layout/header"
android:layout_height="wrap_content"
android:layout_width="fill_parent"/>
<TextView
android:id="#+id/loading_questions"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Some prompt text."
android:textSize="10sp"
/>
<ListView
android:id="#+id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="#+id/label"
android:textSize="20px" >
</ListView>
</LinearLayout>
By the way, if someone can explain to me the diffrence between two syntaxes for referencing the list id, it would be great:
android:id="#android:id/list"
android:id="#+id/list"
FYI, neither of these is working for me :)
And here is the questions_list.xml layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:paddingTop="4dip"
android:paddingBottom="6dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView android:id="#+id/TRAIN_CELL"
android:layout_width="50dip"
android:layout_height="wrap_content"/>
<TextView android:id="#+id/FROM_CELL"
android:layout_width="70dip"
android:layout_height="wrap_content" android:layout_weight="1"/>
<TextView android:id="#+id/TO_CELL"
android:layout_width="60dip"
android:layout_height="wrap_content" android:layout_weight="1"/>
</LinearLayout>
When I run this on the simulator, it crashes with a runtime exception complaining about this line: setContentView(R.layout.all_question_page); and the error is:
java.lang.RuntimeException:
Your content must have a ListView whose id attribute is 'android.R.id.list'
Please help, I am pretty stuck
Thank you!!
The difference seems to be that the former is what you'd need to use in order to use a ListActivity and the latter is what you'd use if you weren't going to use ListActivity, but instead just a normal Activity. So you'll have to stick with. (Note: I've never personally used ListActivity, so I can't exactly vouch for this)
android:id="#android:id/list"
I would also suggest removing these too lines from your ListView:
android:text="#+id/label"
android:textSize="20px"
Neither text, nor textSize are valid attributes of ListView. And for any widget that text is a valid attribute of I don't think you'd ever want to set the text equal to something like "#+id/label". If you are trying to reference a string from your strings.xml file you'd need to use "#string/label". Referencing an id like that for the text will put some hex code into the text that will have no meaning to the user(if it works at all).
It is possible that removing those might fix your trouble, if so my guess is that having the text set to another id was confusing something into thinking that your list didn't have the id list
If that does not solve your problem I would suggest switching to a plain Activity instead of ListActivity and getting the reference to your ListView via findViewById() like they do in the example that you linked.

Why does Android listview sometimes disappear after calling requery on underlying cursor?

I have a fairly simple application that uses a ListActivity to display a ListView. Each ListView item has a CheckBox so that the user can specify favorite items. I am using a class that extends SimpleCursorAdapter so that I can capture both the CheckBox changed event (to save the change to the database) and the list item clicked event (to load an item details activity).
After the OnCheckChangedListener implementation updates the database, I call .requery() on the cursor so that when an item scrolls off and then back on to the screen, the CheckBox has the proper state.
That all works fine. Where I am having problems is in another activity where I am reusing the same ListView layout and the same cursor adapter to display a specific subset of items as part of a different activity's layout. When I use the layout there, everything is fine until I tap the CheckBox, at which point the entire ListView disappears. The database is updated, but until I leave the activity and come back, the ListView is just totally gone.
If I don't call .requery() on the cursor, everything works fine; the ListView does not disappear (but the CheckBox state will be wrong some of the time, as described above).
Working layout, event_list.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:id="#+id/RelativeLayout01"
android:layout_width="fill_parent" android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView android:layout_width="wrap_content" android:text="#+id/eventsHeader"
android:id="#+id/eventsHeader" android:gravity="center_vertical"
android:layout_height="wrap_content" android:textSize="15sp" />
<ListView android:id="#+id/android:list" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_below="#+id/showHistoricalEvents" />
<CheckBox android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="#+id/showHistoricalEvents"
android:layout_alignParentRight="true" android:layout_alignParentTop="true"
android:text="Show Past Events" android:textSize="14sp" />
<TextView android:id="#+id/android:empty" android:text="#string/no_events"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_below="#+id/showHistoricalEvents" />
</RelativeLayout>
Broken layout, track_details.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content" android:orientation="vertical"
android:layout_width="fill_parent">
<TextView android:layout_width="wrap_content" android:id="#+id/InterestLabel"
android:layout_alignParentLeft="true" android:text="#string/interest_level"
android:gravity="center_vertical" android:layout_height="fill_parent"
android:layout_above="#+id/track_name" />
<Spinner android:layout_height="wrap_content" android:id="#+id/InterestSpinner"
android:entries="#array/priority" android:layout_alignParentTop="true"
android:layout_toLeftOf="#+id/FavoriteCheckbox" android:layout_width="fill_parent"
android:layout_toRightOf="#+id/InterestLabel" />
<CheckBox android:layout_width="wrap_content" style="?android:attr/starStyle"
android:id="#+id/FavoriteCheckbox" android:layout_alignParentTop="true"
android:layout_alignParentRight="true" android:gravity="center_vertical"
android:layout_height="fill_parent" android:layout_above="#+id/track_name" />
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="#+id/track_name"
android:text="#+id/track_name" android:textSize="25sp"
android:layout_below="#+id/InterestSpinner" />
<LinearLayout android:id="#+id/LinearLayout01"
android:layout_below="#+id/track_name" android:orientation="vertical"
android:layout_height="fill_parent" android:layout_width="fill_parent">
<TextView android:text="#+id/track_description" android:id="#+id/track_description"
android:scrollbars="vertical" android:layout_width="fill_parent"
android:layout_height="0dip" android:layout_weight="1"
android:paddingLeft="5dp" android:paddingTop="5dp" />
<include layout="#layout/event_list" android:id="#+id/trackEventList"
android:layout_width="fill_parent" android:layout_height="0dip"
android:layout_weight="2.5" />
</LinearLayout>
</RelativeLayout>
My only thought right now is that the way I am using layout_weight in the second layout is causing some weirdness. I am loath to change that, however, since it took me quite some time to get the layout to work the way I wanted it to in the first place.
One other note, when I am including the first layout in the second, I am hiding the TextView and CheckBox controls because they are unnecessary.
Any ideas what I am doing wrong here?
Where I am having problems is in
another activity where I am reusing
the same ListView layout and the same
cursor adapter to display a specific
subset of items as part of a different
activity's layout.
If you mean the same instance of SimpleCursorAdapter, that is so not a good idea. Please make a new adapter.
When I use the layout there,
everything is fine until I tap the
CheckBox, at which point the entire
ListView disappears. The database is
updated, but until I leave the
activity and come back, the ListView
is just totally gone.
Use hierarchyviewer to determine if the ListView has no children (rows), has no height, is invisible/gone from a visibility standpoint, or is truly removed from the view hierarchy. That will give you better ideas of how to proceed.
Any ideas what I am doing wrong here?
Besides the adapter problem mentioned above, you're using CheckBox. Android has built-in support for multiple-select lists (e.g., android:choiceMode="multiple"), but that needs a CheckedTextView. I would aim to use Android's built-in multiple-selection logic rather than rolling your own.

Categories

Resources