ListView not scroll smoothly - android

I have a list view in which i have inflating 3 different type of view, and one type of that view contain horizontal scroll view.
Inside horizontal scroll view i have linear layout,in which i am inflating my custom xml.
All of this working, but scroll of parent list view is not smooth.
When i comment my horizontal scroll view code then list is scrolling smoothly.
Below is my code :
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
view = convertView;
int type = getItemViewType(position);
if(view == null){
mHolder = new ViewHolder();
if (type == 0) {
mHolder.mainLinearType1 = (LinearLayout) view.findViewById(R.id.main_linear);
mHolder.hsv1 = (HorizontalScrollView) view.findViewById(R.id.hsv);
}
if (type == 1) {
....
}
if (type == 2) {
....
}
view.setTag(mHolder);
}
else{
mHolder = (ViewHolder) view.getTag();
}
if(type==0){
mHolder.mainLinearType1.removeAllViews();
for (int i = 0; i <mList.get(position).getEventList().size(); i++) {
View additionView = mLayoutInflater.inflate(R.layout.activity_type1_subitem_view, null,false);
FrameLayout innerLinnerLayout=(FrameLayout)additionView.findViewById(R.id.frame_view);
ImageView activityImage = (ImageView) additionView.findViewById(R.id.activity_iv);
ProgressBar pb = (ProgressBar) additionView.findViewById(R.id.progress);
AQueryImageDownloader.loadImage(activityImage, pb, mList.get(position).getEventList().get(i).getEventImagePath(), mContext);
mHolder.mainLinearType1.addView(innerLinnerLayout);
}
}
I have try a lot but not able to make scrolling properly.
I have also try view pager and horizontal listView. But same issue is occur.
Please help in solve this issue.
Thanks in advance.
EDITED
Below is my listview inside xml :
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/container_ll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/White">
<include
android:id="#+id/header_view"
layout="#layout/header_layout" />
<ListView
android:id="#+id/list_view"
android:layout_below="#+id/header_view"
android:scrollbars="none"
android:visibility="gone"
android:divider="#color/LtGreen"
android:dividerHeight="1dp"
android:smoothScrollbar="true"
android:scrollingCache="false"
android:animationCache="false"
android:cacheColorHint="#android:color/transparent"
android:listSelector="#android:color/transparent"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>

Check this :
http://developer.android.com/training/improving-layouts/smooth-scrolling.html
This basically tells you to use an ASyncTask to handle the scrolling.

According to your implementation, you are always inflating the horizontal scrollview for each item, regardless of whether it is a recycled one, so every time Android needs to display an item, it needs to reinflating the horizontal scrollview again, which may explain why the scrolling is not smooth.
You can try to make a ListView as part of your item view. This ListView will be inflated once when your convertView == null, and everytime getView(position, ...) of the parent ListView is called you refresh the item's ListView Adapter with values of mList.get(position).getEventList(). Since we only swap data of a recycled view, my guess is that it will not affect scrolling much.
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
view = convertView;
int type = getItemViewType(position);
if (view == null) {
mHolder = new ViewHolder();
if (type == 0) {
mHolder.mainLinearType1 = (LinearLayout) view.findViewById(R.id.main_linear);
mHolder.hsv1 = (HorizontalScrollView) view.findViewById(R.id.hsv);
mHolder.listView = (ListView) view.findViewById(R.id.frame_view); // assume this is your ListView
}
if (type == 1) {
....
}
if (type == 2) {
....
}
view.setTag(mHolder);
} else {
mHolder = (ViewHolder) view.getTag();
}
if (type==0) {
mHolder.mainLinearType1.removeAllViews();
mHolder.listView.setAdapter(new Adapter() {
// override adapter with implementation that returns items from mList.get(position).getEventList()
});
}
}

Related

Hide items in a listview

