Dynamic display of ListView elements partially working - java

I am making a time sheet program where a user inputs his in- and out-punches. I have a ListView that I am populating from an array of calendar objects. I would like each row to show the day and date then on a new line the time, but I only want to display the day and date if it is different from the previous element.
Currently, I am setting visibility in the BaseAdapter based on comparisons using position vs position-1 (which are used as indices to the array). This only works if the whole list fits on the screen. If it extends beyond the screen and the user scrolls around the results are unpredictable.
To further confuse things, I am setting the color of the times, based on the position, to alternate between green and red (in/out) and it works as expected, scrolling or not.
How does Android handle the ListView position when scrolling or what could I do differently to show/hide the day and date?
public class TimeSheetActivity extends Activity {
SQLiteDatabase timesDatabase;
Cursor punchCursor;
private static Calendar[] allPunches;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.timesheet);
} //end onCreate()
#Override
public void onResume() {
super.onResume();
//Open database
timesDatabase = openOrCreateDatabase(
"times_database.db",
SQLiteDatabase.CREATE_IF_NECESSARY,
null);
timesDatabase.setLocale(Locale.getDefault());
timesDatabase.setLockingEnabled(true);
timesDatabase.setVersion(1);
punchCursor = timesDatabase.query("Timepunches", null, null, null, null, null, "punch ASC;");
updateTimeSheet();
} //end onResume()
#Override
public void onPause() {
super.onPause();
timesDatabase.close();
} //end onResume()
private static class EfficientAdapter extends BaseAdapter {
private LayoutInflater mInflater;
public EfficientAdapter(Context context) {
mInflater = LayoutInflater.from(context);
}
public int getCount() {
return allPunches.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.time_list_row, null);
holder = new ViewHolder();
holder.text1 = (TextView) convertView.findViewById(R.id.day_textview);
holder.text2 = (TextView) convertView.findViewById(R.id.date_textview);
holder.text3 = (TextView) convertView.findViewById(R.id.times_this_day_textview);
convertView.setTag(holder);
}
else {
holder = (ViewHolder) convertView.getTag();
}
String dayNames[] = new DateFormatSymbols().getWeekdays();
//Initialize first list element
if (position < 1) {
holder.text1.setText(dayNames[allPunches[position].get(Calendar.DAY_OF_WEEK)]);
holder.text2.setText(formatDate(allPunches[position]));
}
else {
holder.text1.setText(dayNames[allPunches[position].get(Calendar.DAY_OF_WEEK)]);
holder.text2.setText(formatDate(allPunches[position]));
holder.text1.setVisibility(View.VISIBLE);
holder.text2.setVisibility(View.VISIBLE);
//Hide day and date if same as last
if (formatDate(allPunches[position]).contentEquals(formatDate(allPunches[position-1]))) {
holder.text1.setVisibility(View.GONE);
holder.text2.setVisibility(View.GONE);
}
}
holder.text3.setText(formatTime(allPunches[position], true) + " " + position);
//Color in/out punches
if (position%2 == 0) {
holder.text3.setTextColor(Color.GREEN);
}
else {
holder.text3.setTextColor(Color.RED);
}
return convertView;
} //end getView()
static class ViewHolder {
public TextView text1;
TextView text2;
TextView text3;
}
} //end EfficientAdapter
public void updateTimeSheet() {
punchCursor = timesDatabase.query("Timepunches", null, null, null, null, null, "punch ASC;");
allPunches = new Calendar[punchCursor.getCount()];
int i = 0; //for indexing allPunches
Calendar nextDay = Calendar.getInstance();
nextDay.setLenient(true);
//populate allPunches
for (punchCursor.moveToFirst(); !punchCursor.isAfterLast(); punchCursor.moveToNext()) {
allPunches[i] = Calendar.getInstance();
allPunches[i].setTimeInMillis(punchCursor.getLong(0));
++i;
} //end for
final ListView timeSheetListView = (ListView)findViewById(R.id.timesheet_listview);
timeSheetListView.setAdapter(new EfficientAdapter(this));
timeSheetListView.setOnItemClickListener(new OnItemClickListener() {...}); //end click listener for list item
} //end updateTimeSheet()
public static String formatTime(Calendar thisTime, boolean showAMPM) {...}
public static String formatDate(Calendar thisDate) {
String formattedDate = "";
formattedDate += thisDate.get(Calendar.MONTH) +"-"+ thisDate.get(Calendar.DAY_OF_MONTH) +"-"+ thisDate.get(Calendar.YEAR);
return formattedDate;
} //end formatDate()
} //end TimeSheet Activity

