Android, changing background of list in array adapter? - android

In my application i have list which i inflate it with array adapter. every thing is OK and i have my result in the list.
I like to change background color of list (even rows red for example and odd rows green).
This is xml of my rows:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<RelativeLayout
android:id="#+id/rllist"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dip"
android:layout_marginBottom="15dip"
>
<TextView
android:id="#+id/outstanding_contractdate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ffffff"
android:textSize="15sp" />
<TextView
android:id="#+id/outstanding_contractno"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/outstanding_contractdate"
android:paddingLeft="20dip"
android:textColor="#ffffff"
android:textSize="15sp" />
<TextView
android:id="#+id/outstanding_contractamount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:textSize="15sp" />
</RelativeLayout>
</LinearLayout>
I have written following codes:
static class ViewHolder {
RelativeLayout rlList;
TextView tvContDate;
TextView tvContNo;
TextView tvContAmount;
}
and in Array Adapter I have this one:
public View getView(int position, View convertView, ViewGroup parent){
ViewHolder holder;
View row = convertView;
if(row == null){
LayoutInflater inflater = getLayoutInflater();
row = inflater.inflate(R.layout.list_outstanding, parent, false);
//convertView = mInflater.inflate(R.layout.list_outstanding, parent, false);
holder = new ViewHolder();
holder.rlList = (RelativeLayout) convertView.findViewById(R.id.rllist);
holder.tvContDate = (TextView) row.findViewById(R.id.outstanding_contractdate);
holder.tvContNo = (TextView) row.findViewById(R.id.outstanding_contractno);
holder.tvContAmount = (TextView) row.findViewById(R.id.outstanding_contractamount);
row.setTag(holder);
} else {
holder = (ViewHolder) row.getTag();
}
holder.tvContDate.setText(llData.get(position).split(",")[0].trim());
holder.tvContNo.setText(llData.get(position).split(",")[1].trim());
holder.tvContAmount.setText(llData.get(position).split(",")[2].trim());
if(position%2 != 0)
holder.rlList.setBackgroundColor(0x00FF00);
else
holder.rlList.setBackgroundColor(0XFF0000);
return(row);
}
after running application when i reach to this code, an error occurs. according to LogCat it is "Null Pointer Exception" and points to this line in getView():
holder.rlList = (RelativeLayout) convertView.findViewById(R.id.rllist);
it seems everything is OK, but I don't know where my problem is?!!!
===========
Update
I have changed above line to:
holder.rlList = (RelativeLayout) row.findViewById(R.id.rllist);
and now i have my result but background did not applied?!!!

Try using
if(position%2 != 0)
holder.rlList.setBackgroundColor(Color.parseColor("#00ff00"));
else
holder.rlList.setBackgroundColor(Color.parseColor("#ff0000"));

Related

Optimizing ListView adapter to display dynamic content in individual ListView items