I have tried to hide items in a custom list adapter. I can hide the visibility of the text but I cannot hide the whole list item. It still shows the dividers etc. I have tried:
tv.setVisibility(View.INVISIBLE);
tv.setVisibility(View.GONE);
convertView.setVisibility(View.INVISIBLE);
convertView.setVisibility(View.GONE);
When I use the convertView i get a null pointer exception.
You can set ContentView with No Element.
In getView() of Your Custom Adapter.
if(condition)
{
convertView=layoutInflater.inflate(R.layout.row_null,null);
return convertView;
}
else
{
convertView=layoutInflater.inflate(R.layout.row_content,null);
return convertView;
}
your XML row_null.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">
</LinearLayout>
You have 3 ways to do this:
Remove the items from your list inside or outside the adapter.
Inside the adapter you can do it in the Constructor.
private List<String> list;
public MyAdapter(Context context, List<String> list) {
list.remove(0);
list.remove(1);
list.remove(<whateverPositionYouLike>);
this.list = list;
}
You need to figure out how many items you want to hide and need to build a similar logic.
#Override
public int getCount() {
// In this adapter, we are supposed to hide the first item of the list view
// Returning 0 if no of items are already 0
if(list.size() <=1)
return 0;
// if number of items are more than one, returning one item less
return list.size() - 1;
}
#Override
public Object getItem(int position) {
// skipping the position
return list.get(position + 1);
}
`
#Override
public View getView(final int position, View v, ViewGroup arg2) {
// this is important, as we are supposed to skip the first item of listview
final int localPosition = position +1;
ViewHolderItem holder;
if (v == null) {
holder = new ViewHolderItem();
v = inflater.inflate(R.layout.list_row, null);
v.setTag(holder);
} else {
holder = (ViewHolderItem) v.getTag();
}
return v;
}
`
Answer provided by #hims_3009
You cannot in the way you are trying to, you'll need to use a custom Adapter and implement in there the logic for showing/not showing a line.
If you want to hide a row in a listview, you need to delete data in that position. For example if you use array adapter and want to hide the row on 5. position. You have to delete line from your array and the call notifyDatasetChanged() method.
(You can delete data from array by using tempArray)
or use this way
private List<String> items = new ArrayList<String>();
// make list a new array, clearing out all old values in it.
for(i=0; i<10; i++)
{
if((i != 5) && (i != 6)){
// if k = 5 or 6, dont add those items to the list
items.add(something[i]); /// whatever your list items are.
}
}
ArrayAdapter<String> itemList = new
ArrayAdapter<String>(this,R.layout.itemlistlayout);
setListAdapter(itemlist);
If you want to hide an entire item you need to build some logic into your getView() method to make it skip over various parts of your data.
lets say you have an ArrayAdapter and I want to hide the data that is at index 2. Your getView() method could look something like this.
#Override
public View getView(int pos, View convertView, ViewGroup, parent){
View mView = convertView;
//TODO: Check if convertView was null, and inflate
// or instantiate if needed.
//Now we are going to set the data
mTxt = mView.findViewById(R.id.mTxt);
if(pos >= 2){
//If position is 2 or above, we ignore it and take the next item.
mTxt.setText(this.getItem(pos + 1).toString());
}else{
//If position is below 2 then we take the current item.
mTxt.setText(this.getItem(pos).toString());
}
return mView;
}
Note that this example is generalized, it is not meant to be able to be dropped directly into your project. I had to make assumptions about some things which I don't know the truth on. You can use the same concept as I've shown here though and modify it to your situation to be able to "hide" rows in your ListView.
If you already have a custom list adapter you can just call notifyDataSetChanged() on the adapter and the adapter itself has of course to implement the logic to filter out the views for the rows you want to hide. These are the methods that come to my mind that need to reflect that logic:
#Override
public Object getItem(int position) {
return mItems.get(position);
}
#Override
public int getCount() {
return mItems.size();
}
#Override
public View getView(final int position, final View convertView, final ViewGroup parent) {
// here goes your logic to hide a row
Additionally you might have to change getItemId() as well.
I think I have a much easier / safer solution: you just have to "embed" your item in a Layout, and change the visibility of this parent layout.
<?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"
android:orientation="horizontal" >
<!-- Embed ListView Item into a "parent" Layout -->
<LinearLayout
android:id="#+id/parentLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<!-- This is the normal content of your ListView Item -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="World" />
</LinearLayout>
</LinearLayout>
Then in your code just do:
public View getView(int position, View view, ViewGroup parent) {
if (view == null) {
LayoutInflater li = mActivity.getLayoutInflater();
view = li.inflate(R.layout.my_listview_item, null);
}
LinearLayout parentLayout = (LinearLayout) view.findViewById(R.id.parentLayout);
if (shouldDisplayItem(position)) {
parentLayout.setVisibility(View.VISIBLE);
} else {
parentLayout.setVisibility(View.GONE);
}
return view;
}
This way you always use/reuse the same item, and just hide/show it.

Display One more Image on top of that clicked grid item

I have grid view with 4 items,now onlclick of each grid item i need to display one more image on top of that clicked grid item.
How to acheive this?
This is my adapter class get View:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder view;
LayoutInflater inflator = activity.getLayoutInflater();
GridView.LayoutParams params = null;
if (convertView == null) {
view = new ViewHolder();
convertView = inflator.inflate(R.layout.tile_row, null);
view.textView = (TextView) convertView.findViewById(R.id.title);
view.imageView = (ImageView) convertView.findViewById(R.id.icons);
convertView.setTag(view);
params = new GridView.LayoutParams(Width, Height);
convertView.setLayoutParams(params);
} else {
view = (ViewHolder) convertView.getTag();
}
// set image view parameters
setImageParamaeters(view.imageView);
view.textView.setText(adapterNames.get(position));
view.imageView.setImageResource(adapterIcondIds.get(position));
if (params != null) {
convertView.setLayoutParams(params);
}
convertView.setId(position);
convertView.setOnClickListener(onClickListeners.get(position));
return convertView;
}
You can do this by positioning a popup window on top of the grid item.
In order to find the exact on screen position of the grid Item you can use the following code
Rect loc = new Rect();
int[] location = new int[2];
view.getLocationOnScreen(location);
loc.left = location[0];
loc.top = location[1];
loc.right = loc.left + view.getWidth();
loc.bottom = loc.top + view.getHeight();
The variable loc holds the exact on screen location of the view that was clicked, this is nothing but the 2nd paramter of the method
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// TODO Auto-generated method stub
}
With this information you can easily achieve what you need. Best is to calculate the center of the view and align the center of the popup to the center of the clicked view.
Note:You will need adjustments for showing the pop up in case part of the view is visible.
Edited:
Since i did not get your question, i am adding an image to bring more clarity.
I have already provided the code for case 1. For case 2 you will need a modified layout where you can show the overlay images on click of the grid item
Edited: Implementing case 2
Modified adapter code, moved around some variables for optimization
public CustomAdapter(Activity activity, ...){
inflator = activity.getLayoutInflater();
...
}
LayoutInflater inflator;
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder view;
if (convertView == null) {
view = new ViewHolder();
convertView = inflator.inflate(R.layout.tile_row, null);
view.textView = (TextView) convertView.findViewById(R.id.title);
view.imageView = (ImageView) convertView.findViewById(R.id.icons);
view.clickedImage = (ImageView) convertView.findViewById(R.id.clickedImage);
convertView.setTag(view);
} else {
view = (ViewHolder) convertView.getTag();
}
// set image view parameters
view.textView.setText(adapterNames.get(position));
view.imageView.setImageResource(adapterIcondIds.get(position));
//add a int variable to the view holder
view.position = position;
if(position != clickedPosition){
view.clickedImage.setVisibility(View.GONE);
}
convertView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
ViewHolder holder = (ViewHolder)v.getTag();
clickedPosition = holder.position;
holder.clickedImage.setVisibility(View.VISIBLE);
//you can also set the resource of the imageview here.
notifyDataSetChanged();
}
});
return convertView;
}
//this is used for resetting the previous view when a new view is clicked
int clickedPosition = -1;
To preserve the clicked state of an item in the grid view, i store the
clicked item position of the grid. Now in onClick i change visibility
of the clicked image(which was in GONE state), update the variable
clickedPosition and simply call notifyDataSetChanged. This tells that
the adapter that the dataset has changed and getView for all the
visible grid items will be called. So, if you click item 1 initially,
and then click item 3 then you will notice that item 1 has been reset
when item 3 was clicked.
XML title_row.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="200dp"
android:layout_height="200dp" >
<ImageView
android:id="#+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:src="#drawable/droid_logo_black"
android:visibility="gone" />
<ImageView
android:id="#+id/clickedImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:src="#drawable/login_help_logo" />
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text="Title"
android:textAppearance="?android:attr/textAppearanceLarge" />
</RelativeLayout>
In the onClickListener of the element, call the imageView and load the image dynamically.
Or predefine the image resource, and call the Imageview with the id of the new image.
onlclick of each grid item i need to display one more image on top of that clicked grid item.
I think you have to create custom Gird View. and append ImageView Dynamically as per the needs.
setVisibilty(View.Visible) when you want to show and setVisibilty(View.Hide) when you don't want to show.
int id = getResources().getIdentifier("yourpackagename:drawable/" + StringGenerated, null, null);
Try something of this sort and you'll get the id. Try changing the image using
imageview.setImageResource(id);
Good Luck!