The views in the ListView are resused as you scroll. This likely causes the odd behavior you see. The important thing to remember when overriding getView is to set the behavior explicitly every time. Don't depend on a a view being in a default state, since you may be reusing a view that has already been changed.
In your particular case, make sure that you always set the visiblity explicitly to true or gone.
Also, did you copy paste this code directly? I believe you are missing a closing bracket for your second else statement.

I seem to have been setting VISIBLE in the wrong place. Here is the code for getView() that seems to have it fixed!
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.time_list_row, null);
holder = new ViewHolder();
holder.text1 = (TextView) convertView.findViewById(R.id.day_textview);
holder.text2 = (TextView) convertView.findViewById(R.id.date_textview);
holder.text3 = (TextView) convertView.findViewById(R.id.times_this_day_textview);
convertView.setTag(holder);
}
else {
holder = (ViewHolder) convertView.getTag();
}
String dayNames[] = new DateFormatSymbols().getWeekdays();
holder.text1.setVisibility(View.VISIBLE);
holder.text2.setVisibility(View.VISIBLE);
//Initialize list
if (position < 1) {
holder.text1.setText(dayNames[allPunches[position].get(Calendar.DAY_OF_WEEK)]);
holder.text2.setText(formatDate(allPunches[position]));
}
else {
//Show day and date if not same as last
holder.text1.setText(dayNames[allPunches[position].get(Calendar.DAY_OF_WEEK)]);
holder.text2.setText(formatDate(allPunches[position]));
if (formatDate(allPunches[position]).contentEquals(formatDate(allPunches[position-1]))) {
holder.text1.setVisibility(View.GONE);
holder.text2.setVisibility(View.GONE);
}
}
holder.text3.setText(formatTime(allPunches[position], true));
//Color in/out punches
if (position%2 == 0) {
holder.text3.setTextColor(Color.GREEN);
}
else {
holder.text3.setTextColor(Color.RED);
}
return convertView;
} //end getView()
static class ViewHolder {
public TextView text1;
TextView text2;
TextView text3;
}
} //end EfficientAdapter

Related

Can't put an ArrayList in a ListView inside a CustomAdapter in Android Studio

