I have a custom adapter class for a listview and I want to be able to access the content of a specific row by clicking a button on it. I tried to create a ViewHolder, but I get a NPE error when I try to click it.
static class ViewHolder {
TextView camera;
TextView players;
TextView max_players;
ImageView privata;
Button Buton;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
String variabile[] = getItem(position).split("\\s+");
LayoutInflater linflater = LayoutInflater.from(getContext());
View customView = linflater.inflate(R.layout.custom_row, parent, false);
final ViewHolder holder = new ViewHolder();
holder.camera = (TextView) customView.findViewById(R.id.Nume);
holder.players = (TextView) customView.findViewById(R.id.players);
holder.max_players = (TextView) customView.findViewById(R.id.max_players);
holder.privata = (ImageView) customView.findViewById(R.id.privata);
holder.Buton = (Button) customView.findViewById(R.id.Buton);
holder.camera.setText(variabile[0]);
if (!variabile[1].equals("true")) {
parola = false;
holder.privata.setVisibility(View.INVISIBLE);
}
holder.players.setText(variabile[2]);
holder.max_players.setText(variabile[3]);
room_id = variabile[4];
nume = variabile[5];
holder.Buton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
hash = new HashMap<String, String>();
hash.put("name", nume);
hash.put("room", room_id);
if (intra) {
holder.Buton.setText("Iesi");
site = siteul + "/join";
intra = false;
} else {
holder.Buton.setText("Intra");
site = siteul + "/leave";
intra = true;
}
new ATask().execute(site);
}
});
return customView;
}
When using the ViewHolder pattern, you should check if the convertView in null or has been created before, in the getView method, and after that use setTag and getTag methods. like this :
if (convertView == null)
{
LayoutInflater linflater = LayoutInflater.from(getContext());
convertView = linflater.inflate(R.layout.your_list_item_view, parent, false);
viewHolder.textView = (TextView)convertView.findViewById([the id]);
.
.
.
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
You need to check if the convertView is null so it is already has been visited or not then store the holder in tag Like
ViewHolder holder;
if (convertView == null) {
LayoutInflater linflater = LayoutInflater.from(getContext());
holder = linflater.inflate(R.layout.custom_row, parent, false);....
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}//Common code
Related
Dose anyone know why setImageResource cannot get image from my getImage method?
It gives me and error message saying setImageResource cannot be applied to (jave.lang.string).
I've tried changing movieImage value into a Int but it then gives me another list of errors. Should I stick to setImageResource or is that another way I can set the image in my listview from my array?
#NonNull
#Override
public View getView(int position ,View convertView, ViewGroup parent) {
setupImageLoader();
//get the movie information
String movieName = getItem(position).getTitle();
String movieDuration = getItem(position).getMovieLength();
String movieRating = getItem(position).getMovieRating();
String movieImage = getItem(position).getCoverArt();
//Create the movie object with the information
objectMovieListView objectMovieListView = new objectMovieListView(movieName, movieDuration, movieRating, movieImage);
//create the view result for showing the animation
final View result;
//ViewHolder object
ViewHolder holder;
if (convertView == null) {
LayoutInflater inflater = LayoutInflater.from(mContext);
convertView = inflater.inflate(mResource, parent, false);
holder = new ViewHolder();
holder.movieName = (TextView) convertView.findViewById(R.id.textViewMovieName);
holder.movieDuration = (TextView) convertView.findViewById(R.id.textViewMovieDuration);
holder.movieRating = (TextView) convertView.findViewById(R.id.textViewMovieRating);
holder.movieImage = (ImageButton) convertView.findViewById(R.id.movieListImageButton);
result = convertView;
convertView.setTag(holder);
}
else {
holder = (ViewHolder) convertView.getTag();
result = convertView;
}
ImageLoader imageLoader = ImageLoader.getInstance();
int defaultImage = mContext.getResources().getIdentifier("#drawable/icons8_image_moviepicture", null,mContext.getPackageName());
DisplayImageOptions options = new DisplayImageOptions.Builder().cacheInMemory(true)
.cacheOnDisc(true).resetViewBeforeLoading(true)
.showImageForEmptyUri(defaultImage)
.showImageOnFail(defaultImage)
.showImageOnLoading(defaultImage).build();
imageLoader.displayImage(movieImage, holder.movieImage, options);
holder.movieName.setText(objectMovieListView.getMovieName());
holder.movieDuration.setText(objectMovieListView.getMovieDuration());
holder.movieRating.setText(objectMovieListView.getMovieRating());
//holder.movieImage.setImageResource(R.drawable.avengers_infinity_war_poster);
holder.movieImage.setImageResource(objectMovieListView.getMovieImage());
return convertView;
}
Here's the Class where I store all my get and set methods
public class objectMovieListView {
private String movieImage;
public objectMovieListView(String movieImage) {
this.movieImage = movieImage;
public String getMovieImage() {
return movieImage;
}
public void setMovieImage(String movieImage) {
this.movieImage = movieImage;
}
}
I have two ArrayList namely "one" and "two" ["two" is always a sub-set of "one"], And i have a list view which is populating by Arraylist "one". Now am checking condition that if element of "two" is present in "one", then set ImageButton in list view and if not the set Button in list view.
Below is my getView method. Any help or keywords will be appreciated.
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
LayoutInflater inflater = LayoutInflater.from(context);
//HERE HOW TO SWITCH TWO LAYOUTS..
convertView = inflater.inflate(R.layout.invite_row, null);
viewHolder = new ViewHolder();
viewHolder.name = (TextView)convertView.findViewById(R.id.textView6);
viewHolder.text = (TextView) convertView.findViewById(R.id.childTextView);
viewHolder.button = (Button) convertView
.findViewById(R.id.childButton);
Typeface typeFace= Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Bold.ttf");
viewHolder.name.setTypeface(typeFace);
// viewHolder.button.setBackgroundResource(R.drawable.invitebuttonbackground);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
final String temp = getItem(position);
final String tempname = getItem(position);
viewHolder.name.setText(tempname);
viewHolder.button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (customListner != null) {
customListner.onButtonClickListner(position, temp, tempname);
}
}
});
return convertView;
}
one thing you can do is
View convertView;
if (whatever condition) {
convertView = inflater.inflate(R.layout.invite_row, null);
} else {
convertView = inflater.inflate(R.layout.invite_row_two, null);
}
if you can post your layout , i will have clear undestanding of what you want to doing.
I try create multi ListView but I have java.lang.NullPointerException. It seems to be alright.
Main:
for(int i = 0; i < 10; i++) {
ActivityObject ao = new ActivityObject();
if(i%2 == 0) {
ao.setType("0");
ao.setTitle("Im null");
} else {
ao.setType("1");
ao.setTitle("Im one");
}
dataActivity.add(ao);
}
ActivityAdapter adapter = new ActivityAdapter(getApplicationContext(), dataActivity);
listActivity.setAdapter(adapter);
Super Adapter
public class ActivityAdapter extends ArrayAdapter {
private Context context;
private ArrayList<ActivityObject> object;
LayoutInflater vi;
public ActivityAdapter(Context context, ArrayList<ActivityObject> object) {
super(context, 0, object);
this.context = context;
this.object = object;
vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if(convertView == null) {
if(object.get(position).equals("0")) {
convertView = vi.inflate(R.layout.p_activity_detected, null);
holder.textActivity = (TextView) convertView.findViewById(R.id.detected_text);
}
if(object.get(position).equals("1")) {
convertView = vi.inflate(R.layout.p_activity_people, null);
holder.textPeople = (TextView) convertView.findViewById(R.id.people_text);
}
holder = new ViewHolder();
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
//set text
if(object.get(position).getType().equals("0")) {
holder.textActivity.setText(object.get(position).getTitle());
}
if(object.get(position).getType().equals("1")) {
holder.textPeople.setText(object.get(position).getTitle());
}
return convertView;
}
static class ViewHolder {
public TextView textActivity;
public TextView textPeople;
}
}
Error
FATAL EXCEPTION: main
java.lang.NullPointerException
at adapters.ActivityAdapter.getView(ActivityAdapter.java:54)
this is line
convertView.setTag(holder);
Replace yours adapter with these code
public class ActivityAdapter extends ArrayAdapter {
private Context context;
private ArrayList<ActivityObject> object;
LayoutInflater vi;
ViewHolder holder;
public ActivityAdapter(Context context, ArrayList<ActivityObject> object) {
super(context, 0, object);
this.context = context;
this.object = object;
vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
holder = new ViewHolder();;
if(convertView == null) {
if(object.get(position).equals("0")) {
convertView = vi.inflate(R.layout.p_activity_detected, null);
holder.textActivity = (TextView) convertView.findViewById(R.id.detected_text);
}
if(object.get(position).equals("1")) {
convertView = vi.inflate(R.layout.p_activity_people, null);
holder.textPeople = (TextView) convertView.findViewById(R.id.people_text);
}
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
//set text
if(object.get(position).getType().equals("0")) {
holder.textActivity.setText(object.get(position).getTitle());
}
if(object.get(position).getType().equals("1")) {
holder.textPeople.setText(object.get(position).getTitle());
}
return convertView;
}
static class ViewHolder {
public TextView textActivity;
public TextView textPeople;
}
}
Move your holder on top. I think it will works. In my opinion you also have to use else statement.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView == null) {
holder = new ViewHolder();
Log.d("object.get(position) = ", object.get(position));
if(object.get(position).equals("0")) {
convertView = vi.inflate(R.layout.p_activity_detected, null);
holder.textActivity = (TextView) convertView.findViewById(R.id.detected_text);
}
else if(object.get(position).equals("1")) {
convertView = vi.inflate(R.layout.p_activity_people, null);
holder.textPeople = (TextView) convertView.findViewById(R.id.people_text);
}
else{
//set defualt holder.textPeople here
}
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
//set text
if(object.get(position).getType().equals("0")) {
holder.textActivity.setText(object.get(position).getTitle());
}
if(object.get(position).getType().equals("1")) {
holder.textPeople.setText(object.get(position).getTitle());
}
return convertView;
}
There is no guarantee in your code that convertView will not be null:
if(convertView == null) {
if(object.get(position).equals("0")) {
convertView = vi.inflate(R.layout.p_activity_detected, null);
holder.textActivity = (TextView) convertView.findViewById(R.id.detected_text);
}
if(object.get(position).equals("1")) {
convertView = vi.inflate(R.layout.p_activity_people, null);
holder.textPeople = (TextView) convertView.findViewById(R.id.people_text);
}
holder = new ViewHolder();
convertView.setTag(holder);
If none of the conditions above hold true, then convertView will still be null.
Are you sure the conditions are exactly what you want to do?
According to your declaration
private ArrayList<ActivityObject> object;
object is a list of ActivityObject, but you are comparing them with the strings "0" and "1" in
object.get(position).equals("0"))
...
object.get(position).equals("1"))
Maybe you want to cast them into ActivityObject and the compare the field in type with the strings?
My initial question was posted here:
ListView for messaging app shows wrong listItem layout after scrolling
But I am a bit confused since there are two answers that were upvoted and I'd like to use both of them. First, I think it is a safe assumption that I should use the getItemViewType method to help me with performance. After that though, should I still use the viewHolder pattern as described in Googles documentation on Making ListView Scrolling Smooth?
If I do use the ViewHolder code, do I incorporate it into getView?
static class ViewHolder {
TextView text;
TextView timestamp;
ImageView icon;
ProgressBar progress;
int position;
}
static public enum LAYOUT_TYPE {
INBOUND,
OUTBOUND
}
#Override
public int getViewTypeCount () {
return LAYOUT_TYPE.values().length;
}
#Override
public int getItemViewType (int position) {
if ( messages.get(position).isOutbound())
return LAYOUT_TYPE.OUTBOUND.ordinal();
else
return LAYOUT_TYPE.INBOUND.ordinal();
}
#Override
public View getView (int position, View convertView, ViewGroup parent) {
LAYOUT_TYPE itemType = LAYOUT_TYPE.values()[getItemViewType(position)];
... (code until inflater )
switch (itemType){
case INBOUND:
convertview = /inflate & configure inbound layout
ViewHolder holder = new ViewHolder();
holder.icon = (ImageView) convertView.findViewById(R.id.listitem_image);
holder.text = (TextView) convertView.findViewById(R.id.listitem_text);
holder.timestamp = (TextView) convertView.findViewById(R.id.listitem_timestamp);
holder.progress = (ProgressBar) convertView.findViewById(R.id.progress_spinner);
convertView.setTag(holder);
break;
case OUTBOUND:
convertview = /inflate & configure outbound layout
ViewHolder holder = new ViewHolder();
holder.icon = (ImageView) convertView.findViewById(R.id.listitem_image);
holder.text = (TextView) convertView.findViewById(R.id.listitem_text);
holder.timestamp = (TextView) convertView.findViewById(R.id.listitem_timestamp);
holder.progress = (ProgressBar) convertView.findViewById(R.id.progress_spinner);
convertView.setTag(holder);
break;
}
//Typical getView
public View getView(int position, View containerRow, ViewGroup parent) {
if (containerRow == null) {
//One time inflate
containerRow = inflater.inflate(R.layout.yourLayout, parent, false);
//instantiate all view from layout in levent relevent object.
//One time instantiation of viewholder
viewHolder = new ViewHolder();
viewHolder.someview = viewFromLayou;
//finally
containerRow.setTag(viewHolder);
}
else{
viewHolder = (ViewHolder) containerRow.getTag();
}
}
//In your case it should be
public View getView(int position, View containerRow, ViewGroup parent) {
if (containerRow == null) {
//One time inflate
containerRow = inflater.inflate(R.layout.yourLayout, parent, false);
//instantiate all view from layout in levent relevent object.
//One time instantiation of viewholder
if(inbound)
inBoundViewHolder = new ViewHolder();
else
outBoundViewHolder = new ViewHolder();
viewHolder.someview = viewFromLayou;
//finally
containerRow.setTag(viewHolder);
}
else{
viewHolder = (ViewHolder) containerRow.getTag();
}
}
How can I display text in TextView at get view after this call
ListAdapter adapter = new MyCustomAdapter (
ManageSection.this, studentList,
R.layout.list_student, new String[] { TAG_StudentID,
TAG_StudentNo,TAG_FullName},
new int[] { R.id.StudentID, R.id.StudentNo,R.id.FullName});
setListAdapter(adapter);
and the class MyCustomAdapter has a get view, I will display the text
holder.FullName= (TextView) convertView.findViewById(R.id.FullName);
holder.FullName.setText();
holder.StudentNo=(TextView) convertView.findViewById(R.id.StudentNo);
holder.StudentNo.setText();
So at set text what should I write cause I do
no=student.get(holder.position).get(TAG_StudentNo);
name =student.get(holder.position).get(TAG_FullName);
and take no, name but the text is duplicated in the whole list
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if(convertView==null)
{
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = mInflater.inflate(resource, parent, false);
holder = new ViewHolder();
no=student.get(holder.position).get(TAG_StudentNo);
name =student.get(holder.position).get(TAG_FullName);
holder.StudentID= (TextView) convertView.findViewById(R.id.StudentID);
holder.FullName= (TextView) convertView.findViewById(R.id.FullName);
holder.FullName.setText();
holder.StudentNo=(TextView) convertView.findViewById(R.id.StudentNo);
holder.StudentNo.setText();
holder.DeleteStudent = (ImageView) convertView.findViewById(R.id.DeleteStudent);
holder.AlertIcon = (ImageView) convertView.findViewById(R.id.Alert);
// add a listener for phone call
holder.DeleteStudent.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
id = student.get(holder.position).get(TAG_StudentID);
Toast.makeText(getContext(),id,Toast.LENGTH_LONG).show();
}
});
holder.AlertIcon.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// String email = MyCustomAdapter.listMap.get(holder.position).get("email");
// ActivityHelper.startActivity(ActivityManager.EMAIL, email);
}
});
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
holder.position = position;
return convertView;
}
private static class ViewHolder
{
ImageView DeleteStudent;
ImageView AlertIcon;
TextView StudentID, StudentNo ,FullName;
int position;
}
}
Can anyone tell me what the problem is here?
Try this code.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if(convertView==null)
{
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = mInflater.inflate(resource, parent, false);
holder = new ViewHolder();
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
holder.position = position;
no=student.get(holder.position).get(TAG_StudentNo);
name =student.get(holder.position).get(TAG_FullName);
holder.StudentID= (TextView) convertView.findViewById(R.id.StudentID);
holder.FullName= (TextView) convertView.findViewById(R.id.FullName);
holder.FullName.setText();
holder.StudentNo=(TextView) convertView.findViewById(R.id.StudentNo);
holder.StudentNo.setText();
holder.DeleteStudent = (ImageView) convertView.findViewById(R.id.DeleteStudent);
holder.AlertIcon = (ImageView) convertView.findViewById(R.id.Alert);
// add a listener for phone call
holder.DeleteStudent.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
id = student.get(holder.position).get(TAG_StudentID);
Toast.makeText(getContext(),id,Toast.LENGTH_LONG).show();
}
});
holder.AlertIcon.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// String email = MyCustomAdapter.listMap.get(holder.position).get("email");
// ActivityHelper.startActivity(ActivityManager.EMAIL, email);
}
});
return convertView;
}
private static class ViewHolder
{
ImageView DeleteStudent;
ImageView AlertIcon;
TextView StudentID, StudentNo ,FullName;
int position;
}
}
What you were doing is just setting the data only when the convertView is null and if not you just returning the view after some Holder operation. You need to set Text etc, in the textView in every case. If you need more explanation, please ask.
its simple buddy U just have to put this line instead of blank setText()
no=student.get(holder.position).get(TAG_StudentNo);// the roll_number string
name =student.get(holder.position).get(TAG_FullName);//full name string
holder.StudentID= (TextView) convertView.findViewById(R.id.StudentID);
holder.FullName= (TextView) convertView.findViewById(R.id.FullName);
holder.FullName.setText(name);//pass fullname
holder.StudentNo=(TextView) convertView.findViewById(R.id.StudentNo);
holder.StudentNo.setText(no);//pass roll no.
you just have to pass the no and 'namevariable tosetText()` method.