I'm trying to display a ListView where individual list items feature a dynamic number of elements. Each item list will have a TextView for a date. Following the date, there can be between 2-5 elements featured.
ListItemA
DateTextView
2-5 TextView
ListItemB
DateTextView
2-5 TextView
ListItemC
DateTextView
2-5 TextView
...
With this current method, it displays the blank TextViews at the bottom of the ListView's item. Would there be a better way to do this?
I thought that convertView would have had methods to add layout elements to it, but that's not the case.
Adapter's getView method:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView == null){
holder = new ViewHolder();
convertView = this.inflater.inflate(R.layout.layout_list_item, parent, false);
holder.text_date_cashout = (TextView) convertView.findViewById(R.id.text_date_cashout);
holder.dynamic_views.add((TextView) convertView.findViewById(R.id.text_cashout1));
holder.dynamic_views.add((TextView) convertView.findViewById(R.id.text_cashout2));
holder.dynamic_views.add((TextView) convertView.findViewById(R.id.text_cashout3));
holder.dynamic_views.add((TextView) convertView.findViewById(R.id.text_cashout4));
holder.dynamic_views.add((TextView) convertView.findViewById(R.id.text_cashout5));
convertView.setTag(holder);
}
else{
holder = (ViewHolder) convertView.getTag();
}
//get and set date from current cashOutHistory
CashOutHistory coh = cashOutHistory.get(position);
holder.text_date_cashout.setText(coh.getDate());
//loop individual cashOuts to display their values
int i = 0;
for (CashOut co : coh.getCashOutHistory() ){
holder.dynamic_views.get(i).setText(co.toString());
i++;
}
return convertView;
}
private class ViewHolder{
TextView text_date_cashout;
ArrayList<TextView> dynamic_views = new ArrayList<TextView>(5);
}
List item layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:id="#+id/text_date_cashout" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:id="#+id/text_cashout1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:id="#+id/text_cashout2" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:id="#+id/text_cashout3" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:id="#+id/text_cashout4" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:id="#+id/text_cashout5" />
</LinearLayout>
Edit #1
Loop showing and hidding the TextViews in my list item:
//loop individual cashOuts to display their values
int i = 0;
for (CashOut co : coh.getCashOutHistory() ){
holder.dynamic_views.get(i).setText(co.toString());
i++;
}
while(i < 5){
holder.dynamic_views.get(i).setVisibility(View.GONE);
i++;
}
You can hide each view you don't need showing for that particular item by using:
Boolean someCondition = true;
if (someCondition)
holder.dynamic_views.get(i).setVisibility(View.GONE);
Hope this helps.

I cannot load listview on my Android phone

I cannot load listview on my phone. It displays the error in the logcat:
03-24 05:27:14.537: D/AbsListView(22125): unregisterIRListener() is called
My code is as follow
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
setHasOptionsMenu(true);
rootView = inflater.inflate(R.layout.fragment_event, container, false);
listView = (ListView) rootView.findViewById(R.id.eventListView);
listView.setVisibility(View.VISIBLE);
listView.setClickable(true);
EventArrayAdapter eArrayAdapter = new EventArrayAdapter(getActivity(), R.layout.rowlayout, events);
listView.setAdapter(eArrayAdapter);
eArrayAdapter.notifyDataSetChanged();
return rootView;
}
rowlayout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="#+id/eventDay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#1d766f"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#FFFFFF" />
<TextView
android:id="#+id/eventMonth"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#e2fffd"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="#0083af" />
<TextView
android:id="#+id/eventTime"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#e2fffd"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="#1d766f" />
</LinearLayout>
<LinearLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="#+id/eventName"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#0083af"/>
<TextView
android:id="#+id/eventLocation"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>
mainlayout.xml
<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"
android:orientation="vertical" >
<Button
android:id="#+id/btnAllEvent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="All Events"
/>
<ListView
android:id="#+id/eventListView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawSelectorOnTop="false"/>
</LinearLayout>
Unfortunately, it doesnot show anything, even the listview itself. Please help me. Thank you
Update: I use the view Holder pattern
You have to return the view simply.
Also For a better scrolling you need to implement and understand the ViewHolder pattern.
Reason why you should use it is because:
layout inflations are expensive operations.
If you do something like this:
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater mInflater = mContext.getLayoutInflater();
View item = mInflater.inflate(R.layout.list_item, null);
MyObj data = getItem(position);
((TextView) item.findViewById(R.id.text1)).setText(data.text1);
((TextView) item.findViewById(R.id.text2)).setText(data.text2);
((TextView) item.findViewById(R.id.longtext)).setText(data.longText);
return item;
}
Please don't do it, because the adapter will create a new view for every position and if you have a very long list it will cause lag scroll. Imagine you have 500 item in the list, the adapter have to create 500 views!!!
So the ViewHolder pattern fix this problem by changing that code from above like this:
public View getView(int position, View convertView, ViewGroup parent) {
Log.d(TAG, "position=" + position);
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_item, parent, false);
holder = new ViewHolder();
holder.text1 = (TextView) convertView.findViewById(R.id.text1);
holder.text2 = (TextView) convertView.findViewById(R.id.text2);
holder.longtext = (TextView) convertView.findViewById(R.id.longtext);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
MyObj data = getItem(position);
holder.text1.setText(data.text1);
holder.text2.setText(data.text2);
holder.longtext.setText(data.longText);
return convertView;
}
The convertView from the getView method will have a non-null value when ListView is asking you recycle the row layout. So, when convertView is not null, you should simply update its contents instead of inflating a new row layout.
What this snippet does goes like this:
If the ConvertView is null it will inflate the layout and save each view under the ViewHolder class, what ViewHolder does is to save the views, then you save the ViewHolder in the ConverView with setTag(Object object), If convertView isn't Null then it get the ViewHolder object like this: holder = (ViewHolder) convertView.getTag();
And then it get the current object from the list with the position variable from the getView method and reference everyView through the ViewHolder instance.
Also don't use android:layout_height="wrap_content" because the listView has to call getView() lot of time to know how big it should be, so use android:layout_height="fill_parent" instead.