I'm having a problem understanding how to finish this part of my code.
It's an app that searches a list of games with the help of an API.
Everything is working so far so good right now, but one final thing.
In the code, first of all I have a simple activity with an edit_text, a button and an empty list view that it is called "lv_listofgames".
Then, when I press the "search" button, I fill the "lv_listofgames" with a series of rows formed by an imageview, a listView called "list_item_text" and a button.
To this point everything is okay it seems.
Then I should just fill the "list_item_text" inside the "lv_listofgames" with the contents of an arraylist but I just can't make it happen. I tried in many ways but I'm stuck. I even tried using 2 adapters but the app crashed everytime or the "list_item_text" remained empty.
The arrayList is something like: [game_title='Name', release_date='date', platform=platform]
I seem so close to the solution but I just can't figure it out how to accomplish that. Im going crazy :(
tl;dr: problem: when I press the "search" button the arrayList content doesn't appear in the ListView "list_item_text".
Here is the code, tell me if something is wrong, thanks:
public class MainActovity extends AppCompatActivity {
EditText et_searchName;
Button btn_search;
ListView lv_listofgames;
ListView lv;
final GamesDataService gameDataService = new GamesDataService(MainActovity.this);
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity);
et_searchName = findViewById(R.id.et_searchName);
btn_search = findViewById(R.id.btn_search);
lv_listofgames= findViewById(R.id.lv_listofgames);
btn_search.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
gameDataService.getGameName(et_searchName.getText().toString(), new GamesDataService.searchGamesResponse() {
#Override
public void onError(String message) {
Toast.makeText(MainActovity.this, "Error", Toast.LENGTH_SHORT).show();
}
#Override
public void onResponse(List<GamesReportModel> gamesReportModels) {
List<GamesReportModel> newName = gamesReportModels;
List<String> stringsList = new ArrayList<>(newName.size());
for (Object object : newName) {
stringsList.add(Objects.toString(object, null));
}
System.out.println("stringsList:" + stringsList);
lv = (ListView) findViewById(R.id.lv_listofnames);
MyListAdapter adapter = new MyListAdapter(MainActovity.this, R.layout.details, stringsList);
lv.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
});
}
});
}
class MyListAdapter extends ArrayAdapter<String> {
private int layout;
public MyListAdapter(#NonNull Context context, int resource, #NonNull List<String> objects) {
super(context, resource, objects);
layout = resource;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
MainActovity.ViewHolder mainViewHolder = null;
if(convertView == null) {
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(layout, parent, false);
MainActovity.ViewHolder viewHolder = new MainActovity.ViewHolder();
viewHolder.thumbnail = (ImageView) convertView.findViewById(R.id.list_item_thumbnail);
viewHolder.title = (ListView) convertView.findViewById(R.id.list_item_text);
viewHolder.button = (Button) convertView.findViewById(R.id.list_item_btn);
convertView.setTag(viewHolder);
viewHolder.button.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
}
});
}
else {
mainViewHolder = (MainActovity.ViewHolder) convertView.getTag();
}
return convertView;
}
}
public class ViewHolder {
ImageView thumbnail;
ListView title;
Button button;
}
}
GamesReportModel:
public class GamesReportModel {
private String game_title;
private String release_date;
private String platform;
public GamesReportModel(String game_title, String release_date, String platform) {
this.game_title = game_title;
this.release_date = release_date;
this.platform = platform;
}
public GamesReportModel() {
}
#Override
public String toString() {
return "game_title='" + game_title + '\'' +
", release_date='" + release_date + '\'' +
", platform=" + platform;
}
public String getGame_title() {
return game_title;
}
public void setGame_title(String game_title) {
this.game_title = game_title;
}
public String getRelease_date() {
return release_date;
}
public void setRelease_date(String release_date) {
this.release_date = release_date;
}
public String getPlatform() {
return platform;
}
public void setPlatform(String platform) {
this.platform = platform;
}
}
There are two things you need to change in your code to get the desired effect.
In your row view layout (R.layout.details), replace the ListView with a TextView since you are just trying to show text for a given row (not a nested list inside each row). Then update the view holder to hold the correct view type as well
viewHolder.title = (TextView) convertView.findViewById(R.id.list_item_text);
//...
public class ViewHolder {
ImageView thumbnail;
TextView title;
Button button;
}
In the adapter's getView method you have to actually set the text to show for that row. You never set the text to show anywhere, which is why your rows are blank. That should look like this:
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
MainActovity.ViewHolder mainViewHolder = null;
if(convertView == null) {
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(layout, parent, false);
MainActovity.ViewHolder viewHolder = new MainActovity.ViewHolder();
viewHolder.thumbnail = (ImageView) convertView.findViewById(R.id.list_item_thumbnail);
viewHolder.title = (TextView) convertView.findViewById(R.id.list_item_text);
viewHolder.button = (Button) convertView.findViewById(R.id.list_item_btn);
convertView.setTag(viewHolder);
}
else {
mainViewHolder = (MainActovity.ViewHolder) convertView.getTag();
}
// Here, you need to set what values to show for this row - this
// is why your list is empty/blank
mainViewHolder.title.setText((String)getItem(position));
return convertView;
}

Listview not behaving well with Folding Cell Library

