I wrote a custom ArrayAdapter to show my listview items.
My items have many types. if the type is text then i show a TextView and if the type is Image or Video i show an ImageView (for video the thumbnail).
This is the code.
public class MessageAdapter extends ArrayAdapter<NMessage> {
public static final int ALL_MESSAGES = 0;
public static final int MEDIA_ONLY = 1;
Context context;
DatabaseActions db;
ArrayList<NMessage> items;
AQuery aq;
Profile myProfile = ProfilesSingleton.getInstance().getCurrentProfile();
LayoutInflater inflater;
int type;
public MessageAdapter(Context context, int resource, ArrayList<NMessage> objects) {
super(context, resource, objects);
this.context = context;
items = objects;
aq = new AQuery(context);
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.type = type;
db = new DatabaseActions();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
final NMessage msg = items.get(position);
ViewHolder holder = new ViewHolder();
int type = getItemViewType(position);
if (row == null) {
if (type == 1) {
row = inflater.inflate(R.layout.out_message, parent, false);
} else if (type == 0) {
row = inflater.inflate(R.layout.in_message, parent, false);
}
holder.avatar = (ImageView) row.findViewById(R.id.avatar);
holder.profileName = (TextView) row.findViewById(R.id.profile_name);
holder.text = (TextView) row.findViewById(R.id.msg_body);
holder.image = (ImageView) row.findViewById(R.id.image_message);
holder.video = (ImageView) row.findViewById(R.id.video_message);
holder.time = (TextView) row.findViewById(R.id.msg_date);
holder.location = (ImageView) row.findViewById(R.id.location_message);
holder.audioController = (RelativeLayout) row.findViewById(R.id.audioContainer);
row.setTag(holder);
} else {
holder = (ViewHolder) row.getTag();
}
holder.video.setVisibility(View.GONE);
holder.image.setVisibility(View.GONE);
holder.text.setVisibility(View.GONE);
holder.audioController.setVisibility(View.GONE);
holder.location.setVisibility(View.GONE);
AQuery rowAq = aq.recycle(row);
holder.text.setText(msg.getText());
holder.time.setText(Util.dateParser((Long.parseLong(msg.getTime()))));
if(!msg.isSent()) {
rowAq.id(holder.avatar).image(Util.URL_USERS_PHOTOS+msg.getPhoto_path(), false, true, 50, R.drawable.avatar_profile);
holder.profileName.setText(msg.getName());
} else {
rowAq.id(holder.avatar).image(myProfile.getFullPhotoPath(), false, true, 50, R.drawable.avatar_profile);
holder.profileName.setText("you");
}
switch (msg.getType()){
case NMessage.TEXT:
holder.text.setVisibility(View.VISIBLE);
break;
case NMessage.IMAGE:
rowAq.id(holder.image).image(msg.getText(), false, true, 100, R.drawable.ic_photo).visible();
break;
case NMessage.VIDEO:
String url = msg.getText().replace(msg.getText().substring(msg.getText().lastIndexOf(".")), ".jpg");
rowAq.id(holder.video).image(url, false, true, 100, R.drawable.ic_video).visible();
break;
case NMessage.LOCATION:
holder.location.setVisibility(View.VISIBLE);
break;
case NMessage.AUDIO:
holder.audioController.setVisibility(View.VISIBLE);
break;
}
return row;
}
#Override
public int getViewTypeCount() {
return 2;
}
#Override
public int getItemViewType(int position) {
NMessage message = items.get(position);
if (message.isSent()) {
return 1;
} else
return 0;
}
private class ViewHolder {
MediaController controller;
RelativeLayout audioController;
ImageView avatar,
image,
video,
location;
TextView text;
TextView time;
TextView profileName;
}
}
The problem is that some views are not shown in the right place. when i scroll the listview and scroll back they are arranged properly.
This is before i scroll. (when the listview is first populated)
This is after i scroll and scroll back. the imageview is gone and the right type (text) is shown.
I searched everywhere but cannot seem to find the answer even in AQuery's wiki page.
As the this blog post explains, Android does not actually guarantee that getView will receive the correct type of view.
Related
public class ListAdapter extends ArrayAdapter<ListItem> {
private ArrayList<ListItem> listItems;
private Context context;
private boolean[] check = new boolean[10];
private boolean checked;/////STRANGE!!
public ListAdapter(Context context, int textViewResourceId, ArrayList<ListItem> listItems) {
super(context, textViewResourceId, listItems);
this.listItems = listItems;
this.context = context;
}
#Override
public int getViewTypeCount() {
return 2;
}
#Override
public int getItemViewType(int position) {
if(position > 0) return 1;
else return 0;
}
#Override
#SuppressWarnings("deprecation")
public View getView(final int position, View convertView, ViewGroup parent) {
Log.i("EXPAND","in getView : "+position);
int viewType =this.getItemViewType(position);
ListViewHolder holder = null;
ListItem listItem = listItems.get(position);
switch(viewType){
case 0:
if(convertView == null){
Log.i("EXPAND","null");
LinearLayout textViewWrap;
LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
TextView text;
convertView = vi.inflate(R.layout.setting_list_item, null);
textViewWrap = (LinearLayout) convertView.findViewById(R.id.set_pull);
text = (TextView) convertView.findViewById(R.id.just_setting);
holder = new ListViewHolder(text);
// setViewWrap IS REQUIRED
holder.setViewWrap(textViewWrap);
//
}
else{
holder = (ListViewHolder) convertView.getTag();
}
holder.getViewWrap().setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT, listItem.getCurrentHeight()));
holder.getTextView().setText(listItem.getText());
holder.getTextView().setCompoundDrawablesWithIntrinsicBounds(listItem.getDrawable(), 0, 0, 0);
convertView.setTag(holder);
// setHolder IS REQUIRED
listItem.setHolder(holder);
//
final Button scanBtn = (Button)convertView.findViewById(R.id.ScanAll);
scanBtn.setOnClickListener(new View.OnClickListener(){
public void onClick(View view){
Log.i("EXPAND","ScanBtn clicked");
}
});
return convertView;
case 1:
if(convertView == null){
Log.i("EXPAND","null");
LinearLayout textViewWrap;
LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
TextView text;
convertView = vi.inflate(R.layout.list_item, null);
textViewWrap = (LinearLayout) convertView.findViewById(R.id.text_wrap);
text = (TextView) convertView.findViewById(R.id.text);
holder = new ListViewHolder(text);
// setViewWrap IS REQUIRED
holder.setViewWrap(textViewWrap);
//
}
else{
holder = (ListViewHolder) convertView.getTag();
}
holder.getViewWrap().setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT, listItem.getCurrentHeight()));
holder.getTextView().setText(listItem.getText());
holder.getTextView().setCompoundDrawablesWithIntrinsicBounds(listItem.getDrawable(), 0, 0, 0);
convertView.setTag(holder);
// setHolder IS REQUIRED
listItem.setHolder(holder);
//
//
final ImageButton check_box = (ImageButton) convertView.findViewById(R.id.check_button);
check_box.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// record what is selected
//.............
//change appearance
if (check[position]) {
Log.i("EXPAND","checked : "+position );
check[position] = false;
check_box.setBackgroundResource(R.drawable.empty);
} else {
Log.i("EXPAND","not checked : "+position);
check[position] = true;
check_box.setBackgroundResource(R.drawable.checked_check_box);
}
}
});
check_box.setFocusable(true);
//
return convertView;
default:
Log.i("EXPAND","serverly default!!");
}
return convertView;
}
}
The Button is working but not always working, especially for the scanBtn in type 0.
Yes the button is working but not always because you defined it only when the viewType == 0, but if it equals 1, the button onClick() won't do anything.
If you want the button to work always you have to define it again inside the case in which
viewType == 1.
I have a problem. I'm attempting to change an icon in my listview after it has been clicked. It works correctly although are not modified only the clicked icons but also those who are not displayed. For example if I click the icon in the first item of the listview, also the fifth icon changes. This behaviour is repeated for all the following items (every five items of the listview).
This is my getView method:
public class AlphabeticalAdapter extends ArrayAdapter<String>
{
int layoutResourceId;
private final Context context;
private List<String> data;
private ProgressDialog mProgressDialog;
private ImageView downloadImageButton;
public AlphabeticalAdapter(Context context, int resource, List<String> data){
super(context, resource, data);
this.layoutResourceId = resource;
this.context = context;
this.data = data;
}
public View getView(int position, View convertView, ViewGroup parent) {
// View rowView = convertView;
final ViewHolder viewHolder;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.catalogslist_single_row, parent, false);
viewHolder = new ViewHolder();
viewHolder.catlogTitle=(TextView)convertView.findViewById(R.id.txtTitle);
viewHolder.icon=(ImageView)convertView.findViewById(R.id.imageView2);
viewHolder.downloadImageButton=(ImageView)convertView.findViewById(R.id.downloadImageButton);
//downloadImageButton = (ImageView)rowView.findViewById(R.id.downloadImageButton);
viewHolder.position = position;
viewHolder.downloadImageButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
System.out.println("DOWNLOAD PRESSED");
viewHolder.downloadImageButton = (ImageView)v.findViewById(R.id.downloadImageButton);
viewHolder.downloadImageButton.setImageResource(R.drawable.icon_ok);
viewHolder.downloadImageButton.setTag("downloaded");
//rowView.setTag("downloaded");
}
});
convertView.setTag(viewHolder);
}
else{
viewHolder= (ViewHolder)convertView.getTag();
}
viewHolder.catlogTitle.setText(data.get(position));
viewHolder.catlogTitle.setTypeface(regularDin);
viewHolder.icon.setImageResource(R.drawable.cata);
if(viewHolder.downloadImageButton.getTag() == "downloaded"){
downloadImageButton = (ImageView)convertView.findViewById(R.id.downloadImageButton);
downloadImageButton.setImageResource(R.drawable.icon_ok);
}
else{
downloadImageButton = (ImageView)convertView.findViewById(R.id.downloadImageButton);
downloadImageButton.setImageResource(R.drawable.icon_download);
}
viewHolder.position = position;
return convertView;
} //close getView
...
And this is my ViewHolder class:
static class ViewHolder{
ImageView downloadImageButton;
TextView catlogTitle;
ImageView icon;
int position;
}
Change your code at below. I think you're missing that.
public class AlphabeticalAdapter extends ArrayAdapter<String> {
int layoutResourceId;
private final Context context;
private List<String> data;
private List<String> tags;
private ProgressDialog mProgressDialog;
private ImageView downloadImageButton;
public AlphabeticalAdapter(Context context, int resource, List<String> data) {
super(context, resource, data);
this.layoutResourceId = resource;
this.context = context;
this.data = data;
tags = new ArrayList<String>();
int size = data.size();
for (int i = 0; i < size; i++) {
tags.add("tag");
}
}
static class ViewHolder {
ImageView downloadImageButton;
TextView catlogTitle;
ImageView icon;
int position;
}
public View getView(final int position, View convertView, ViewGroup parent) {
// View rowView = convertView;
final ViewHolder viewHolder;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// convertView = inflater.inflate(R.layout.catalogslist_single_row,
// parent, false);
viewHolder = new ViewHolder();
viewHolder.position = position;
viewHolder.downloadImageButton
.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
System.out.println("DOWNLOAD PRESSED");
viewHolder.downloadImageButton.setTag("downloaded");
tags.add(position, "downloaded");
}
});
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.catlogTitle.setText(data.get(position));
viewHolder.catlogTitle.setTypeface(regularDin);
viewHolder.icon.setImageResource(R.drawable.cata);
if (tags.get(position) == "downloaded") {
downloadImageButton.setImageResource(R.drawable.icon_ok);
} else {
downloadImageButton.setImageResource(R.drawable.icon_download);
}
viewHolder.position = position;
return convertView;
} // close getView
}
There are as many convertViews as many row visible in the same time in your ListView (the system reuses it). So you actually have 5 convertView, and because of that you have 5 ImageView for the icons. The problem is that you use those ImageView's tag to store the "downloaded" information. That is 5 state, and that is why you see every fifth row downloaded while you scroll in the list.
I guess now you see that it won't work. You need to store the downloaded state for every item, so you have to change the underlying List<String> to List<ListItem>, where ListItem can store the downloaded state for the actual row.
After that, all you have to do is to update the convertView's ImageView (in getView()) to show the correct icon.
Change your code like this. Add null check with convertView before your try block.
final MenuItem menuItem = getItem(position);
View view = convertView;
final ViewHolder viewHolder;
if (convertView == null) {
LayoutInflater inflater;
inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.menu_item, parent, false);
viewHolder = new ViewHolder();
// viewHolder.half = (TextView) view.findViewById(R.id.half);
viewHolder.name = (TextView) view.findViewById(R.id.name);
viewHolder.description = (TextView) view.findViewById(R.id.description);
viewHolder.price = (TextView) view.findViewById(R.id.price);
viewHolder.add = (Button) view.findViewById(R.id.add);
viewHolder.selectedView = view.findViewById(R.id.selectedView);
viewHolder.remove = (Button) view.findViewById(R.id.remove);
viewHolder.total = (TextView) view.findViewById(R.id.itemTotal);
viewHolder.quantity = (TextView) view.findViewById(R.id.quantity);
view.setTag(viewHolder);
}else{
viewHolder= (ViewHolder)convertView.getTag();
}
You can try this
public class CustomArrayAdapter extends ArrayAdapter {
// declare your custom list with type;
private List<YourModelClass> allData = new ArrayList<YourModelClass>();
public CustomArrayAdapter(#NonNull Context context, List<YourModelClass> allData) {
super(context, R.layout.your_layout, allData); // add your_layout.xml
this.allData = allData;
}
class ViewHolder {
TextView name, phone; // declare your your_layout.xml view type
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ViewHolder holder = new ViewHolder();
if (convertView == null) {
convertView = inflater.inflate(R.layout.your_layout, parent, false); // inflate your_layout.xml
//initialize your your_layout.xml view
holder.name = convertView.findViewById(R.id.tv_item_name);
holder.phone = convertView.findViewById(R.id.tv_item_phone);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
//set value into your_layout.xml
holder.name.setText(allData.get(position).getName());
holder.phone.setText(allData.get(position).getNumber());
return convertView;
}
}
public class AndroidListViewActivity extends ListActivity
{
private ListView listView;
private String names[] = {
"HV CAPACITOR",
"LV CAPACITORCSS",
};
private String desc[] = {
"The Powerful Hypter Text Markup Language 5",
"Cascading Style Sheets",
};
private Integer imageid[] = {
R.drawable.hv_capacitor,
R.drawable.lv_capacitor,
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.capacitor_layout);
// storing string resources into Array
String[] product_name = getResources().getStringArray(R.array.product_name);
// Binding Array to ListAdapter
this.setListAdapter(new ArrayAdapter<String>(this, R.layout.list_item, R.id.label, product_name));
ListView lv = getListView();
// listening to single list item on click
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// selected item
String product = ((TextView) view).getText().toString();
// Launching new Activity on selecting single List Item
Intent i = new Intent(getApplicationContext(), SingleListItem.class);
// sending data to new activity
i.putExtra("product", product);
startActivity(i);
}
});
CapacitorList capacitorList = new CapacitorList(this, names, desc, imageid);
listView = (ListView) findViewById(R.id.listView);
listView.setAdapter(capacitorList);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
// Launching new Activity on selecting single List Item
Intent i = new Intent(getApplicationContext(), CapacitorList.class);
// sending data to new activity
// startActivity(i);
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Toast.makeText(getApplicationContext(), "You Clicked " + names[i], Toast.LENGTH_SHORT).show();
}
});
}
#Override
public boolean onCreateOptionsMenu (Menu menu){
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected (MenuItem item){
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
I have a list view in my screen, every list item contains 2 text views and one button.
On button click i want to take the list item selected index to get some data from a vector.
This is my List Custom Adapter.But i don't know how to do that.
private class CustomAdapter extends ArrayAdapter<ServicesItems> {
public CustomAdapter(Context context, int resource,
int textViewResourceId, List<ServicesItems> objects) {
super(context, resource, textViewResourceId, objects);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
TextView item = null;
TextView description = null;
Button subNowBtn;
ServicesItems ii = getItem(position);
if (null == convertView) {
convertView = mInflater.inflate(
R.layout.list_of_servics_item_2, null);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
}
holder = (ViewHolder) convertView.getTag();
// cat_name = holder.gettitle();
Resources resources = getResources();
ServicesItems bean1 = (ServicesItems) servicesVector
.elementAt(position);
String cat_name_str = bean1.getService_name().toString();
String descreption = bean1.getDescription().toString();
item = holder.getItem();
item.setText(bean1.getDescription());
description = holder.getDescription();
description.setText(bean1.getService_name());
subNowBtn=holder.getSubButton();
return convertView;
}
private class ViewHolder {
private View mRow;
private TextView description = null;
private TextView item = null;
private Button sub = null;
public ViewHolder(View row) {
mRow = row;
}
public TextView getDescription() {
if (null == description) {
description = (TextView) mRow
.findViewById(R.id.category_tv);
}
return description;
}
public TextView getItem() {
if (null == item) {
item = (TextView)
mRow.findViewById(R.id.descreption_tv);
}
return item;
}
public Button getSubButton(){
if(null==sub){
sub=(Button)findViewById(R.id.subscribe_now_btn);
}
return sub;
}
}
}
In your Adapter try this:
#Override
public View getView(final int position, View convertView, ViewGroup parent)
{
View row = convertView;
YourWrapper wrapper = null;
if (row == null)
{
row = inflater.inflate(R.layout.layout, parent, false);
wrapper = new YourWrapper (row);
row.setTag(wrapper);
}
else
wrapper = (YourWrapper) row.getTag();
wrapper.getButton().setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
// What you want
}
});
return row;
}
EDIT
Your wrapper class:
public class YourWrapper
{
private View base;
private Button button;
public YourWrapper(View base)
{
this.base = base;
}
public Button getButton()
{
if (button == null)
{
button = (Button) base.findViewById(R.id.your_button);
}
return (button`);
}
}
Change sub=(Button)findViewById(R.id.subscribe_now_btn); into sub=(Button) mRow.findViewById(R.id.subscribe_now_btn);
You can get the index of list-view on button click, here are two examples:--
You can write these in your onClick method of listener.
Example 1
View parentRow = (View) v.getParent();
ListView listView = (ListView) parentRow.getParent();
final int position = listView.getPositionForView(parentRow);
Example 2
Set position using setTag when creating view
mybutton.setTag(position);
Get position in the listener
int position = (Integer) view.getTag();
Hope this help :)
I am working on app which has a GridView of images but the last item in GridView is a button that loads more item into Grid. But i am facing a strange issue and that is Button shows up sometime and sometime it doesn't specially when i scroll up and down really fast on GridView. I think it's because of recycle issue but i don't know how to fix it.
Here is my code:-
public class ButtonGridAdapter extends BaseAdapter implements OnCheckedChangeListener, OnClickListener {
private ArrayList<String> thumbUrls;
private ArrayList<String> mainUrls;
private LayoutInflater layoutInflater;
private Context context;
private Intent intent;
private ArrayList<String> positions = new ArrayList<String>();
private static ArrayList<String> urlsToUpload = new ArrayList<String>();
private int width;
public ButtonGridAdapter(Context context, ArrayList<String> thumbUrls, ArrayList<String> mainUrls, String clicked)
{
this.context = context;
this.thumbUrls = thumbUrls;
this.mainUrls = mainUrls;
intent = new Intent(context, GalleryView.class);
this.layoutInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
DisplayMetrics displaymetrics = new DisplayMetrics();
((Activity) context).getWindow().getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
this.width = displaymetrics.widthPixels;
System.out.println(width+" width");
}
#Override
public int getCount() {
return thumbUrls.size()+1;
}
#Override
public Object getItem(int arg0) {
return thumbUrls.get(arg0);
}
#Override
public long getItemId(int position) {
return position;
}
public static class ViewHolder
{
ImageView mainImage;
CheckBox checkBox;
Button button;
}
public static class ButtonHolder
{
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View row = convertView;
ViewHolder holder;
if(row==null || row.getTag().equals("button"))
{
row = layoutInflater.inflate(R.layout.griditem, parent, false);
holder = new ViewHolder();
holder.mainImage = (ImageView)row.findViewById(R.id.itemgrid);
holder.checkBox = (CheckBox)row.findViewById(R.id.itemselected);
holder.button = null;
row.setTag(holder);
}
else
{
holder = (ViewHolder)row.getTag();
}
if(position==thumbUrls.size())
{
int width = row.getWidth();
int height = row.getHeight()-70;
row = layoutInflater.inflate(R.layout.mybutton, parent, false);
holder.button = (Button)row.findViewById(R.id.gridbutton);
holder.button.setText("Load More");
LayoutParams params = holder.button.getLayoutParams();
params.height = height;
params.width = width;
holder.button.requestLayout();
holder.button.setOnClickListener(this);
System.out.println("Called");
row.setTag("button");
return row;
}
else
{
setImageSize(holder.mainImage);
System.out.println(position);
holder.mainImage.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
intent.putExtra("position", position);
intent.putStringArrayListExtra("MainUrls", mainUrls);
intent.putStringArrayListExtra("Thumbnails", thumbUrls);
context.startActivity(intent);
}
});
holder.checkBox.setOnCheckedChangeListener(null);
holder.checkBox.setTag(position);
holder.checkBox.setChecked(positions.contains(thumbUrls.get(position)));
holder.checkBox.setOnCheckedChangeListener(this);
UrlImageViewHelper.setUrlDrawable(holder.mainImage, thumbUrls.get(position), R.drawable.extras_load);
return row;
}
}
private void setImageSize(ImageView imageView) {
LayoutParams params = imageView.getLayoutParams();
int leftWidth = width - 80;
params.width = leftWidth/3;
params.height = leftWidth/3;
imageView.requestLayout();
}
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked)
{
positions.add(thumbUrls.get((Integer)buttonView.getTag()));
urlsToUpload.add(mainUrls.get((Integer)buttonView.getTag()));
}
else
{
positions.remove(thumbUrls.get((Integer)buttonView.getTag()));
urlsToUpload.remove(mainUrls.get((Integer)buttonView.getTag()));
}
}
public static ArrayList<String> getUrlsToUpload()
{
return urlsToUpload;
}
#Override
public void onClick(View v) {
if(v.getId()==R.id.gridbutton)
{
InstagramImpl.getInstance().fetchMorePhotos();
}
}
}
Any help would be really really appreciate.
Thanks.
I post full getView method from my other answer. Simple you check the position first. If it's the last item (load more button) return layout immediately.
private final Media special = new Media("-1", "", "", "", "");
public MediaGridAdapter(Context context, int imageID, ArrayList<Media> array, int type, boolean isGetMore) {
list = array;
mediaType = type;
this.context = context;
if(list != null) {
list.add(special);
}
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
RelativeLayout item;
ViewHolder holder;
//this part check it's the last item. -1 is my special item id in contructor.
if(list.get(position).getId().equals("-1")) {
item = (RelativeLayout) LayoutInflater.from(context).inflate(R.layout.item_special_more, null);
item.setTag(MORE_BUTTON);
return item;
}
//
if(convertView == null || convertView.getTag().toString().equals(MORE_BUTTON)) {
Context context = parent.getContext();
item = (RelativeLayout) LayoutInflater.from(context).inflate(R.layout.item_with_icon_vertical, null);
holder = new ViewHolder();
holder.thumbnail = (ImageView) item.findViewById(R.id.iv_icon_media);
item.setTag(holder);
} else {
item = (RelativeLayout) convertView;
holder = (ViewHolder) item.getTag();
}
}
// set data.
holder.thumbnail.setBitmap(...)
return item;
Maybe you can try delete row==null and holder = (ViewHolder)row.getTag(); it's because of recycle issue,you can have a try first.But it will affect efficiency. Another thing i want to say,how do position==thumbUrls.size();? Maybe it's position==thumbUrls.size()-1;.Ok,that's my view,i help it work.
At beginning, the list shows three items and when I scroll down, it creates the fourth and fifth item, but the sixth and next ones are not being created. These views mix the information with the first five items and they are repeated until the application crash with a ClassCastException.
The reason is simple, each item has a different layout and type, and I have a different ViewHolder for each one. So as the views are not being created, the ViewHolders are the same as the first five items, and when the list reach one that has a different ViewHolder it crash (it's luck that it happens at the twelfth item). I need to discover why the items are being mixing with the first ones.
This is the code of the adapter, I think it's enough:
public class PostsListAdapter extends BaseAdapter {
private FacebookPost[] posts;
private LayoutInflater mInflater;
public PostsListAdapter (Context ctx, FacebookPost[] user_posts) {
mInflater = (LayoutInflater)ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
posts = user_posts;
}
#Override
public int getCount() {
return posts.length;
}
#Override
public Object getItem(int position) {
return posts[position];
}
#Override
public long getItemId(int position) {
return position;
}
private abstract static class ViewHolder {
TextView fromName;
TextView arrow;
TextView toName;
TextView message;
TextView attribution;
}
private static class VideoViewHolder extends ViewHolder {
TextView name;
TextView caption;
TextView description;
ImageView icon;
}
private static class PhotoViewHolder extends ViewHolder {
}
private static class LinkViewHolder extends ViewHolder {
}
private static class StatusViewHolder extends ViewHolder {
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
Log.d("POSITION",""+position);
if(convertView == null) {
switch(posts[position].getType()) {
case FacebookPost.VIDEO:
Log.d(""+position,"VIDEO");
convertView = mInflater.inflate(R.layout.post_list_item_video, parent, false);
holder = new VideoViewHolder();
holder.fromName = (TextView)convertView.findViewById(R.id.post_list_item_video_from_name);
holder.arrow = (TextView)convertView.findViewById(R.id.post_list_item_video_arrow);
holder.toName = (TextView)convertView.findViewById(R.id.post_list_item_video_to_name);
holder.message = (TextView)convertView.findViewById(R.id.post_list_item_video_message);
((VideoViewHolder)holder).name = (TextView)convertView.findViewById(R.id.post_list_item_video_name);
((VideoViewHolder)holder).caption = (TextView)convertView.findViewById(R.id.post_list_item_video_caption);
((VideoViewHolder)holder).description = (TextView)convertView.findViewById(R.id.post_list_item_video_description);
break;
case FacebookPost.LINK:
Log.d(""+position,"LINK");
convertView = mInflater.inflate(R.layout.post_list_item_link, parent, false);
holder = new LinkViewHolder();
holder.fromName = (TextView)convertView.findViewById(R.id.post_list_item_link_from_name);
holder.arrow = (TextView)convertView.findViewById(R.id.post_list_item_link_arrow);
holder.toName = (TextView)convertView.findViewById(R.id.post_list_item_link_to_name);
holder.message = (TextView)convertView.findViewById(R.id.post_list_item_link_message);
break;
case FacebookPost.STATUS:
Log.d(""+position,"STATUS");
convertView = mInflater.inflate(R.layout.post_list_item_status, parent, false);
holder = new StatusViewHolder();
holder.fromName = (TextView)convertView.findViewById(R.id.post_list_item_status_from_name);
holder.arrow = (TextView)convertView.findViewById(R.id.post_list_item_status_arrow);
holder.toName = (TextView)convertView.findViewById(R.id.post_list_item_status_to_name);
holder.message = (TextView)convertView.findViewById(R.id.post_list_item_status_message);
break;
case FacebookPost.PHOTO:
Log.d(""+position,"PHOTO");
convertView = mInflater.inflate(R.layout.post_list_item_photo, parent, false);
holder = new PhotoViewHolder();
holder.fromName = (TextView)convertView.findViewById(R.id.post_list_item_photo_from_name);
holder.arrow = (TextView)convertView.findViewById(R.id.post_list_item_photo_arrow);
holder.toName = (TextView)convertView.findViewById(R.id.post_list_item_photo_to_name);
holder.message = (TextView)convertView.findViewById(R.id.post_list_item_photo_message);
break;
default:
holder=null;
break;
}
convertView.setTag(holder);
}
else {
holder = (ViewHolder)convertView.getTag();
}
Spanned text = Html.fromHtml(posts[position].getFrom().getName());
holder.fromName.setText(text);
if(posts[position].getTo() != null)
text = Html.fromHtml(posts[position].getTo()[0].getName());
else
text=null;
if(text==null) {
holder.arrow.setVisibility(View.GONE);
holder.toName.setVisibility(View.GONE);
} else
holder.toName.setText(text);
text = Html.fromHtml(posts[position].getMessage());
holder.message.setText(text);
switch(posts[position].getType()) {
case FacebookPost.VIDEO:
text = Html.fromHtml(((FacebookVideoPost)posts[position]).getCaption());
Log.d("CAST: "+position,holder.getClass().getName());
((VideoViewHolder)holder).caption.setText(text);
text = Html.fromHtml(((FacebookVideoPost)posts[position]).getName());
((VideoViewHolder)holder).name.setText(text);
text = Html.fromHtml(((FacebookVideoPost)posts[position]).getDescription());
((VideoViewHolder)holder).description.setText(text);
break;
case FacebookPost.LINK:
break;
case FacebookPost.STATUS:
Log.d("CAST: "+position,holder.getClass().getName());
break;
case FacebookPost.PHOTO:
break;
}
return convertView;
}
}
I guess you are missing getViewTypeCount