Gridview row height mess up when scrolling

I'm using a gridview to present various article items consisting of two textfield. Because of different amount of text the height of each item is different and a row should be sized with the height of the biggest item of a row. The gridview uses colnum = autofit.
As the following screenshot before and after scrolling show, the behaviour is as expected since i scroll down and up again: Rows mess up and cut content of big items.
What am I missing?
Gridview before scrolling:
GridView after scrolling down and up:
Further code:
item xml code
<?xml version="1.0" encoding="utf-8"?>
<TextView
android:id="#+id/title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="14dp"
android:textColor="#040404"
android:textSize="20sp"
android:textStyle="bold"
android:typeface="serif" />
<TextView
android:id="#+id/text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:textColor="#343434"
android:textSize="14sp"
android:typeface="serif" />
</LinearLayout>
My ListAdapter (recycles views if possible):
public class SearchResultListViewAdapter extends ArrayAdapter
{
Context context;
Newspaper newspaper;
List<SearchResultListItem> searchResults;
int viewStyle;
public SearchResultListViewAdapter(Context context, int resourceId, List<SearchResultListItem> searchResults, int viewStyle) {
super(context, resourceId, searchResults);
this.context = context;
this.searchResults = searchResults;
this.viewStyle = viewStyle;
}
/* private view holder class */
private class ViewHolder
{
TextView txtTitle;
TextView txtText;
}
public View getView(int position, View convertView, ViewGroup parent)
{
View gridItem;
ViewHolder holder = null;
if (convertView == null)
{
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (this.viewStyle == 0)
{
gridItem = mInflater.inflate(R.layout.searchresult_list_item, null);
} else
{
gridItem = mInflater.inflate(R.layout.searchresult_grid_item, null);
}
holder = new ViewHolder();
} else {
gridItem = convertView;
holder = (ViewHolder) gridItem.getTag();
}
holder.txtText = (TextView) gridItem.findViewById(R.id.text);
holder.txtTitle = (TextView) gridItem.findViewById(R.id.title);
gridItem.setTag(holder);
SearchResultListItem rowItem = getItem(position);
holder.txtText.setText(Html.fromHtml(rowItem.getText()), TextView.BufferType.SPANNABLE);
holder.txtTitle.setText(Html.fromHtml(rowItem.getTitle()), TextView.BufferType.SPANNABLE);
return gridItem;
}
}
And finally my activity layout containing the gridview:
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="match_parent" >
<TableRow
android:id="#+id/tableRow3"
android:layout_width="wrap_content"
android:layout_height="match_parent" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1" >
<EditText
android:id="#+id/searchPatternInput"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="#+id/loadSearchResults"
android:imeOptions="actionSearch"
android:inputType="text" />
<ImageButton
android:id="#+id/showExtendedSearch"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:src="#drawable/ic_action_filter" />
<ImageButton
android:id="#+id/loadSearchResults"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toLeftOf="#+id/showExtendedSearch"
android:src="#drawable/ic_action_search" />
</RelativeLayout>
</TableRow>
<TableRow
android:id="#+id/tableRow2"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:background="#ffffff" >
<ImageSwitcher
android:id="#+id/nothingLoaded"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="#drawable/ic_nothing_loaded" >
</ImageSwitcher>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true" >
<GridView
android:id="#+id/searchResultThumbnailsGridView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:columnWidth="160dp"
android:divider="#b5b5b5"
android:dividerHeight="1dp"
android:gravity="center"
android:horizontalSpacing="4dp"
android:listSelector="#drawable/list_selector"
android:numColumns="auto_fit"
android:padding="10dp"
android:layout_weight="1"
android:stretchMode="columnWidth"
android:verticalSpacing="4dp" />
</LinearLayout>
</RelativeLayout>
</TableRow>
</TableLayout>
You seem to have confusion using View.setTag() and View.getTag() methods. Try this:
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder = null;
if (convertView == null)
{
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (this.viewStyle == 0)
{
convertView = mInflater.inflate(R.layout.searchresult_list_item, null);
} else
{
convertView = mInflater.inflate(R.layout.searchresult_grid_item, null);
}
holder = new ViewHolder();
//Always use View.findViewById() and View.setTag() here
holder.txtText = (TextView) convertView.findViewById(R.id.text);
holder.txtTitle = (TextView) convertView.findViewById(R.id.title);
convertView.setTag(holder);
} else {
//Always use View.getTag() here
holder = (ViewHolder) convertView.getTag();
}
//Always set your data here
SearchResultListItem rowItem = getItem(position);
holder.txtText.setText(Html.fromHtml(rowItem.getText()), TextView.BufferType.SPANNABLE);
holder.txtTitle.setText(Html.fromHtml(rowItem.getTitle()), TextView.BufferType.SPANNABLE);
return convertView;
}
I moved on to use a third party component. The StaggeredGridView workes fine for me, more information can be found here.

