I have created an adapter that feeds a list view. It is working ok but is a little jenky so I am trying to use the Convert View to avoid inflating a view on every getView call. I changed the getview method to the following
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Suggestion suggestion = getItem(position);
int type = getItemViewType(position);
ImageView imageView;
TextView titleTv;
ImageView checkBox;
switch (type) {
case Suggestion.CONTACT_SUGGESTION_ID:
ContactSuggestion contactSuggestion = (ContactSuggestion) suggestion;
String id = contactSuggestion.getId();
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.contact_history_item, parent, false);
}
imageView = (ImageView) convertView.findViewById(R.id.imageView);
PhotoRetreiver photoRetreiver = (PhotoRetreiver) imageView.getTag();
if (photoRetreiver != null) {
photoRetreiver.cancel(true);
}
if (images.containsKey(id)) {
imageView.setImageBitmap(images.get(id));
} else {
photoRetreiver = new PhotoRetreiver(context, id, imageView);
imageView.setTag(photoRetreiver);
photoRetreiver.execute();
}
titleTv = (TextView) convertView.findViewById(R.id.titleTv);
titleTv.setText(suggestion.getTitle());
checkBox = (ImageView) convertView.findViewById(R.id.favouriteIv);
checkBox.setOnClickListener(this);
checkBox.setId(position);
if (suggestion.isFavourite()) {
checkBox.setBackgroundResource(R.drawable.search_fav_active);
checkBox.setTag(true);
} else {
checkBox.setTag(false);
}
break;
case Suggestion.GOOGLE_SUGGESTION_ID:
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.google_history_item, parent, false);
}
imageView = (ImageView) convertView.findViewById(R.id.imageView);
titleTv = (TextView) convertView.findViewById(R.id.titleTv);
imageView.setImageResource(resources.getIdentifier(suggestion.getInActiveImageResource(), "drawable", "com.allryder.android"));
titleTv.setText(suggestion.getTitle());
checkBox = (ImageView) convertView.findViewById(R.id.favouriteIv);
checkBox.setOnClickListener(this);
checkBox.setId(position);
if (suggestion.isFavourite()) {
checkBox.setBackgroundResource(R.drawable.search_fav_active);
checkBox.setTag(true);
} else {
checkBox.setTag(false);
}
break;
case Suggestion.STATION_SUGGESTION_ID:
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.station_history_item, parent, false);
}
StationSuggestion stationSuggestion = (StationSuggestion) suggestion;
StationView stationView = (StationView) convertView.findViewById(R.id.stationView);
stationView.setStationTypes(stationSuggestion.getStationTypes());
titleTv = (TextView) convertView.findViewById(R.id.titleTv);
titleTv.setText(suggestion.getTitle());
checkBox = (ImageView) convertView.findViewById(R.id.favouriteIv);
checkBox.setOnClickListener(this);
checkBox.setId(position);
if (suggestion.isFavourite()) {
checkBox.setBackgroundResource(R.drawable.search_fav_active);
checkBox.setTag(true);
} else {
checkBox.setTag(false);
}
break;
case Suggestion.CURRENT_LOCATION_SUGGESTION_ID:
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.current_location_item, parent, false);
}
titleTv = (TextView) convertView.findViewById(R.id.titleTv);
titleTv.setText(suggestion.getTitle());
break;
}
TextView detailTv = (TextView) convertView.findViewById(R.id.detailTv);
detailTv.setText(suggestion.getDescription());
convertView.setTag(type);
return convertView;
}
Then overwrote the following to methods so the adapter knows which view type is should pass into the getview method
#Override
public int getViewTypeCount() {
return 4;
}
#Override
public int getItemViewType(int position) {
return getItem(position).getTypeId();
}
However I receive a a null pointer on this line
checkBox.setOnClickListener(this);
So checkbox is not instantiated.
You can see that I added a tag to the convert view this was just to check that the tag would equal the type when convert view is not null. And it always is.
Why the hell can the adapter not find checkbox?
Related
My ListView displays in first Item something else as the rest of the ListView
The Problem is, that it replaces the first item instead of taking a own position.
Example how it has to be:
A (diferent to the others)
B
B
B
How it is:
A (B Overlaid by A)
B
B
As you can see, one B is missing because it is overlaid by A.
Here is the Code. I wrote my own CustomAdapter:
#Override
public int getCount() {
if (taskItems.size() + 1 >= 0)
return taskItems.size();
return 0;
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
public static class ViewHolder {
public TextView taskTitleTextView;
public TextView taskObjectTextView;
public TextView taskLocationTextView;
public ImageView taskImageImageView;
}
public static class ViewHolderProjects {
public TextView projectTitelTextView;
public TextView projectInfoTextView;
public TextView projectDeadline;
public ImageView projectImageImageView;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View vi = convertView;
ViewHolderProjects holderProjects;
if (position == 0) {
if (convertView == null) {
vi = inflater.inflate(R.layout.list_item_projects, null);
holderProjects = new ViewHolderProjects();
holderProjects.projectTitelTextView = (TextView) vi.findViewById(R.id.projectTitle);
holderProjects.projectInfoTextView = (TextView) vi.findViewById(R.id.projectInfo);
holderProjects.projectImageImageView = (ImageView) vi.findViewById(R.id.projectImage);
holderProjects.projectDeadline = (TextView) vi.findViewById(R.id.projectdeadline);
vi.setTag(holderProjects);
} else {
holderProjects = (ViewHolderProjects) vi.getTag();
}
if (projectMap.size() <= 0) {
holderProjects.projectInfoTextView.setText("Keine Infos");
holderProjects.projectTitelTextView.setText("Kein Titel");
} else {
if (projectMap.get(position).containsKey("project_company_image")) {
if (projectMap.get(position).get("project_company_image").getBytes().length == 0) {
holderProjects.projectTitelTextView.setText(jobMap.get(position).get("job_subject"));
holderProjects.projectDeadline.setText(jobMap.get(position).get("job_deadline"));
return vi;
}
Bitmap bm = Bitmap.createBitmap(base64EncodeDecode.decodeBase64(projectMap.get(position).get("project_company_image")));
holderProjects.projectTitelTextView.setText(jobMap.get(position).get("job_subject"));
holderProjects.projectDeadline.setText(jobMap.get(position).get("job_deadline"));
holderProjects.projectImageImageView.setImageBitmap(bm);
}
}
} else {
ViewHolder holder;
if (convertView == null) {
vi = inflater.inflate(R.layout.list_item_tasks, null);
holder = new ViewHolder();
holder.taskTitleTextView = (TextView) vi.findViewById(R.id.taskTitle);
holder.taskObjectTextView = (TextView) vi.findViewById(R.id.taskObject);
holder.taskLocationTextView = (TextView) vi.findViewById(R.id.taskLocation);
holder.taskImageImageView = (ImageView) vi.findViewById(R.id.taskImage);
vi.setTag(holder);
} else {
holder = (ViewHolder) vi.getTag();
}
if (taskItems.size() <= 0) {
holder.taskTitleTextView.setText("Kein Titel");
holder.taskObjectTextView.setText("Kein Objekt");
holder.taskLocationTextView.setText("Kein Standort");
} else {
if (taskItems.get(position).containsKey("object_image")) {
if (taskItems.get(position).get("object_image").getBytes().length == 0) {
holder.taskTitleTextView.setText(taskItems.get(position).get("task_headline"));
holder.taskObjectTextView.setText(taskItems.get(position).get("object_name"));
holder.taskLocationTextView.setText(taskItems.get(position).get("object_location"));
return vi;
}
}
Bitmap bm = Bitmap.createBitmap(base64EncodeDecode.decodeBase64(taskItems.get(position).get("object_image")));
holder.taskTitleTextView.setText(taskItems.get(position).get("task_headline"));
holder.taskObjectTextView.setText(taskItems.get(position).get("object_name"));
holder.taskLocationTextView.setText(taskItems.get(position).get("object_location"));
holder.taskImageImageView.setImageBitmap(bm);
}
}
return vi;
}
First inflate your row layout into view:
LayoutInflater inflater = getLayoutInflater();
ViewGroup header = (ViewGroup)inflater.inflate(<R.layout.header>, myListView, false);
Now you can take each component of view and can assign the values to them.eg:
TextView tv = header.findViewById(<R.id.text>);
tv.setText("Something");
Now just pass that header to the list view.
myListView.addHeaderView(header, null, false);
To add listener to that header. Just pass a listnener to that view group:
header.setOnClickListener(<pass a new OnClickListener Instance>);
After that you put the code to add adapter into list view.
myListView.setAdapter(<your adapter instance>);
If there is condition in inflating view in getView of CustomAdapter then you must
override extra two methods..
declare a integer named "type" globally in adapter class
int type;
Override these two functions
#Override
public int getViewTypeCount() {
return 2;
}
#Override
public int getItemViewType(int position) {
if(position == 0){
return 0;
}else{
return 1;
}
return super.getItemViewType(position);
}
Make a slight change to your getView function as given in the following code
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View vi = convertView;
ViewHolderProjects holderProjects;
type = getItemViewType(position);
if (type == 0) {
if (convertView == null) {
vi = inflater.inflate(R.layout.list_item_projects, null);
holderProjects = new ViewHolderProjects();
holderProjects.projectTitelTextView = (TextView) vi.findViewById(R.id.projectTitle);
holderProjects.projectInfoTextView = (TextView) vi.findViewById(R.id.projectInfo);
holderProjects.projectImageImageView = (ImageView) vi.findViewById(R.id.projectImage);
holderProjects.projectDeadline = (TextView) vi.findViewById(R.id.projectdeadline);
vi.setTag(holderProjects);
} else {
holderProjects = (ViewHolderProjects) vi.getTag();
}
if (projectMap.size() <= 0) {
holderProjects.projectInfoTextView.setText("Keine Infos");
holderProjects.projectTitelTextView.setText("Kein Titel");
} else {
if (projectMap.get(position).containsKey("project_company_image")) {
if (projectMap.get(position).get("project_company_image").getBytes().length == 0) {
holderProjects.projectTitelTextView.setText(jobMap.get(position).get("job_subject"));
holderProjects.projectDeadline.setText(jobMap.get(position).get("job_deadline"));
return vi;
}
Bitmap bm = Bitmap.createBitmap(base64EncodeDecode.decodeBase64(projectMap.get(position).get("project_company_image")));
holderProjects.projectTitelTextView.setText(jobMap.get(position).get("job_subject"));
holderProjects.projectDeadline.setText(jobMap.get(position).get("job_deadline"));
holderProjects.projectImageImageView.setImageBitmap(bm);
}
}
} else {
ViewHolder holder;
if (convertView == null) {
vi = inflater.inflate(R.layout.list_item_tasks, null);
holder = new ViewHolder();
holder.taskTitleTextView = (TextView) vi.findViewById(R.id.taskTitle);
holder.taskObjectTextView = (TextView) vi.findViewById(R.id.taskObject);
holder.taskLocationTextView = (TextView) vi.findViewById(R.id.taskLocation);
holder.taskImageImageView = (ImageView) vi.findViewById(R.id.taskImage);
vi.setTag(holder);
} else {
holder = (ViewHolder) vi.getTag();
}
if (taskItems.size() <= 0) {
holder.taskTitleTextView.setText("Kein Titel");
holder.taskObjectTextView.setText("Kein Objekt");
holder.taskLocationTextView.setText("Kein Standort");
} else {
if (taskItems.get(position).containsKey("object_image")) {
if (taskItems.get(position).get("object_image").getBytes().length == 0) {
holder.taskTitleTextView.setText(taskItems.get(position).get("task_headline"));
holder.taskObjectTextView.setText(taskItems.get(position).get("object_name"));
holder.taskLocationTextView.setText(taskItems.get(position).get("object_location"));
return vi;
}
}
Bitmap bm = Bitmap.createBitmap(base64EncodeDecode.decodeBase64(taskItems.get(position).get("object_image")));
holder.taskTitleTextView.setText(taskItems.get(position).get("task_headline"));
holder.taskObjectTextView.setText(taskItems.get(position).get("object_name"));
holder.taskLocationTextView.setText(taskItems.get(position).get("object_location"));
holder.taskImageImageView.setImageBitmap(bm);
}
}
return vi;
}
You can set header to ListView like this
View headerView = getLayoutInflater().inflate(R.layout.header_view, null, false);
listview.addHeaderView(headerView);
Note: you have to set header view before setting the adapter
I am quite new to Android. In the following class the data is retrieved from the database and displayed in a ListView which has two different layouts.
Though it works as expected, the problem is that scrolling is not smooth because the textviews are assigned again and again. I couldn't figure out how to have them assigned only once. Please somebody help me out with this.
Thanks in advance. My apology for the code, I know it looks bad.
public class FragmentVerses extends ListFragment {
Typeface font;
ViewHolder viewHolder = new ViewHolder();
ViewHolderHeader viewHolderHeader = new ViewHolderHeader();
DatabaseHelper db;
public List<VersesModel> verses;
public List<ChapterModel> chapterName;
ArrayAdapter<VersesModel> adapter;
public FragmentVerses() {
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.verses_fragment, container, false);
db = new DatabaseHelper(getActivity());
try {
db.createDatabase();
} catch (IOException e) {
Toast.makeText(getActivity(), "Error Creating Database", Toast.LENGTH_LONG)
.show();
}
verses = db.getVerses(" WHERE " + getActivity().getIntent().getStringExtra(MainActivity.CONDITION));
chapterName = db.getChapter();
adapter = new MyListAdapter();
setListAdapter(adapter);
return view;
}
private class MyListAdapter extends ArrayAdapter<VersesModel> {
public MyListAdapter() {
super(getActivity(), R.layout.verses_custom_list, verses);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
VersesModel currentVerse = verses.get(position);
if (convertView == null) {
convertView = getActivity().getLayoutInflater().inflate(
R.layout.verses_custom_list, parent, false);
font = Typeface.createFromAsset(convertView.getContext().getAssets(), "Quran_Taha.ttf");
viewHolder.textView = (TextViewEx) convertView.findViewById(R.id.textView_Verse);
viewHolder.textViewTranslation = (TextView) convertView.findViewById(R.id.textView_VerseTranslation);
viewHolder.nView = (TextView) convertView.findViewById(R.id.textView_verseNumber);
viewHolder.textView.setTypeface(font);
viewHolder.imageView = (ImageView) convertView.findViewById(R.id.versesImageView);
convertView.setTag(viewHolder);
} else {
if (currentVerse.getVerseNumber() != 0) {
convertView = getActivity().getLayoutInflater().inflate(
R.layout.verses_custom_list, parent, false);
viewHolder.textView = (TextViewEx) convertView.findViewById(R.id.textView_Verse);
viewHolder.nView = (TextView) convertView.findViewById(R.id.textView_verseNumber);
viewHolder.textViewTranslation = (TextView) convertView.findViewById(R.id.textView_VerseTranslation);
viewHolder.textView.setTypeface(font);
viewHolder.textView.setText(currentVerse.getVerseText() + "", true);
viewHolder.textViewTranslation.setText(currentVerse.getVerseTranslation());
viewHolder.nView.setText(currentVerse.getVerseNumber() + "");
convertView.setTag(viewHolder);
} else {
convertView = getActivity().getLayoutInflater().inflate(
R.layout.verses_custom_list_header, parent, false);
ChapterModel chapterModel = chapterName.get(currentVerse.getChapterNumber() - 1);
if (viewHolderHeader.textViewChapter == null) viewHolderHeader.textViewBismillah = (TextView) convertView.findViewById(R.id.textView_Verse_Bismillah);
viewHolderHeader.textViewChapter = (TextView) convertView.findViewById(R.id.textView_Verse_ChapterName);
viewHolderHeader.textViewChapter.setText("سورة " + chapterModel.getChapterText());
viewHolderHeader.textViewBismillah.setTypeface(font);
viewHolderHeader.textViewChapter.setTypeface(font);
} else {
viewHolderHeader = (ViewHolderHeader) convertView.getTag();
}
convertView.setTag(viewHolderHeader);
}
}
return convertView;
}
}
I know this post is old, but just for future reference...
In this case you should use the ViewHolder pattern.
If you want to use 2 layouts just create two ViewHolder's and switch between then in the getView method.
Pretty similar to the accepted answer but with better performance.
Declare the view types.
private final int VIEW_TYPE_EXAMPLE = 0;
private final int VIEW_TYPE_EXAMPLE_TWO = 1;
Return as many types as you declared above.
#Override
public int getViewTypeCount() {
return 2;
}
Switch when returning the viewType when the item is at position X. in this case I only change the type when the item is the first on the list.
#Override
public int getItemViewType(int position) {
return (position == 0) ? VIEW_TYPE_EXAMPLE : VIEW_TYPE_EXAMPLE_TWO;
}
Create the view holders matching your layouts. They will hold your data.
class SecondViewHolder {
TextView mDate;
TextView mDescription;
TextView mObservations;
public SecondViewHolder(View view) {
mDate = (TextView) view.findViewById(R.id.txt_date);
mDescription = (TextView) view.findViewById(R.id.txt_description);
mObservations = (TextView) view.findViewById(R.id.txt_observations);
}
}
class FirstViewHolder {
ImageView mPhoto;
TextView mName;
TextView mAge;
public FirstViewHolder(View view) {
mPatientPhoto = (ImageView)view.findViewById(R.id.img_photo);
mPatientName = (TextView)view.findViewById(R.id.txt_name);
mPatientAge = (TextView)view.findViewById(R.id.txt_age);
}
}
Switch between then in the getView method.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
int viewType = getItemViewType(position);
switch (viewType) {
case VIEW_TYPE_EXAMPLE: {
FirstViewHolder firstViewHolder = null;
if(convertView == null){
convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_example, parent, false);
firstViewHolder = new FirstViewHolder(convertView);
convertView.setTag(firstViewHolder);
}
else firstViewHolder = (FirstViewHolder)convertView.getTag();
firstViewHolder.mName.setText("Your name");
firstViewHolder.mAge.setText("20 years old");
break;
}
case VIEW_TYPE_EXAMPLE_TWO: {
SecondViewHolder holder = null;
if(convertView == null){
convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_example_two, parent, false);
holder = new SecondViewHolder(convertView);
convertView.setTag(holder);
}
else holder = (SecondViewHolder)convertView.getTag();
holder.mDate.setText("01/01/2016");
holder.mDescription.setText("Description");
holder.mObservations.setText("Obs");
break;
}
}
return convertView;
}
But I can not ignore the fact that in this specific question, you should use the CursorAdapter because you are querying from a database.
You also should not do the access to the database directly.
Should create a Loader instead (does the async task but not tied to the activity).
And if you want to follow best practices and save some trouble later on, create the ContentProvider to manage your SQLite database.
But that's just too much code for me to put in this answer :/
Hope this helps someone.
Android's adapter provide a way to use multiple layouts in a single adapter.
First, tell your adapter how many layouts you need:
public int getViewTypeCount()
{
return 2;
}
Then, gives some logic to tell which layout should be used for the current item:
public int getItemViewType(int position)
{
if (verses.get(position).getVerseNumber() != 0)
{
return 0;
}
return 1;
}
Finally, in your build the appropriate view:
public View getView(int position, View convertView, ViewGroup parent)
{
if (this.getItemViewType(position) == 0)
{
// TODO Build the appropriate view
return view;
}
// TODO Build the appropriate other view
return view;
}
There are two many things to changes have a look at code below it will give you idea. You dont have to inflate layout everytime and no need to call findViewById everytime as well look at sample code below
ViewHolder holder;
if ((convertView == null)) {
convertView = layoutInflater
.inflate(R.layout.list_item,
viewGroup, false);
holder = new ViewHolder();
holder.itemImage = (ImageView) convertView
.findViewById(R.id.logo);
holder.itemName = ((TextView) convertView
.findViewById(R.id.title_product_search));
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
//assign text and images to controls after this
holder.itemName.setText("text");
imageLoader.displayImage(item.imageUrl, holder.itemImage,
options);
Here is what i did.
private class MyListAdapter extends ArrayAdapter<VersesModel> {
public MyListAdapter() {
super(getActivity(), R.layout.verses_custom_list, verses);
}
#Override
public int getViewTypeCount() {
return 2;
}
#Override
public int getItemViewType(int position) {
if (verses.get(position).getVerseNumber() != 0) {
return 0;
}
return 1;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
VersesModel currentVerse = verses.get(position);
if (convertView == null) {
viewHolder = new ViewHolder();
switch (getItemViewType(position)) {
case 0:
convertView = getActivity().getLayoutInflater().inflate(
R.layout.verses_custom_list, parent, false);
viewHolder.textView = (TextViewEx) convertView.findViewById(R.id.textView_Verse);
viewHolder.nView = (TextView) convertView.findViewById(R.id.textView_verseNumber);
viewHolder.textViewTranslation = (TextView) convertView.findViewById(R.id.textView_VerseTranslation);
font = Typeface.createFromAsset(convertView.getContext().getAssets(), "Quran_Taha.ttf");
viewHolder.textView.setTypeface(font);
Toast.makeText(getActivity(), "" + position, Toast.LENGTH_SHORT).show();
break;
case 1:
convertView = getActivity().getLayoutInflater().inflate(
R.layout.verses_custom_list_header, parent, false);
chapterModel = chapterName.get(currentVerse.getChapterNumber() - 1);
viewHolder.textView = (TextViewEx) convertView.findViewById(R.id.textView_Verse_Bismillah);
viewHolder.nView = (TextView) convertView.findViewById(R.id.textView_Verse_ChapterName);
font = Typeface.createFromAsset(convertView.getContext().getAssets(), "Quran_Taha.ttf");
viewHolder.textView.setTypeface(font);
viewHolder.nView.setTypeface(font);
break;
}
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
switch (getItemViewType(position)) {
case 0:
viewHolder.textView.setText(currentVerse.getVerseText() + "", true);
viewHolder.textViewTranslation.setText(currentVerse.getVerseTranslation());
viewHolder.nView.setText(currentVerse.getVerseNumber() + "");
break;
case 1:
viewHolder.nView.setText("سورة " + chapterModel.getChapterText());
break;
}
return convertView;
}
}
The toast displays 3 times when the list loads and the scrolling is slower at the beginning.
I am creating an app where there are images in a custom Listview. The database put a picture or another. Clicking the image has to change. But when I click the image is not changed at the correct ImageView. It changes other ImageView.
I need any help. thanks
public View getView(final int position, View convertView, ViewGroup parent) {
View v = convertView;
final MonumentosHolder holder = new MonumentosHolder();
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.listview_row, null);
TextView tv = (TextView) v.findViewById(R.id.textoListviewNombre);
ImageView img3 = (ImageView) v.findViewById(R.id.imagenVisto);
holder.texto = tv;
holder.imagenVisto = img3;
v.setTag(holder);
}
else {
holder = (MonumentosHolder) v.getTag();
}
holder.position = position;
final MonumentosObj p = monumentosLista.get(position);
holder.texto.setText(p.getNombre());
if (p.getVisto().equals("n")) {
holder.imagenVisto.setImageResource(R.drawable.vistorojo);
} else {
holder.imagenVisto.setImageResource(R.drawable.vistoverde);
}
holder.imagenVisto.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MonumentosObj p1 = monumentosLista.get(holder.position);
if (p1.getVisto().equals("s")) {
holder.imagenVisto.setImageResource(R.drawable.vistorojo);
p1.setVisto("n");
} else {
holder.imagenVisto.setImageResource(R.drawable.vistoverde);
p1.setVisto("s");
}
MonumentosAdapter.updateMonumentos(p1);
MonumentosObj p = monumentosLista.get(holder.position);
}
});
imageLoader.displayImage(imageUrls[position], holder.imagen, options, animateFirstListener);
return v;
}
EDIT
Onclick not change the correct image. But when I scroll the listview to below and and return to top, the correct image has changed...
I think that bit of code maybe wrong :
holder.imagenVisto.setOnClickListener(new View.OnClickListener() {
private int pos = position;
#Override
public void onClick(View v) {
MonumentosObj p1 = monumentosLista.get(pos);
Try to store position inside holder object and when assigning it in onClick Listener instead
private int pos = position;
do
private int pos = holder.getPosition()
Remember that android ListViews are not loading all items at one time it just loads thats what is visible and few items beyond that,
Also remember that positions of your items in your Arrays doesn't change you may use it somehow :)
try to change
holder.imagenVisto.setOnClickListener(new View.OnClickListener()
by
holder.imagenVisto.setOnClickListener(new OnClickListener()
I think your click listener affect early items in your list!
do this:
put a long item in your viewHolder:
class MonumentosHolder {
.
.
.
long position;
}
and then in your getView, set the holder positon:
View v = convertView;
--EDITED--
final MonumentosHolder holder = new MonumentosHolder();
--END EDITED--
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.listview_row, null);
TextView tv = (TextView) v.findViewById(R.id.textoListviewNombre);
ImageView img3 = (ImageView) v.findViewById(R.id.imagenVisto);
holder.texto = tv;
holder.imagenVisto = img3;
v.setTag(holder);
}
else {
holder = (MonumentosHolder) v.getTag();
}
**holder.postion = position;**
and then click listener would be like this:
EDITED
holder.imagenVisto.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MonumentosObj p1 = monumentosLista.get(**holder.position**);
if (p1.getVisto().equals("s")) {
holder.imagenVisto.setImageResource(R.drawable.vistorojo);
p1.setVisto("n");
} else {
holder.imagenVisto.setImageResource(R.drawable.vistoverde);
p1.setVisto("s");
}
MonumentosAdapter.updateMonumentos(p1);
MonumentosObj p = monumentosLista.get(holder.position);
}
});
EDIT 4
remove the final modifier from holder, define another MonumentosHolder named finalHolder like this:
public View getView(final int position, View convertView, ViewGroup parent) {
View v = convertView;
MonumentosHolder holder = new MonumentosHolder();
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.listview_row, null);
TextView tv = (TextView) v.findViewById(R.id.textoListviewNombre);
ImageView img3 = (ImageView) v.findViewById(R.id.imagenVisto);
holder.texto = tv;
holder.imagenVisto = img3;
v.setTag(holder);
}
else {
holder = (MonumentosHolder) v.getTag();
}
holder.position = position;
final MonumentosObj p = monumentosLista.get(position);
holder.texto.setText(p.getNombre());
if (p.getVisto().equals("n")) {
holder.imagenVisto.setImageResource(R.drawable.vistorojo);
} else {
holder.imagenVisto.setImageResource(R.drawable.vistoverde);
}
final MonumentosHolder finalHolder = holder;
holder.imagenVisto.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MonumentosObj p1 = monumentosLista.get(finalHolder.position);
if (p1.getVisto().equals("s")) {
holder.imagenVisto.setImageResource(R.drawable.vistorojo);
p1.setVisto("n");
} else {
holder.imagenVisto.setImageResource(R.drawable.vistoverde);
p1.setVisto("s");
}
MonumentosAdapter.updateMonumentos(p1);
MonumentosObj p = monumentosLista.get(finalHolder.position);
}
});
imageLoader.displayImage(imageUrls[position], holder.imagen, options, animateFirstListener);
return v;
}
I am using ListView with two different row layouts. The data is set and displayed properly but when i scroll up its getting null pointer exception. In logs its pointing to holder.mainContainer as null pointer, I had added comment in code where i am getting null pointer exception.
public static class ViewHolder {
....
public TextView title;
public RelativeLayout mainContainer;
public LinearLayout categoryContainer;
public TextView submenuCategoryTitle;
....
}
public View getView(int position, View convertView, ViewGroup parent) {
View vi = convertView;
ViewHolder holder;
final MultiTierMenu multiTierMenu = mMultiTierMenuList.get(position);
if (convertView == null) {
holder = new ViewHolder();
if(multiTierMenu instanceof SubMenu) {
vi = inflater.inflate(R.layout.event_list_snippet),
null);
....
holder.mainContainer = (RelativeLayout) vi.findViewById(R.id. snippet_container);
holder.title = (TextView) vi.findViewById(R.id.list_title);
....
vi.setTag(holder);
}
else if(multiTierMenu instanceof MenuCategory) {
vi = inflater.inflate(R.layout.submenu_category_list_item),
null);
....
holder.categoryContainer = (LinearLayout) vi.findViewById(R.id.category_container);
holder.submenuCategoryTitle = (TextView) vi.findViewById(R.id.subcategory_title);
....
vi.setTag(holder);
}
else
holder = (ViewHolder) vi.getTag();
//SubMenu
if(multiTierMenu instanceof SubMenu) {
final SubMenu subMenu = (SubMenu) multiTierMenu;
//GETTING NULL POINTER EXCEPTION HERE ON SCROLL UP
//if(null != holder.mainContainer) {
if(subMenu.getIsVisibleMenu())
==> holder.mainContainer.setVisibility(View.VISIBLE);
else
holder.mainContainer.setVisibility(View.GONE);
//}
//ADDING NULL CHECK ABOVE - GETTING NULL POINTER EXCEPTION HERE
holder.title.setText(subMenu.getTitle());
....
}
else if(multiTierMenu instanceof MenuCategory) {
final MenuCategory menuCategory = (MenuCategory) multiTierMenu;
holder.submenuCategoryTitle.setText(menuCategory.getTitle());
....
}
return vi;
}
Did you implement following two methods?
getItemViewType
you have to return each number by position
#Override
public int getItemViewType(int position) {
if (position % 2 == 0) {// example
return 0;// MenuCategory
}
else {
return 1;// SubMenu???
}
}
getViewTypeCount
you have to return the number of views
#Override
public int getViewTypeCount() {
return 2;
}
if their methods are implemented, "inflate" is needed only in (convertView == null).
like following...
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
int type = getItemViewType(position);
if (convertView == null){
holder = new ViewHolder();
switch (type) {
case 0:// MenuCategory
convertView = inflater.inflate(R.layout.event_list_snippet, null);
holder.mainContainer = (RelativeLayout) convertView.findViewById(R.id. snippet_container);
holder.title = (TextView) convertView.findViewById(R.id.list_title);
break;
case 1:// SubMenu???
convertView = inflater.inflate(R.layout.submenu_category_list_item, null);
holder.categoryContainer = (LinearLayout) convertView.findViewById(R.id.category_container);
holder.submenuCategoryTitle = (TextView) convertView.findViewById(R.id.subcategory_title);
break;
}
convertView.setTag(holder);
}
else {
holder = (ViewHolder) convertView.getTag();
}
// assign data into view
switch (type) {
case 0:// MenuCategory
holder.submenuCategoryTitle.setText(menuCategory.getTitle());
break;
case 1:// SubMenu???
holder.title.setText(subMenu.getTitle());
break;
}
I'm having 4 groups of contacts(Type1,2,3,None). i want to load different images 3 for Type1,2,3, if contact belong to None then listview shouldn't contain any image.. This is my code
#Override
public View getView(int position, View convertView,
ViewGroup parent) {
// return super.getView(position, convertView, parent);
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater) ContactsListActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.contacts_list_row_view, null);
}
try {
contactsData = (ContactsItem) getItem(position);
} catch (Exception e) {
}
if (null != contactsData){
final CheckBox contactsSelectedCheck = (CheckBox) v.findViewById(R.id.contact_selected_check);
TextView contactNameText = (TextView) v.findViewById(R.id.contact_name_text);
TextView contactNumberText = (TextView) v.findViewById(R.id.contact_number_text);
ImageView contactImage = (ImageView) v.findViewById(R.id.contact_image);
contactNameText.setText(contactsData.getContactName());
contactNumberText.setText(contactsData.getContactNumber());
if(contactNameText != null && contactNumberText != null){
if(contactsData.getContactProfileType() == DBConstants.TYPE_1){ contactImage.setImageDrawable(getResources().getDrawable(R.drawable.icon_1));
} else if(contactsData.getContactProfileType() == DBConstants.TYPE_2){ contactImage.setImageDrawable(getResources().getDrawable(R.drawable.icon_2));
} else if(contactsData.getContactProfileType() == DBConstants.TYPE_3){ contactImage.setImageDrawable(getResources().getDrawable(R.drawable.icon_3));
}else{
}
}
if (selectedContactsTable.containsKey(contactsData.getContactNumber())) {
contactsSelectedCheck.setChecked(true);
} else {
contactsSelectedCheck.setChecked(false);
}
contactsSelectedCheck.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (contactsSelectedCheck.isChecked()) {
LinearLayout r_layout = (LinearLayout) v.getParent();
TextView contactName = (TextView) r_layout.getChildAt(1);
TextView contactNumber = (TextView) r_layout.getChildAt(2);
selectedContactsTable.put(contactNumber.getText().toString(), contactName.getText().toString());
}else{
LinearLayout r_layout = (LinearLayout) v.getParent();
TextView contactNumber = (TextView) r_layout.getChildAt(2);
selectedContactsTable.remove(contactNumber.getText().toString());
}
}
});
}
return v;
}
}
Problem with this is if i assign some contacts to Type 1 corresponding images for this type loaded correctly but when i scroll the list same image will be loaded to some unassigned also, is there any problem with my code please tell me
do the class Holder that the other question suggested. And do the Holder for every single adapter you ever create.
To answer your question, try this edit:
contactImage.setVisibility(View.Visible);
if(contactsData.getContactProfileType() == DBConstants.TYPE_1){ contactImage.setImageDrawable(getResources().getDrawable(R.drawable.icon_1));
} else if(contactsData.getContactProfileType() == DBConstants.TYPE_2){ contactImage.setImageDrawable(getResources().getDrawable(R.drawable.icon_2));
} else if(contactsData.getContactProfileType() == DBConstants.TYPE_3){ contactImage.setImageDrawable(getResources().getDrawable(R.drawable.icon_3));
}else{
contactImage.setVisibility(View.GONE);
}
Try to make a holder class for your views. Then in the if(v==null) block, you can use setTag() and use getTag() in the else block. Here's some code.
public static class ViewHolder {
TextView contactNameText;
TextView contactNumberText;
ImageView contactImage;
}
This is a holder class that contains your views. The first part of the getView() method should then look like this:
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater) ContactsListActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.contacts_list_row_view, null);
holder = new ViewHolder();
holder.contactNameText = (TextView) v.findViewById(R.id.contact_name_text);
holder.contactNumberText = (TextView) v.findViewById(R.id.contact_number_text);
holder.contactImage = (ImageView) v.findViewById(R.id.contact_image);
v.setTag(holder);
}
else{
holder = (ViewHolder) v.getTag();
}
try {
contactsData = (ContactsItem) getItem(position);
} catch (Exception e) {
}
if (null != contactsData){
final CheckBox contactsSelectedCheck = (CheckBox) v.findViewById(R.id.contact_selected_check);
holder.contactNameText.setText(contactsData.getContactName());
holder.contactNumberText.setText(contactsData.getContactNumber());
if(contactNameText != null && contactNumberText != null){
if(contactsData.getContactProfileType() == DBConstants.TYPE_1){ holder.contactImage.setImageDrawable(getResources().getDrawable(R.drawable.icon_1));
} else if(contactsData.getContactProfileType() == DBConstants.TYPE_2){ holder.contactImage.setImageDrawable(getResources().getDrawable(R.drawable.icon_2));
} else if(contactsData.getContactProfileType() == DBConstants.TYPE_3){ holder.contactImage.setImageDrawable(getResources().getDrawable(R.drawable.icon_3));
}else{
}
}