Cannot change the visiblity of an ImageView

I have a ListView using a custom cursoradapter to fill the ListView.
The row.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="match_parent"
android:orientation="horizontal" >
<LinearLayout
android:orientation="vertical"
android:layout_width="0dip"
android:layout_weight="1"
android:layout_height="fill_parent">
<TextView
android:id="#+id/title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:gravity="center_vertical"
android:ellipsize="marquee"
android:textSize="24dp" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/artist"
android:singleLine="true"
android:ellipsize="marquee"
android:textSize="14dp" />
</LinearLayout>
<ImageView
android:id="#+id/currentplaying"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_marginLeft="1dip"
android:src="#android:drawable/ic_media_play"
android:contentDescription="#string/now_playing"
android:visibility="gone" />
</LinearLayout>
As you can see, the ImageView's visibility is gone. I want to make it
visible for one particular row. Here is the code I tried but it is not
working...
View view = getListView().getAdapter().getView(0, null, null);
ImageView iv = (ImageView)view.findViewById(R.id.currentplaying);
iv.setVisibility(ImageView.VISIBLE);
Thanks in advance.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView==null) {
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.yourlayout, null);
holder.imgViewLogo = (ImageView) convertView.findViewById(R.id.imgViewLogo);
convertView.setTag(holder);
}
else {
holder=(ViewHolder)convertView.getTag();
}
if(position==0) {
holder.imgViewLogo.setVisiblity(View.VISIBLE);
}
return convertView;
}
EDIT:
I got it working. I used this to start the ListView activity.
intent.putExtra("id", c.getInt(c.getColumnIndex(DatabaseHelper._ID)));
startActivity(intent);
In the ListView activity,
currentplayingid = getIntent().getExtras().getInt("id");
Then I added this in bindview()
ImageView imgview = (ImageView)view.findViewById(R.id.currentplaying);
int id = c.getInt(c.getColumnIndex(DatabaseHelper._ID));
if (id == SongsListActivity.this.currentplayingid)
imgview.setVisibility(View.VISIBLE);
else
imgview.setVisibility(View.GONE);
I got it working. I used this to start the list view activity.
intent.putExtra("id", c.getInt(c.getColumnIndex(DatabaseHelper._ID)));
startActivity(intent);
In the listview activity,
currentplayingid = getIntent().getExtras().getInt("id");
Then i added this in bindview()
ImageView imgview = (ImageView)view.findViewById(R.id.currentplaying);
int id = c.getInt(c.getColumnIndex(DatabaseHelper._ID));
if ( id == SongsListActivity.this.currentplayingid )
imgview.setVisibility(View.VISIBLE);
else
imgview.setVisibility(View.GONE);
perhaps you should do it in getView() of your adapter
EDIT:
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
// codes...
if (position == 0)
{
holder.imgViewLogo.setVisibility(ImageView.VISIBLE);
}
else
{
holder.imgViewLogo.setVisibility(ImageView.GONE);
}
// codes...
}
You have to do it like this
iv.setVisibility(View.VISIBLE);
If it is working some time then may be i can help you. What happen that whenever you move you listview it recreates all views again in this case it never save the last state of view. So what you need to do is to save state of your each imageview and in getView() you have to set accordingly.I am posting one of my answer it may help you.
Here is a little code for your help: I will create a boolean arraylist.
private ArrayList imageview_visible = null;
Then I will set states of all imageview as false in my constructor:
for (int i=0; i < no_of_elements.size(); i++) {
imageview_visible.add(i, false);
}
In your getView write this code:
public View getView (int position, View convertView, ViewGroup parent)
{
//WRITE YOUR CODE
if (imageview_visible.get(position) == true)
{
//SET YOUR IMAGE VIEW AS VISIBLE
} else {
// SET IMAGEVIEW AS GONE
}
}
Whenever you unhide or hide your view just save it into imageview_visible.set(true or false) this will save state of you all imageview and set every image view accordingly
Use LayoutInflater to get view object
LayoutInflater inflater = this.getLayoutInflater();
View rowView = inflater.inflate(R.layout.row, null, true);
ImageView iv = (ImageView)view.findViewById(R.id.currentplaying);
iv.setVisibility(ImageView.VISIBLE);
Try the following code as follows,
private class ViewHolder
{
ImageView imgViewLogo;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolder holder;
if(convertView==null)
{
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.yourlayout, null);
holder.imgViewLogo = (ImageView) convertView.findViewById(R.id.imgViewLogo);
convertView.setTag(holder);
}
else
{
holder=(ViewHolder)convertView.getTag();
}
if(position==0)
{
holder.imgViewLogo.setVisiblity(View.VISIBLE);
}
return convertView;
}
It Works for me...It may help you.
I ran into similar problems where several widgets would appear for some rows but not for others. The problems were due to view recycling. I'm not exactly sure if that's your issue here, but you should handle it anyway. The trick is to set visibility for every row; instead of just for the row that you want to appear/disappear.
So:
if (position == 0)
{
iv.setVisibility(ImageView.VISIBLE);
}
else
{
iv.setVisibility(ImageView.GONE);
}
Otherwise, you're assuming that for positions other than 0 the visibility is GONE but that might not be the case with view recycling. I do this work in bindView, by the way. Not sure if that's technically correct.
I have the same issue... i solved with a non standar solution, but worked for me...
v.setImageResource(R.color.transparent);
importing R from android
import android.R;
Both iv.setVisibility(View.VISIBLE); and iv.setVisibility(ImageView.VISIBLE); are correcte but It's better to use View instead of ImageView because VISIBLE & GONE are defined in View class.
You most change Both Visibility (VISIBLE or GONE) in that if. like:
if(?)
iv.setVisibility(View.VISIBLE);
else iv.setVisibility(View.GONE);
You can hide or show views using setVisibility(int) .
use iv.setVisibility(View.VISIBLE);