Textview background repeats in a listview

So the problem that i am facing, is that when i try to set dynamically the background of a textView that belongs to a listView, the background that i set, is set for other textViews too..it repeats itself...i saw that these problems with listView items are common, but couldn't find a solution for me
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.product_item, null);
holder = new ViewHolder();
holder.increment = (Button) convertView.findViewById(R.id.increment);
holder.decrement = (Button) convertView.findViewById(R.id.decrement);
holder.pic_view_quantity = (TextView) convertView.findViewById(R.id.pic_view_quantity);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.pic_view_quantity.setText(products.get(position).getQuantity());
if (products.get(position).getQuantity().matches("[0-9]+")){
holder.pic_view_quantity.setBackgroundResource(R.drawable.transparent_rectangle); //this is where i set the background, to items that have a quantity
}
return convertView;
}
My layout:
<RelativeLayout
android:id="#+id/relativelayout"
android:layout_width="70dp"
android:layout_height="70dp" >
<ImageView android:id="#+id/pic_view"
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_marginTop="5sp"
android:contentDescription="#string/product_picture" >
</ImageView>
<TextView
android:id="#+id/pic_view_quantity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/pic_view"
android:layout_alignTop="#+id/pic_view"
android:layout_alignRight="#+id/pic_view"
android:layout_alignBottom="#+id/pic_view"
android:layout_margin="1dp"
android:textSize="36sp"
android:gravity="center"
android:textColor="#FF0000" />
</RelativeLayout>
Add an else to the following statement
if (products.get(position).getQuantity().matches("[0-9]+")){
holder.pic_view_quantity.setBackgroundResource(R.drawable.transparent_rectangle); //this is where i set the background, to items that have a quantity
}
else {
holder.pic_view_quantity.setBackgroundResource(0);
}