I have a problem using folding cell library from the RAMOTION
I have implemented everything but I am facing a problem with the list view
I have a list of planets and when user tap on let's say Jupiter the view gets unfolded and more information is visible to the user and when user tap on the same view which is seeing then the view gets folded
Problem
if the user scrolls down the list and then scroll back up and come back up to Jupiter the view remains unfolded and it is happening to all the view.
I appreciate if anyone helps me out
folding state
here
unfolding state
here
AdapterClass
#SuppressWarnings({"WeakerAccess", "unused"})
public class SolarSystemFoldingCellListAdapter extends ArrayAdapter<SolarSystemItemFoldingCell> {
private HashSet<Integer> unfoldedIndexes = new HashSet<>();
private View.OnClickListener defaultRequestBtnClickListener;
private int incomingPosition ;
public SolarSystemFoldingCellListAdapter(Context context, List<SolarSystemItemFoldingCell> objects) {
super(context, 0, objects);
}
#NonNull
#Override
public View getView(int position, View convertView, #NonNull ViewGroup parent) {
// get item for selected view
SolarSystemItemFoldingCell solarSystemItemFoldingCell = getItem(position);
// if cell is exists - reuse it, if not - create the new one from resource
FoldingCell cell = (FoldingCell) convertView;
final ViewHolder viewHolder;
if (cell == null) {
viewHolder = new ViewHolder();
LayoutInflater vi = LayoutInflater.from(getContext());
cell = (FoldingCell) vi.inflate(R.layout.solar_system_folding_cell, parent, false);
// binding view parts to view holder
viewHolder.foldingCell = cell.findViewById(R.id.folding_cell);
viewHolder.relativeLayoutFolded = cell.findViewById(R.id.relativeLayoutFolded);
viewHolder.linearLayoutFolded = cell.findViewById(R.id.linearLayoutFolded);
viewHolder.planetOrStarNameFolded = cell.findViewById(R.id.planetOrStarNameFolded);
viewHolder.mass = cell.findViewById(R.id.mass);
viewHolder.actualMass = cell.findViewById(R.id.actualMass);
viewHolder.distance = cell.findViewById(R.id.distance);
viewHolder.actualDistance = cell.findViewById(R.id.actualDistance);
viewHolder.diameter = cell.findViewById(R.id.diameter);
viewHolder.actualDiameter = cell.findViewById(R.id.actualDiameter);
viewHolder.speed = cell.findViewById(R.id.speed);
viewHolder.actualSpeed = cell.findViewById(R.id.actualSpeed);
viewHolder.moreInfoButton = cell.findViewById(R.id.button);
viewHolder.frameLayoutUnfolded = cell.findViewById(R.id.frameLayoutUnfolded);
viewHolder.planetOrStarNameUnfolded = cell.findViewById(R.id.planetOrStarNameUnfolded);
cell.setTag(viewHolder);
} else {
// for existing cell set valid valid state(without animation)
if (unfoldedIndexes.contains(position)) {
cell.unfold(true);
} else {
cell.fold(true);
}
viewHolder = (ViewHolder) cell.getTag();
}
if (null == solarSystemItemFoldingCell)
return cell;
// bind data from selected element to view through view holder
viewHolder.planetOrStarNameFolded.setText(solarSystemItemFoldingCell.getPlantOrStarNameFolded());
viewHolder.actualMass.setText(solarSystemItemFoldingCell.getActualMass());
viewHolder.actualDistance.setText(solarSystemItemFoldingCell.getActualDistance());
viewHolder.actualDiameter.setText(solarSystemItemFoldingCell.getActualDiameter());
viewHolder.actualSpeed.setText(solarSystemItemFoldingCell.getActualSpeed());
viewHolder.planetOrStarNameUnfolded.setText(String.valueOf(solarSystemItemFoldingCell.getPlanetOrStarNameUnfolded()));
//setting Fonts
viewHolder.planetOrStarNameFolded.setTypeface(App.getAppInstance().getArvoBold());
viewHolder.mass.setTypeface(App.getAppInstance().getArvoBold());
viewHolder.distance.setTypeface(App.getAppInstance().getArvoBold());
viewHolder.diameter.setTypeface(App.getAppInstance().getArvoBold());
viewHolder.speed.setTypeface(App.getAppInstance().getArvoBold());
viewHolder.actualMass.setTypeface(App.getAppInstance().getArvoRegular());
viewHolder.actualDistance.setTypeface(App.getAppInstance().getArvoRegular());
viewHolder.actualDiameter.setTypeface(App.getAppInstance().getArvoRegular());
viewHolder.actualSpeed.setTypeface(App.getAppInstance().getArvoRegular());
viewHolder.moreInfoButton.setTypeface(App.getAppInstance().getArvoRegular());
// set custom btn handler for list item from that item
if (solarSystemItemFoldingCell.getRequestBtnClickListener() != null) {
viewHolder.moreInfoButton.setOnClickListener(solarSystemItemFoldingCell.getRequestBtnClickListener());
} else {
// (optionally) add "default" handler if no handler found in item
viewHolder.moreInfoButton.setOnClickListener(defaultRequestBtnClickListener);
}
viewHolder.relativeLayoutFolded.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getContext(), "Something gets clicked", Toast.LENGTH_SHORT).show();
viewHolder.foldingCell.fold(false);
registerFold(incomingPosition);
}
});
return cell;
}
// simple methods for register cell state changes
public void registerToggle(int position) {
if (unfoldedIndexes.contains(position)) {
registerFold(position);
incomingPosition = position;
}else
registerUnfold(position);
}
public void registerFold(int position) {
unfoldedIndexes.remove(position);
}
public void registerUnfold(int position) {
unfoldedIndexes.add(position);
}
public View.OnClickListener getDefaultRequestBtnClickListener() {
return defaultRequestBtnClickListener;
}
public void setDefaultRequestBtnClickListener(View.OnClickListener defaultRequestBtnClickListener) {
this.defaultRequestBtnClickListener = defaultRequestBtnClickListener;
}
// View lookup cache
private static class ViewHolder {
RelativeLayout relativeLayoutFolded ;
LinearLayout linearLayoutFolded ;
TextView planetOrStarNameFolded;
TextView mass;
TextView actualMass;
TextView distance;
TextView actualDistance;
TextView diameter;
TextView actualDiameter;
TextView speed;
TextView actualSpeed ;
Button moreInfoButton ;
FrameLayout frameLayoutUnfolded ;
TextView planetOrStarNameUnfolded;
FoldingCell foldingCell ;
}
}
SolarSystemClass
private void listViewIntegration (){
arrayList = addingDataIntoList();
solarSystemFoldingCellListAdapter = new SolarSystemFoldingCellListAdapter(SolarSystem.this , arrayList);
listView.setAdapter(solarSystemFoldingCellListAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
int duration = 500; //miliseconds
int offset = 0; //fromListTop
listView.smoothScrollToPositionFromTop(position,offset,duration);
// toggle clicked cell state
((FoldingCell) view).toggle(false);
// register in adapter that state for selected cell is toggled
solarSystemFoldingCellListAdapter.registerToggle(position);
// listView.smoothScrollToPosition(position);
}
});
}