OnItemClickListener Not Triggered on Android GridView

I have a Gridview filled by an Adapter which returns LinearLayouts each contains an ImageButton and TextView.
In the adapter I am binding an onClick and onLongClick event to the ImageButton.
I am trying to bind OnItemClickListener to the gridview but I don't know why that the onItemclicked never fired up.
It's my 6th hour without anything.
By the way;
OnItemSelectListener working perfectly on the Grid.
I am checking if some piece of code accidentally handles the onItemClicked but couldn't catch yet.
I need help guys.
gridView = (GridView) layoutInflater.inflate(R.layout.gridview, null);
gridView.setOnItemClickListener(new ItemClickListener());
.
.
.
//inner handler class
class ItemClickListener implements AdapterView.OnItemClickListener {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Toast.makeText(mainActivity.getApplicationContext(),view + " clicked at pos " +
i,Toast.LENGTH_SHORT).show();
}
}
Do not use clickable objects in the grid. In that case Android cannot handle the click event of GridView.
Instead, use something to show a similar user interface view. Then handle that object's click actions.
Don't: put Button in the GridView to perform some click actions.
Do: put an ImageView instead of ImageButton and handle ImageView's click events.
If you wants to use Button or ImageButton then you need to write these attributes in your xml code of the widgets.
android:focusable="false"
android:focusableInTouchMode="false"
Its works for me.
But in GridView, Try to avoid use of these widgets. You can use any other widgets in place of these (Like ImageView or any other).
Also make sure, that your ListAdpter returns true for
public boolean isEnabled(int _position)
for the position you want to click.
Hey guyz finally got a solution...
what we were doing is directly accessing the Layout inside the GridView, so the onItemClickListener finds it confusing to access the item.
So the solution is to apply the onClickListener inside the Adapter (i.e. normally ArrayAdapter)
so what i m trying to say is:
public View getView(int position, View convertView, ViewGroup parent) {
//Here row is a view and we can set OnClickListener on this
final View row;
ViewHolder holder = null;
if (convertView == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
//Here we inflate the layout to view (linear in my case)
row = inflater.inflate(layoutResourceId, parent, false);
holder = new ViewHolder();
holder.imageTitle = (TextView) row.findViewById(R.id.text);
holder.image = (ImageView) row.findViewById(R.id.image);
row.setTag(holder);
} else {
row = convertView;
holder = (ViewHolder) row.getTag();
}
ImageItem item = data.get(position);
holder.imageTitle.setText(item.getTitle());
holder.image.setImageBitmap(item.getImage());
//Now get the id or whatever needed
row.setId(position);
// Now set the onClickListener
row.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(context, "Clicked" + row.getId() + "!!",
Toast.LENGTH_SHORT).show();
}
});
return row;
}
Try to set
android:clickable="false"
android:focusable="false"
I meet same problem too, because of several reasons.
So, here's my tips:
Extend BaseAdapter for your adapter;
Use OnClickListener inside the getView in adapter instead setting OnItemClickListener for GridView;
Avoid setting LayoutParams multiple times;
Check if position = 0, don't use convertView, inflate new View;
Set OnClickListener not only for parent View, but for any child View, if any;
Make all your Views clickable.
I just tested it on 4 devices, and this solution works as expected. Hope, it will help in your case.
Correct me, if I made something wrong.
Layout code XML:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#273238"
android:clickable="true"
android:focusable="true"
android:focusableInTouchMode="true"
android:padding="1dp">
<ImageView
android:id="#+id/open_image_item_imageview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/loh"
android:clickable="true"
android:focusable="false"
android:focusableInTouchMode="false"
android:scaleType="centerCrop"/>
<TextView
android:id="#+id/open_image_item_textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="false"
android:focusableInTouchMode="false"
android:layout_gravity="bottom"
android:padding="4dp"
android:textSize="10sp"
android:ellipsize="start"
android:background="#55000000"
android:textColor="#FFFFFF"
android:text="image name"/>
</FrameLayout>
Adapter code Java:
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View view = null;
if(convertView != null && position != 0)
view = convertView;
else{
view = LayoutInflater.from(getContext()).inflate(R.layout.open_image_item_layout, null, false);
view.setLayoutParams(new GridView.LayoutParams(GridView.AUTO_FIT, size));
}
TextView textView = (TextView)view.findViewById(R.id.open_image_item_textview);
ImageView imageView = (ImageView)view.findViewById(R.id.open_image_item_imageview);
...
View.OnClickListener onClickListener = getOnClickListener(files[position]);
view.setOnClickListener(onClickListener);
textView.setOnClickListener(onClickListener);
imageView.setOnClickListener(onClickListener);
return view;
}

