When i click in the first row the layout in rows 1 , 4 , 7 , 10 are visible.
When i click in second row the layout in rows 2 , 5 , 8 , 11 are visible
This is Update For getView i used the holder and (tag like id)
private class ViewHolder {
private LinearLayout[] myLay , myDesLay;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View row = convertView;
final ViewHolder holder ;
if(row == null){
row = inflater.inflate(R.layout.list_items, parent , false);
holder = new ViewHolder();
holder.myLay = new LinearLayout[values.length];
holder.myDesLay = new LinearLayout[values.length];
for(int i = 0; i < holder.myLay.length;i++){
holder.myLay[i] = (LinearLayout) row.findViewById(R.id.post_background);
holder.myDesLay[i] = (LinearLayout) row.findViewById(R.id.post_des_layout);
}
row.setTag(holder);
}else{
holder = (ViewHolder) row.getTag();
}
holder.myDesLay[position].setTag(values[position]);
holder.myLay[position].setTag(values[position]);
holder.myLay[position].setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
String myTag = String.valueOf(v.getTag());
String myTag2 = String.valueOf(holder.myDesLay[position].getTag());
Toast.makeText(context, myTag2, Toast.LENGTH_LONG).show();
if((clicked == false) && myTag2.equals(myTag) ){
holder.myDesLay[position].setVisibility(View.VISIBLE);
clicked = true;
}else{
holder.myDesLay[position].setVisibility(View.GONE);
clicked = false;
}
}
});
return row;}
Update
I See at a video from google which talking about ListView And They Said The Problem may be
in List Height And should Make it to WrapContent And i did this but it still reapeated :(
<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="match_parent"
tools:context=".MainActivity" >
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
</ListView>
The change to visibility will effect the listItem at that point every time you scroll down. So if it's the second item in the current visible list for every set of items you scroll through the second item will be affected.
I would assign a unique ID to each list item then in getView set the visibility to false for all items that do not match that ID. So have fields and set them like:
selectedID = currentID;
in onClick(), or have selectedID as an array if you need to store multiple clicked list items.
Then in getView():
if(currentID==selectedID)
holder.desLayout.setVisibility(View.VISIBLE);
else
holder.desLayout.setVisibility(View.GONE);
Add this to your original code so that the visibility is still altered in onClick()
Make unique id to every list item "Post" you can insert items to arraylist and access them using the index not the position :)
Related
I have a custom layout for a Listview, each row item contains a button that when clicked it shows a small imageview in the item, however the actions i perform in one item, repeats for another item down the list, for example, if i click the button in item 1, the imageview will show up in item 1 and item 10, if i click the button in item 2, the Imageview will show up on item 2 and item 11 and while i scroll it will keep repeating in different items, heres the code for my custom adapter:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
mparent = parent;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.places_item, parent, false);
holder = new ViewHolder();
holder.placeimage = (CircularImageView) convertView.findViewById(R.id.locationimage_pilayout);
holder.addbtn = (TextView) convertView.findViewById(R.id.addbtn_pilayout);
holder.delbtn = (TextView) convertView.findViewById(R.id.delbtn_pilayout);
holder.oribtn = (TextView) convertView.findViewById(R.id.oribtn_pilayout);
holder.placename = (TextView) convertView.findViewById(R.id.locationname_pilayout);
holder.selected = (ImageView) convertView.findViewById(R.id.selected_pilayout);
holder.origin = (ImageView) convertView.findViewById(R.id.origin_pilayout);
holder.swipeLayout = (SwipeRevealLayout) convertView.findViewById(R.id.swipe_pilayout);
holder.mainLayout = (LinearLayout) convertView.findViewById(R.id.main_pilayout);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
final Place item = getItem(position);
/*
my code assigning the button click listener and assigning the views
*/
return convertView;
}
Am i missing something? im sure this could be a simple fix, but i havent found it yet. any help would be kindly appreciated.
In ListView the individual views for rows, get reused. For example, let's say the window can show up to 10 rows inside the ListView. Now when you scroll down, the 1st view gets out of the window from the top, and a new 11th view comes into the window from the bottom. In order to save memory and CPU power, Android uses the same 1st view for the 11th view. That's the purpose of convertView and the if (convertView == null) {} else {} code.
So the reason why the image is being shown in the 1st item and also in the 11th item, is that they are exactly one view object. To tackle this issue, in the getView() method, you need to reset every attribute of every view and don't rely on the defaults.
So adding a line like the one below, will get rid of the mentioned problem:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// all your code ...
holder.placeImage.setImageResource(0); //<-- This clears any previously set image.
return convertView;
}
I am making Android app but I am stuck on constructing list view.
I want to remove each item by using delete button on each list item. What I mean that if I press a delete button in a specific row, a list item on the same row should be removed.
However, I got some bugs on here. When I press any delete buttons on the view, only last item on the view is deleted, not the item in same row. I don't know why each delete button's event action is connected to only last item's id.
Here is my Adapter code.
public View getView(int i, View convertView, ViewGroup parent){
if(convertView == null){
convertView = LayoutInflater.from(context).inflate(R.layout.item,null);
viewHolder = new ViewHolder();
viewHolder.nickname_textView = (TextView)convertView.findViewById(R.id.nickname);
viewHolder.content_textView = (TextView)convertView.findViewById(R.id.post_content);
viewHolder.date_textView = (TextView)convertView.findViewById(R.id.date);
viewHolder.company_textView = (TextView)convertView.findViewById(R.id.company);
viewHolder.location_textView = (TextView)convertView.findViewById(R.id.location);
viewHolder.profile_imageView = (ImageView)convertView.findViewById(R.id.imageView);
viewHolder.deleteButton = (Button)convertView.findViewById(R.id.deleteButton);
viewHolder.idHolder_textView = (TextView)convertView.findViewById(R.id.idView);
convertView.setTag(viewHolder);
}
else{
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.nickname_textView.setText(list_itemArrayList.get(i).getNickname());
viewHolder.content_textView.setText(list_itemArrayList.get(i).getContent());
viewHolder.date_textView.setText(list_itemArrayList.get(i).getWrite_date().toString());
viewHolder.location_textView.setText(list_itemArrayList.get(i).getLocation());
viewHolder.company_textView.setText(list_itemArrayList.get(i).getCompany());
viewHolder.profile_imageView.setImageResource(list_itemArrayList.get(i).getProfile_image());
viewHolder.idHolder_textView.setText(""+list_itemArrayList.get(i).getId());
viewHolder.idHolder_textView.setVisibility(View.INVISIBLE);
viewHolder.deleteButton.setId(list_itemArrayList.get(i).getId());
viewHolder.deleteButton.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
String sID = viewHolder.idHolder_textView.getText().toString();
long id = Long.parseLong(sID);
UserPosts deletePost = new UserPosts(context);
deletePost.open();
deletePost.deleteItem(id);
deletePost.close();
}
});
return convertView;
}
I have no idea why my deleteButton.setOnClickListener doesn't work well.
Thank you.
Here is my application screenshot
enter image description here
viewHolder.idHolder_textView.getText() will return the value of last visible items of the ListView. Try replacing these lines
String sID = viewHolder.idHolder_textView.getText().toString();
long id = Long.parseLong(sID);
With this
long id = list_itemArrayList.get(i).getId();
I use even and odd rows to set backgrond to my listview rows. In my efficientAdapter I set the row background as follows:
public View getView(int position, View convertView, ViewGroup parent) {
vi = convertView;
if (convertView == null) {
vi = inflater.inflate(R.layout.ecran_multiple_row, null);
holder = new ViewHolder();
holder.txIndex = (TextView) vi.findViewById(R.id.txIndex);
holder.txSTitle = (TextView) vi.findViewById(R.id.txSTitle);
holder.btOnOFF = (ImageView) vi.findViewById(R.id.btOnOFF);
vi.setTag(holder);
} else
holder = (ViewHolder) vi.getTag();
/*
* CHANGE ROW COLOR 0 WHITE 1 GRAY
*/
if ( position % 2 == 0) //0 even 1 odd..
vi.setBackgroundResource(R.drawable.listview_selector_odd);
else
vi.setBackgroundResource(R.drawable.listview_selector_even);
/*
* ONE ITEM IN ARRAY
*/
if (data.toArray().length==1){
holder.btOnOFF.setBackgroundResource(R.drawable.air_radio_button_rouge);
}else {
holder.btOnOFF.setBackgroundResource(R.drawable.air_deezer_check);
}
return vi;
}
and in my MainActivity.Class. I select an item using on itemclicklistener() as shown below:
**lvRMultiple.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
imgview = (ImageView) view.findViewById(R.id.btOnOFF);
//And change its background here
imgview.setBackgroundResource(R.drawable.air_radio_button_rouge);
}
});**
When i clicked on an item btnOff image change successfully but when i scroll down it change to default background. Secondly when i click on one item after the other both becomes the new image but i want only the row clicked by the user to change to new image and the previous image are set to default.
All row view of a ListView created by the getView() method of BaseAdpter class. When ever we scroll the ListView all, new viable row create by getView() using recycle. So getView() called again and again when new row is viable on scroll.
There are two solution of your question:-\
You can save the status of ListView
// Save ListView state
Parcelable state = listView.onSaveInstanceState();
// Set new items
listView.setAdapter(adapter);
// Restore previous state (including selected item index and scroll position)
listView.onRestoreInstanceState(state)
And other solution is create RowView at runtime and add it on a Parent Layout by using addView() method.
LayoutInflater inflater = LayoutInflater.from(context);
// You should use the LinerLayout instead of the listview, and parent Layout should be inside of the ScrollView
parentView = (LinerLayout)this.findViewById(R.id.parentView);
for(int i = 0; i<=numberOfRow;i++){
LinearLayout rowView = (LinerLayout)inflater.inflate(R.layout.rowView);
ImageView rowImageView = (ImageView)rowView.findViewById(R.id.rowImage);
rowImageView.setOnClickListener(new View.onClickListListener(){
#Override
public void onClick(){
rowImageView.setImageBitmap(onClickBitmapImage);
}
});
parentView.addView(rowView);
}
Please check this answer Maintain/Save/Restore scroll position when returning to a ListView
More Reference
http://developer.android.com/reference/android/widget/Adapter.html#getView(int,android.view.View, android.view.ViewGroup)
The item changes back to the default background because the view gets recycled. This is the same problems of checkboxes losing their checked state
Check out this answer too see how to handle it:
CheckBox gets unchecked on scroll in a custom listview
As for your second problem, I believe it's already answered here:
highlighting the selected item in the listview in android
Hope it helps
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.
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!