NullPointerException on populating data in BaseAdapter

I'm trying to populate a listview with data passed into the activity via a the intent that created it. The println statement you see confirms that the data is passed in correctly (i.e. the expected content is printed, meaning that the ArrayList referenced in the adapter is properly initialized). However, I keep getting a NullPointerException on the line
content.setText(Html.fromHtml(cmts.get(position).content));
There must be something wrong in the adapter - maybe in the getItem(), or perhaps my calls to cmts.get(position) isn't doing what I think it is, but at this point I can't figure it out.
public class CommentsView extends Activity {
ArrayList<Comment> cmts;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_comments_view);
cmts = (ArrayList<Comment>) getIntent().getExtras().getSerializable("clist");
for (Comment c : cmts) {
System.out.println("CMTinCV: " + c.content);
}
ListView lv = (ListView)findViewById(R.id.commentsList);
CommentAdapter ca = new CommentAdapter();
lv.setAdapter(ca);
}
class CommentAdapter extends BaseAdapter {
public CommentAdapter(){
}
#Override
public int getCount() {
return cmts.size()-1;
}
#Override
public Object getItem(int position) {
return cmts.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = getLayoutInflater().inflate(R.layout.commentbox, null);
TextView content = (TextView)findViewById(R.id.commentText);
TextView author = (TextView)findViewById(R.id.commentAuthor);
TextView date = (TextView)findViewById(R.id.commentDate);
content.setText(Html.fromHtml(cmts.get(position).content));
author.setText(cmts.get(position).author.name);
date.setText(cmts.get(position).date);
}
return convertView;
}
}
}
You need to access the textview's in your getview method as below:
convertView.findViewById(R.id.commentText); access it like this.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = getLayoutInflater().inflate(R.layout.commentbox, null);
TextView content = (TextView)convertView.findViewById(R.id.commentText);
TextView author = (TextView)convertView.findViewById(R.id.commentAuthor);
TextView date = (TextView)convertView.findViewById(R.id.commentDate);
content.setText(Html.fromHtml(cmts.get(position).content));
author.setText(cmts.get(position).author.name);
date.setText(cmts.get(position).date);
}
return convertView;
}
Change your Adapter's constructor to this (if it's not an inner class for your activity) :
ArrayList<Comment> cmts;
public CommentAdapter(ArrayList<Comment> mComments){
this.cmts = mComments;
}
and these lines :
TextView content = (TextView)findViewById(R.id.commentText);
TextView author = (TextView)findViewById(R.id.commentAuthor);
TextView date = (TextView)findViewById(R.id.commentDate);
should be like :
TextView content = (TextView) convertView.findViewById(R.id.commentText);
TextView author = (TextView) convertView.findViewById(R.id.commentAuthor);
TextView date = (TextView) convertView.findViewById(R.id.commentDate);
Check if the variable is null or not first:
if(cmts.get(position) != null) {
content.setText(Html.fromHtml(cmts.get(position).content));
author.setText(cmts.get(position).author.name);
date.setText(cmts.get(position).date);
}
To create the adapter like this
CommentAdapter ca = new CommentAdapter(cmts);
And CommentAdapter class to create constructor like this
public CommentAdapter(ArrayList<Comment> cmts){
this.cmts = cmts;
}
And create local variable in CommentAdapter class
private ArrayList<Comment> cmts;

