I need to show ListView header always, even when ListView has no items.
It is possible to do? Or better add header in ListView as first item?
If there's no elements for list and you are not adding the adapter, just add this:
mListView.setAdapter(null);
and the header will appear.
In your activity in onCreate You can add header by adding code:
View headerView = ((LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.header_view, null, false);
getListView().addHeaderView(headerView);
In most cases no need to add header, You can just add items in xml layout.
As case you can use http://viewpagerindicator.com/
and set getListView().setEmptyView(emptyView); // when your listView has no items
My solution was to manually toggle the empty view.
/**
* Custom empty view handling because we don't want the
* list to be hidden when the empty view is displayed,
* since the list must always display the header.
*/
private void toggleEmptyView(Adapter adapter)
{
final View emptyView = findViewById(R.id.empty_view);
adapter.registerDataSetObserver(new DataSetObserver() {
#Override
public void onChanged() {
emptyView.setVisibility(adapter.getCount() == 0 ? View.VISIBLE : View.GONE);
}
});
}
Irrespective of whether your ListView has elements or not, header will be visible always. If there are elements in ListView, header will scroll along with them else it will be on top always.
For how to add header view to ListView, you can refer other answers provided by users.
Related
In my app I am using recycler view.I want to show and hide view on particular condition.But when I scroll recycler views I am not getting expected behaviour.When I Visible a view it gets visible for other rows as well randomly.
What I understand is when it recycles it reuses view and when previous view when it gets recycled it finds the visibility of that view.How can I hide view on particular condition? here is my adapter code
#Override
public void onBindViewHolder(UrduRhymesViewHolder holder, int position) {
RhymesModel current = mUrduRhymesList.get(position);
AppUtility.setCustomFont(mContext, holder.tvUrduRhymesName, Constants.HANDLEE_REGULAR);
holder.tvUrduRhymesName.setText(current.getRhymeName());
holder.ivUrduRhymesLogo.setImageUrl(current.getThumbnailUrl(), mImageRequest);
int status = AppUtility.getFavouriteStatus(mContext, current.getRhymeName(), new UrduRhymesDb(mContext));
if (status == 0)
holder.btnFavourite.setBackgroundResource(R.mipmap.btn_star_unactive);
else
holder.btnFavourite.setBackgroundResource(R.mipmap.btn_star);
ProgressbarDetails progressbarDetails = ProgressbarDetails.getProgressDetail(current.getRhymeName());
if (progressbarDetails == null) {
progressbarDetails = new ProgressbarDetails();
progressbarDetails.prgProgressBar = holder.pbRhymeDownload;
progressbarDetails.download_btn_settings = holder.downloadButtonLayout;
} else {
progressbarDetails.prgProgressBar = holder.pbRhymeDownload;
progressbarDetails.download_btn_settings = holder.downloadButtonLayout;
holder.pbRhymeDownload.setProgress(progressbarDetails.progress);
}
ProgressbarDetails.addUpdateProgressDetail(current.getRhymeName(), progressbarDetails);
if (progressbarDetails != null && progressbarDetails.isDownloading) {
Log.e("test","downloading foe position "+position );
holder.downloadButtonLayout.setBackgroundResource(R.mipmap.btn_download);
holder.pbRhymeDownload.setVisibility(View.VISIBLE);
holder.pbRhymeDownload.setProgress(progressbarDetails.progress);
} else {
Log.e("test","should not be visible for position "+position);
holder.pbRhymeDownload.setVisibility(View.GONE);
}
}
Here progressbarDetails.isDownloading (having value true) is the criteria when I want to show my view but is else clause it is not hiding my view
Edit: Here ProgressbarDetails (Singleton )is a class keeping reference of every row of adapter's progress bar.
No direct way of hiding and unhiding recylerview childitems.
Solution:
Let us assume that the recyclerview adapter is ArrayList
Now make another arraylist (temp_list)
Scenarios:
Hide: iterate through your adapter items and remove the ones that you want to hide. Put each of these into temp_list. After iteration is over, call notifyDataSetChanged()
Show: iterate through your temp_list items and remove the ones that you want to show. Put each of these into adapter. After iteration is over, call notifyDataSetChanged()
You should add a flag in your viewHolder that indicates if this view should be displayed or not . and check this flag every time in the onBindViewHolder.
because the recyclerView reuses the same views you should make a decision depending on something special for every view in you viewHolder.
do u mean when your data has been changed?
and your layout want to change ?
adapter.notifyDataSetChanged();
I have different buttons in my header view for sorting the entries within the list. The problem is that when I am re-adding the header view to the listview, the header view will appear multiple times (it depends how many times I am sorting the list), which isn't the right way. The header view should appear once.
What have I tried:
// Create a new instance of a sorting view
SortingView header = new SortingView(getActivity(), new int[] {R.id.btnAsc, R.id.btnDesc, R.id.btnAll});
// If an item is pressed, then collapse the last expanded group view
header.setOnItemClickListener(new View.OnClickListener(){
#Override(View v) {
expListView.collapsGroupView(mLastExpandedView);
}
});
// The exp list-view is having a header view
// REMOVE THE HEADER VIEW
if (expListView.getHeaderViewsCount() != 0) {
expListView.removeHeaderView(header);
}
// Add the new header view
expListView.addHeader(header);
expListView.setAdapter(mEntries);
It's not working... I don't know what should I do.
Note: I don't want to hide/show the header view, because I am passing multiple listeners (event listeners), objects, etc. and I want to make a new instance of this class.
You aren't removing the previously-added header view; you are attempting to remove the newly-created instance of SortingView. Look:
SortingView header = new SortingView(getActivity(), new int[] {R.id.btnAsc, R.id.btnDesc, R.id.btnAll});
...
expListView.removeHeaderView(header);
If this instance of SortingView has not yet been added as a header, how do you expect to remove it?
You need to store references to your previously-added headers so that you can remove them.
I created an expandable listview based on this link. Its just working fine. Now what i want is
1) How to make a childview to link another sub-child view
2) The sub- child view should be open as a new list view on the window(Right side of the view) is my expected layout. I googled but couldn't find how to achieve this. Please help me in achieving this. Thanks in advance.
You'll need to specify and handle onClick event of ListView row items.
Then you'll open a new Activity, based on the item clicked.
Parameters for new activity are supplied through intent extras, the new activity can use these values to get data from cloud or process the values to show certain results.
I've used CustomAdapter class several times to handle this scenario.
class Ocl implements OnClickListener{
#Override
public void onClick(View v) {
Intent intDetail = new Intent(getActivity(), PartDetail.class);
intDetail.putExtra(_ID, mParts[position].getSPr());
intDetail.putExtra(_LOT, mParts[position].getLotID());
intDetail.putExtra(_QTY, mParts[position].getQty());
intDetail.putExtra(_UID, mParts[position].getPartID());
startActivity(intDetail);
}
}
So, do you want your first child to expand into another ListView? Or maybe just open another Activity/Fragment that contains the matching ListView?
In case you want to the the first, you could design a CustomLayout for the Childview, which on OnClick expands, and changes its content to a specific ListView.
Otherwise you would just open up another ListView with data depending on Which Child in First List was Clicked.
Well, i am using some Like that to enlarge ChildViews on Click to show me detailed information.
Im using a Class to wrap my Data named Row. These Rows indicate if they are clickable and if so, the ListView will allow clicks on the rows. A Click will then be handled by the Class itself, making the displayed Text longer(more Detailed). And in order to relayout the items, you need to call notifyDataSetChanged.
#Override
public void onClick(Context context, MyExpandableListAdapter mela) {
this.setBig(!isBig());
mela.notifyDataSetChanged();
}
So, i would handle the row state (expanded/normal) in the getView Method of parents Adapter, to decide which childLayout i inflate.
would looke something like this
public View getView (args...) {
Object data = getItem(position);
if (data.isExpanded()) {
//inflate ListView Layout, create Addapter fill it....
} else {
//show some title or whatever to identify row.
}
}
I have an exception I never thought I would see. A class cast exception of the adapter when removing a footer view from a ListView (sic).
java.lang.ClassCastException: com.test.MyAdapter
at android.widget.ListView.removeFooterView(ListView.java:381)
How can this happen? What does removing a footer have to do with class cast exception????
The list is a multi-list adapter perhaps that is why but still a class cast exception for removing a footer (sic).
Add your footer view to ListView before calling setAdapter() method.
Added:
public void addFooterView (View v)
Since: API Level 1
Add a fixed view to appear at the bottom of the list.
If addFooterView is called more than once, the views will appear in the order they were added. Views added using this call can take focus if they want.
NOTE: Call this before calling setAdapter. This is so ListView can wrap the supplied cursor with one that will also account for header and footer views.
Parameters
v The view to add.
Source
Also you can check this interesting post.
Hope this helps.
This is some code for the answer above, it worked in my case:
I had to set a footerView (it's a loadingView in a listView with pagination) to my listView before setting it's adapter and then remove it. First I initialized my loadingView from a layout file in OnCreate method:
LayoutInflater layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
loadingView = layoutInflater.inflate(R.layout.loading_view, null);
Then I used this workaround in the same method:
this.setIsLoading(true);
listView.setAdapter(adapter);
this.setIsLoading(false);
Where
private void setIsLoading(boolean isLoading)
{
this.isLoading = isLoading;
if (isLoading) {
listView.addFooterView(loadingView);
}
else {
listView.removeFooterView(loadingView);
}
}
The problem does not come from removeFooterView(), but from addFooterView().
If you read the documentation, it states that an wrapper will be added to your adapter:
If the ListView's adapter does not extend HeaderViewListAdapter, it will be wrapped with a supporting instance of WrapperListAdapter.
Thus you must use the getter for retrieving the wrapped adapter and cast it to your adapter. Like this:
((MyAdapter) ((HeaderViewListAdapter) listView.getAdapter()).getWrappedAdapter())
Hope this will help you with your issue.
Best regards,
Adding to the other answers, if you're adding/removing footers dynamically (such as if they reach the bottom of your list and then you're adding a footer view) the easiest thing is to Override setAdapter in your ListView and add a new View object as the footer there, this will ensure the adapter is wrapped in the HeaderViewListAdapter:
#Override
public void setAdapter(ListAdapter adapter) {
addFooterView(new View(getContext()));
super.setAdapter(adapter);
}
I implemented a View stack system for my Android application, which, upon pushing a new View removes the current view in the target layout, stores it in the stack and then adds the new View to the layout.
It works flawlessly until I try storing and then restoring a View containing a ListView. When doing so, the ListView receives no itemClick events, although it does scroll.
The code for the stack system is as follows:
Stack<View> viewStack;
public View pushView(View v) {
// 1. Get reference to main content panel
LinearLayout content = (LinearLayout) findViewById(R.id.contentPanel);
View last = content.getChildAt(0);
// Pushing old to stack
viewStack.push(last);
// 2. Clear it
content.removeAllViews();
// 3. Add new View
content.addView(v);
return last;
}
public View popView() {
if (!viewStack.isEmpty()) {
// 1. Get reference to main content panel
LinearLayout content = (LinearLayout) findViewById(R.id.contentPanel);
View last = content.getChildAt(0);
// 2. Clear it
content.removeAllViews();
// 3. Add last View
content.addView(viewStack.pop());
// Pushing old to stack
return last;
} else {
return null;
}
}
Curiously, the other items in the View that contains the ListView (CheckBoxes and a Button) DO receive clickEvents.
I suspect:
1. The ListView has lost focus so it won't receive those events, or
2. The ListView has been detached of the onItemClickListener
Thanks in advance!
If you have set "clickable" as "true" in you layout in xml file then remove it from every where. then you can try...
If you are declaring anywhere then only. If you are declaring "view_name.setClickable(true)" then remove this line. One more thing if you are using ontouchlistener then always return false. Actually i have faced similar problem in which I was using listview and imageview in listview row. My imageview was receiving click event but listview was not receiving onitemclick event because i had set imageview as clickable in my layout.