Android: How to hide a ListView Item

How can you hide an item in a ListView or at least set its height to zero?
I have tried setting the visibility of the View to GONE but it still maintains the item's space (height).
Ressurecting an old question, but I just had this issue where I wanted to hide list items temporarily based upon criteria outside of the list data. What I ended up doing was creating a "null item" layout in xml and returned that based upon my criteria instead of the convert view in getView()...
instead of returning the convertView, I returned my null_item...
return inflater.inflate(R.layout.null_item, null);
null_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</LinearLayout>
if you want to hide the item like this:
convertView.setLayoutParams(new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,1));
convertView.setVisibility(View.GONE);
can't be AbsListView.LayoutParams(-1,0);
if convertview are reused you should add this below to set it height back:
if(convertView.getVisibility() == View.GONE) {
convertView.setLayoutParams(new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, AbsListView.LayoutParams.WRAP_CONTENT));
convertView.setVisibility(View.VISIBLE);
}
When it comes to ListView, to make it efficient, we use ViewHolder pattern. The way to use ViewHolder Pattern and R.layout.row_null of the following xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</LinearLayout>
is to use with getViewTypeCount() and getItemViewType(int position) as follow.
#Override
public int getViewTypeCount() {
return 2;
}
#Override
public int getItemViewType(int position) {
return (hideStatusCheck(position)) ? 1 : 0;
}
#Override
public View getView(int pos, View convertView, ViewGroup parent) {
View rowView = convertView;
if (hideStatusCheck(pos)) {
if (rowView == null || rowView.getTag() != null) {
LayoutInflater inflater = mActivity.getLayoutInflater();
rowView = inflater.inflate(R.layout.row_null, parent, false);
}
} else {
if (rowView == null) {
rowView = inflateNormalView(parent);
} else if (rowView.getTag() == null) {
rowView = inflateNormalView(parent);
} else {
ViewHolder holderToCheck = (ViewHolder) rowView.getTag();
Integer storedPos = (Integer) holderToCheck.getTag(POSITION);
if (storedPos == null || storedPos != pos)
rowView = inflateNormalView(parent);
}
ViewHolder holder = (ViewHolder) rowView.getTag();
holder.setTag(POSITION,pos);
/*
Populate data
*/
return rowView;
}
private View inflateNormalView(ViewGroup parent) {
View rowView;
LayoutInflater inflater = mActivity.getLayoutInflater();
rowView = inflater.inflate(R.layout.normal_item, parent, false);
ViewHolder viewHolder = new ViewHolder();
assert rowView != null;
/* Initiate normal findViewById thing*/
rowView.setTag(viewHolder);
return rowView;
}
We do the checking of the item's View type and if it meets the hide check, it will return 1, otherwise 0. The ListView knows that there will be 2 types of View from getViewTypeCount. Now, the getView will return the approriate View depending on the hideStatusCheck. To make a robust ListView, we want to use the ViewHolder pattern. We don't need to use ViewHolder when it is hidden. We simply inflate the R.layout.row_null and return it. We will use the ViewHolder for the R.layout.normal_item. Here is the tricky part assuming the hiding check is not static. The first check of rowView==null is standard. The second check of rowView.getTag()==null is to see if the View is coming back to normal
from hiding. The third check in the last else clause is to check if the ViewHolder retained in the tag is the right ViewHolder. If these conditions are met, we always inflate the view again. Yes, it is true that, the ViewHolder pattern is not used throughout but it uses to certain extends. It is better than nothing.
I did some tinkering with a drag and drop list from here. When an item is popped out of the list to be moved around the cell space it occupied has it's height set to 1px (see line 238) so it appears "gone". I couldn't find a way to handle this better as setting height to 0 fails as does visibility GONE.
That said, If you really want to get rid of a row less temporarily, it might be a good idea to change the backing of the Adapter and call notifyDataSetChanged() on it.
I have look at source code. And there is only one way to hide item without notifyDataSetChanged(). You must set visibility GONE for all inner views and remove background image and paddings for item's view.
Note: Row with such invisible element will be selectable.
P.S: This is very usefull for ExpandableListView if you want to hide group view it self.
add to your ListView object:
android:dividerHeight="0px"
android:divider="#FFFFFF"
Divider color doesn't matter
only setting dividerHeight doesn't work
This does remove the divider though...
I think I have a much easier / safer solution: you just have to "embed" your item in a Layout, and change the visibility of this parent layout.
<?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"
android:orientation="horizontal" >
<!-- Embed ListView Item into a "parent" Layout -->
<LinearLayout
android:id="#+id/parentLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<!-- This is the normal content of your ListView Item -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="World" />
</LinearLayout>
</LinearLayout>
Then in your code just do:
public View getView(int position, View view, ViewGroup parent) {
if (view == null) {
LayoutInflater li = mActivity.getLayoutInflater();
view = li.inflate(R.layout.my_listview_item, null);
}
LinearLayout parentLayout = (LinearLayout) view.findViewById(R.id.parentLayout);
if (shouldDisplayItem(position)) {
parentLayout.setVisibility(View.VISIBLE);
} else {
parentLayout.setVisibility(View.GONE);
}
return view;
}
This way you always use/reuse the same item, and just hide/show it.
To Hide whole raw from listview in android:-
RelativeLayout parentLayout = (RelativeLayout) view.findViewById(R.id.relative);
if (productPojoList.get(position).getSERSERVICETYPE().toString().equals("Group|Promotional")){
view.setLayoutParams(new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,1));
view.setVisibility(View.GONE);
} else {
if(view.getVisibility() == View.GONE) {
view.setLayoutParams(new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, AbsListView.LayoutParams.WRAP_CONTENT));
view.setVisibility(View.VISIBLE);
}
}

Categories

Resources