ListView displays data from last passes as well as current pas

I have a small "search" implementation I am working on. A listView displays the items if they match the query. This works fine, but whenever the menu is hidden and re-displayed and a new query is made, all the "searchables" continue to stack up. If i have 4 that should be displaying, first it would show 4, then 8, then 12, etc.
private class Adapter extends BaseAdapter {
private LayoutInflater inflater;
public Adapter(){
inflater = LayoutInflater.from(getContext());
}
#Override
public int getCount() {
return menuItems.size();
}
#Override
public Object getItem(int position) {
return menuItems.get(position).text;
}
#Override
public long getItemId(int position) {
return menuItems.get(position).id;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder holder = new ViewHolder();
if (!isSearching) {
convertView = inflater.inflate(R.layout.rbm_item, null);
} else {
convertView = inflater.inflate(R.layout.rbm_search_item, null);
}
holder.subMenuList = (LinearLayout) convertView.findViewById(R.id.sub_holder);
holder.text = (TextView) convertView.findViewById(R.id.rbm_item_text);
convertView.setTag(holder);
convertView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (holder.subMenuList.getVisibility() == View.VISIBLE) {
holder.subMenuList.setVisibility(View.GONE);
} else {
holder.subMenuList.setVisibility(View.VISIBLE);
}
}
});
if (isSearching) {
holder.image = (ImageView) convertView.findViewById(R.id.rbm_item_icon);
holder.image.setImageResource(menuItems.get(position).icon);
holder.chapterId = (TextView) convertView.findViewById(R.id.id_text);
holder.chapterId.setText("Ch"+Integer.toString(menuItems.get(position).id));
} else {
holder.chapterId = (TextView) convertView.findViewById(R.id.rbm_item_id);
holder.chapterId.setText(Integer.toString(menuItems.get(position).id));
}
holder.text.setText(menuItems.get(position).text);
if (!isSearching) {
for (int i=0;i<menuItems.get(position).subItems.size();i++) {
TextView tv = new TextView(ctx);
tv.setTextColor(0xFF893658);
tv.setText(menuItems.get(position).subItems.get(i).getTitle());
tv.setCompoundDrawablesWithIntrinsicBounds(menuItems.get(position).subItems.get(i).getIcon(), 0, 0, 0);
tv.setCompoundDrawablePadding(5);
if (i == 0) {
if (menuItems.get(position).subItems.size() == 1) {
tv.setPadding(20, 20, 0, 20);
} else{
tv.setPadding(20, 20, 0, 10);
}
} else if (i == menuItems.get(position).subItems.size()-1){
tv.setPadding(20, 10, 0, 20);
} else {
tv.setPadding(20, 10, 0, 10);
}
holder.subMenuList.addView(tv);
}
}
return convertView;
}
class ViewHolder {
TextView text;
ImageView image;
LinearLayout subMenuList;
TextView chapterId;
}
}
try to clear the listitems that are in the menuItems and then add the items back after the new query is made.
Is the try to clear the listitems that are in the menuItems and then add the items back after the new query is made a arraylist or something?
Hard to tell for sure from what you posted, but I'd guess that you're appending the new results to menuItems rather than replacing it with your new data.
I didn't understand your problem much. but by just glancing over your code i see one issue
if (!isSearching) {
convertView = inflater.inflate(R.layout.rbm_item, null);
} else {
convertView = inflater.inflate(R.layout.rbm_search_item, null);
}
This piece can be the cause of your problem.
getView method of list adaptor gets called very frequently and so it should contain minimum and less heavy operation.
If you will going to check the default examples of list adapters. you will going to see the convertView is checked against null so that it need not to be inflated again and is reused again for faster preparation of view to be displayed in the list.
And this is not happening in your code.
Google about Efficient Adapter Example Android.