Android: ListView bug

I have a custom list view which has a Textview and an image. When I click on the textview a hidden layout will be expanded for that particular row. But what happening was, for eg., when I click on 2nd row, 10th row is also getting expanded. Here is my code,
CustomListAdapter.java
public View getView(final int position, View convertView, ViewGroup parent) {
holder = null;
DataFields rowItems = (DataFields) getItem(position);
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = inflater.inflate(R.layout.home_field_row, null);
holder = new ViewHolder();
holder.dataFields = items.get(position);
holder.mName = (TextView) convertView
.findViewById(R.id.hmFieldName);
holder.mDeleteImage = (ImageView) convertView
.findViewById(R.id.hmFieldDeleteImage);
holder.deleteMainRL = (RelativeLayout) convertView
.findViewById(R.id.hmdeleteMainRL);
holder.mDeleteImage.setTag(position);
holder.mName.setTag(position);
holder.deleteMainRL.setTag(position);
final View clickView = convertView;
holder.mName.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
RelativeLayout displayAddInfo = (RelativeLayout)clickView.findViewById(R.id.displayRecordRL);
Animation expandAnim = expand(displayAddInfo,
true);
displayAddInfo
.startAnimation(expandAnim);
}
});
convertView.setTag(holder);
}
else {
holder = (ViewHolder) convertView.getTag();
}
holder.mName.setText(rowItems.getName());
return convertView;
}
How can I fix this? Any kind of help or suggestion is much appreciated. Thanks.
Update
list_row.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/hmFieldMainRL"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/grid_shape" >
<TextView
android:id="#+id/hmFieldName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/displayRecordRL"
android:layout_alignParentLeft="true"
android:gravity="left"
android:padding="15dp"
android:shadowColor="#000000"
android:shadowDx="0"
android:shadowDy="0"
android:clickable="false"
android:shadowRadius="2"
android:text="#string/no_data"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#F2F2F2" />
<RelativeLayout
android:id="#+id/displayRecordRL"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/hmFieldName"
android:layout_centerVertical="true"
android:layout_marginBottom="5dp"
android:layout_marginLeft="1dp"
android:layout_marginRight="1dp"
android:layout_marginTop="1dp"
android:background="#drawable/display_record_bg"
android:visibility="gone" >
<EditText
android:id="#+id/displayRecordName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:layout_toLeftOf="#+id/displayRecordUpdate"
android:padding="10dp"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceMedium" />
<EditText
android:id="#+id/displayRecordPwd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="#id/displayRecordName"
android:layout_marginLeft="10dp"
android:layout_marginTop="5dp"
android:layout_toLeftOf="#+id/displayRecordShow"
android:inputType="textPassword"
android:paddingLeft="10dp"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceMedium" />
<ImageView
android:id="#+id/displayRecordAddInfoImg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginLeft="10dp"
android:layout_below="#id/displayRecordPwd"
android:contentDescription="#string/right_arrow"
android:visibility="gone"
android:src="#drawable/info" />
<EditText
android:id="#+id/displayRecordAddInfo"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="#id/displayRecordAddInfoImg"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="2dp"
android:hint="Additional Information"
android:textAppearance="?android:attr/textAppearanceMedium"
android:visibility="gone" />
<ImageView
android:id="#+id/displayRecordUpdate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:background="#drawable/display_record_img"
android:contentDescription="#string/right_arrow"
android:padding="10dp"
android:src="#drawable/update_rec" />
<ImageView
android:id="#+id/displayRecordShow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_below="#id/displayRecordUpdate"
android:layout_marginTop="10dp"
android:contentDescription="#string/right_arrow"
android:padding="10dp"
android:src="#drawable/eye" />
<ImageView
android:id="#+id/displayRecordShowRed"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_below="#id/displayRecordUpdate"
android:layout_marginTop="10dp"
android:contentDescription="#string/right_arrow"
android:padding="10dp"
android:src="#drawable/redeye"
android:visibility="gone" />
</RelativeLayout>
</RelativeLayout>
But what happening was, for eg., when I click on 2nd row, 10th row is also getting expanded.
You are fighting the way ListViews recycle the row layouts. But this is easy enough to deal with, first let's add a couple new class variables:
SparseBooleanArray expanded = new SparseBooleanArray();
LayoutInflater inflater; // initialize this in your constructor
Now we'll use expanded to check whether displayRecordRL should be visible:
public View getView(final int position, View convertView, ViewGroup parent) {
DataFields rowItems = (DataFields) getItem(position);
if (convertView == null) {
convertView = inflater.inflate(R.layout.home_field_row, null);
holder = new ViewHolder();
holder.dataFields = items.get(position);
holder.mName = (TextView) convertView
.findViewById(R.id.hmFieldName);
holder.mDeleteImage = (ImageView) convertView
.findViewById(R.id.hmFieldDeleteImage);
holder.deleteMainRL = (RelativeLayout) convertView
.findViewById(R.id.hmdeleteMainRL);
// Add this to your holder
holder.mAddInfo = (RelativeLayout) convertView
.findViewById(R.id.displayRecordRL);
holder.mDeleteImage.setTag(position);
holder.mName.setTag(position);
holder.deleteMainRL.setTag(position);
holder.mName.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// Get the ViewHolder
holder = (ViewHolder) ((View) v.getParent()).getTag();
Animation expandAnim = expand(holder.mAddInfo, true);
holder.mAddInfo.startAnimation(expandAnim);
// Remember that this View is expanded
int pos = (Integer) v.getTag();
expanded.put(pos, true);
}
});
convertView.setTag(holder);
}
else {
holder = (ViewHolder) convertView.getTag();
}
holder.mName.setText(rowItems.getName());
if(expanded.get(position, false))
holder2.mAddInfo.setVisibility(View.VISIBLE);
else
holder2.mAddInfo.setVisibility(View.GONE);
return convertView;
}
Notice how this tracks whether each row should be visible and uses a simple if statement to make sure the recycled layout correctly shows or hide the "Add Info" section.
You need to add a attribute to your adapter, a simple int. When you click on an item, update the current selected position. When you build the view, check if position equals the selected position.
public View getView(final int position, View convertView, ViewGroup parent) {
if(this.selectedPosition == position){
//add a holder
else{
//don't add a holder
return convertview;
}
What I'm saying is that you are encountering a View recycling problem. If you modify item n°2 and then the view of item n°10 is build from the View n°2, you end up with an item unwanted (that will look as it was clicked).
When an item of your list is clicked:
1) update the selected item (attribute of your adapter). Example, if you click on item 12 of your listview, selectedItem = 12;
2) call method notifyDataSetChanged(). This will refresh the view of the list.
3) When you build the view (getView() of adapter), check for each position if it corresponds to the selected item. If it does, build your special view (I don't know exactly what you want to do). If it doesn't correspond to the selected item, build your view "normally"
Try to put the R.id.displayRecordRL as part of the viewholder and on the OnClick method call it.
holder.displayAddInfo = (RelativeLayout)clickView.findViewById(R.id.displayRecordRL);
and on the OnclickMethod :
Animation expandAnim = expand(holder.displayAddInfo,
true);
holder.displayAddInfo
.startAnimation(expandAnim);
}
The problem you experience could be that you animate a View (converView) that is being re-used for another item in your list-view when scrolling.
Look at this YouTube video and you may get an idea on how to solve your problem.
Chet Haase (Google engineer) "DevBytes" series "ListView Animations" :
https://www.youtube.com/watch?v=8MIfSxgsHIs#!

Categories

Resources