Android custom listview

I'm trying to create custom listview in android.
When I try to access my arraylist variale historyArrayList in HistoryAdapter -> getView, historyArrayList always return me last added element arraylist.
public class HistoryDetails extends Activity {
List<HistoryInfoClass> historyArrayList = new ArrayList<HistoryInfoClass>() ;
DBAdapter db = new DBAdapter(this);
private class HistoryAdapter extends BaseAdapter {
private LayoutInflater mInflater;
public HistoryAdapter(Context context) {
mInflater = LayoutInflater.from(context);
}
public int getCount() {
return historyArrayList.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.history_listview, null);
holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(R.id.TextView01);
holder.text2 = (TextView) convertView.findViewById(R.id.TextView02);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
//PROBLEM HERE " historyArrayList.get(position).Time " always give me last element in historyArrayList, and historyArrayList.get(0).Time give me last element too, and get(1)
holder.text.setText(Integer.toString( historyArrayList.get(position).Time ));
holder.text2.setText(Integer.toString( historyArrayList.get(position).Time1 ));
return convertView;
}
private class ViewHolder {
TextView text;
TextView text2;
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.historydetails);
super.onCreate(savedInstanceState);
HistoryFromDBToArray();
ListView l1 = (ListView) findViewById(R.id.ListView01);
l1.setAdapter(new HistoryAdapter(this));
l1.setOnItemClickListener(new OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
Toast.makeText(getBaseContext(), "You clciked ", Toast.LENGTH_LONG).show();
}
});
}
class HistoryInfoClass {
Integer Time = 0,
Time1 = 0;
}
private void HistoryFromDBToArray(){
HistoryInfoClass History = new HistoryInfoClass();
historyArrayList.clear();
db.open();
int i =0;
Cursor c = db.getHistory("history");
startManagingCursor(c);
if (c.moveToFirst())
{
do {
History.Time = c.getInt(1);
History.Time1 = c.getInt(2);
historyArrayList.add(History);
// Here "historyArrayList.get(i).Time" return true value (no last record)
i++;
} while (c.moveToNext());
}
db.close();
}
}
When you populate historyArrayList, you're updating and adding the same object History every time through the loop. Try reinitializing History at the start of the loop:
do {
// Initialize History
History = new HistoryInfoClass();
History.Time = c.getInt(1);
History.Time1 = c.getInt(2);
historyArrayList.add(History);
i++;
} while (c.moveToNext());
getItem looks incorrect
I would also suggest you clean up and restructure the code someone can help you with the rest, it is hard to follow
look at this tutorial... scroll down to the WeatherDataListAdapter code

Categories