I making a gridview that is made of a text and under it an image and everything is working fine but the problem is that when I scroll, the images gets repeated, so any tips on how I could solve this problem
here is my adapter:
public class CustomGridAdapter extends BaseAdapter {
private Context context;
private final String[] mobileValues;
public CustomGridAdapter(Context context, String[] mobileValues) {
this.context = context;
this.mobileValues = mobileValues;
}
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View gridView;
if (convertView == null) {
gridView = new View(context);
// get layout from mobile.xml
gridView = inflater.inflate(R.layout.heartless_gridview_design, null);
// set value into textview
TextView textView = (TextView) gridView
.findViewById(R.id.heartless_name);
textView.setText(mobileValues[position]);
// set image based on selected text
ImageView imageView = (ImageView) gridView
.findViewById(R.id.heartless_image);
String mobile = mobileValues[position];
if (mobile.equals("Shadow")) {
imageView.setImageResource(R.drawable.shadow);
} else if (mobile.equals("Soldier")) {
imageView.setImageResource(R.drawable.soldier);
} else if (mobile.equals("Large Body")) {
imageView.setImageResource(R.drawable.large_body);
} else if (mobile.equals("Silver Rock")) {
imageView.setImageResource(R.drawable.silver_rock);
} else if (mobile.equals("Emerald Blues")) {
imageView.setImageResource(R.drawable.emerald_blues);
} else {
}
} else {
gridView = (View) convertView;
}
return gridView;
}
#Override
public int getCount() {
return mobileValues.length;
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
}
please if you know how to fix this please tell me how.
so far I understood you should use viewholder pattern and
every time when getView method calls check if viewholder is null initialize it otherwise do nothing just return view..
http://developer.android.com/training/improving-layouts/smooth-scrolling.html#ViewHolder
and good example here - http://java.dzone.com/articles/android-listview-optimizations
Related
I am trying to get the total of numbers in an sql table,
i first connected between android and sql but i can't
sum the numbers in the table column and show them
in a textview,like i want to get the total
of numbers in a column then
display them in a text view
,can someone help me with this task?
here is the code i used for
the listview
public class MyAppAdapter extends BaseAdapter //has a class viewholder which holds
{
public class ViewHolder
{
TextView textDate;
TextView textTotal;
TextView textLastTotal;
TextView textCount;
TextView textTaxs;
}
public List<ClassListItems2> parkingList;
public Context context;
ArrayList<ClassListItems2> arraylist;
private MyAppAdapter(List<ClassListItems2> apps, Context context)
{
this.parkingList = apps;
this.context = context;
arraylist = new ArrayList<ClassListItems2>();
arraylist.addAll(parkingList);
}
#Override
public int getCount() {
return parkingList.size();
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) // inflating the layout and initializing widgets
{
View rowView = convertView;
ViewHolder viewHolder= null;
if (rowView == null)
{
LayoutInflater inflater = getLayoutInflater();
rowView = inflater.inflate(R.layout.listcontent2, parent, false);
viewHolder = new ViewHolder();
viewHolder.textDate = (TextView) rowView.findViewById(R.id.date);
viewHolder.textLastTotal = (TextView) rowView.findViewById(R.id.lasttotal);
viewHolder.textTaxs = (TextView) rowView.findViewById(R.id.date3);
viewHolder.textCount = (TextView) rowView.findViewById(R.id.InvoicescCount);
viewHolder.textTotal = (TextView) rowView.findViewById(R.id.total);
rowView.setTag(viewHolder);
}
else
{
viewHolder = (ViewHolder) convertView.getTag();
}
// here setting up names and images
viewHolder.textDate.setText(parkingList.get(position).getDate()+"");
viewHolder.textTotal.setText(parkingList.get(position).getTotal());
viewHolder.textLastTotal.setText(parkingList.get(position).getLasttotal());
viewHolder.textTaxs.setText(parkingList.get(position).getTaxs());
viewHolder.textCount.setText(parkingList.get(position).getInvoicecount());
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//What happens when you click on a place!
}
});
return rowView;
}
This Adapter is feed with a Collection (List) in his constructor.
To know total numbers, in Activity/Fragment that handle that Collection use:
parkingList.size()
To get sum:
float total;
for (ClassListItems2 actualItem : parkingList) {
total += actualItem.getTotal()
}
All of this logic must be executed in Activity/Fragment, never in Adapter because the Adapter only got presentation/visual logic.
I am trying to implement a customlistadapter for a small project of mine. I basically want ask java to use the appropriate class to inflate the view. I have here first:
public class slide {
public class video {
VideoView videoOfTheDay;
//Purpose of this constructor
public video(VideoView videoOfTheDay) {
this.videoOfTheDay = videoOfTheDay;
}
public VideoView getVideoOfTheDay() {
return videoOfTheDay;
}
}
public class blog {
ImageView imageOfTheDay;
TextView messageOfTheDay;
public blog(ImageView imageOfTheDay, TextView messageOfTheDay) {
this.imageOfTheDay = imageOfTheDay;
this.messageOfTheDay = messageOfTheDay;
}
public ImageView getImageOfTheDay() {
return imageOfTheDay;
}
public TextView getMessageOfTheDay() {
return messageOfTheDay;
}
}
public class advertisement {
ImageView ImageViewAd1;
ImageView ImageViewAd2;
public advertisement(ImageView imageViewAd1, ImageView imageViewAd2) {
this.ImageViewAd1 = imageViewAd1;
this.ImageViewAd2 = imageViewAd2;
}
public ImageView getImageViewAd1() {
return ImageViewAd1;
}
public ImageView getImageViewAd2() {
return ImageViewAd2;
}
}
}`
I have listed all the classes within a superclass slide because I wasn't able to accomplish no errors without them being grouped. From there I went to ask Java to look within itself and determine the appropriate class to use to populate the element:
class CustomListAdapter extends BaseAdapter {
private ArrayList<slide> customVariableDisplay;
private LayoutInflater layoutInflater;
public CustomListAdapter(Context context, ArrayList<slide>customVariableDisplay) {
this.customVariableDisplay = customVariableDisplay;
layoutInflater = LayoutInflater.from(context);
}
public int getCount() {
return customVariableDisplay.size();
}
public Object getItem(int position) {
return customVariableDisplay.get(position);
}
public long getItemId(int position) {
return position;
}
// If the element of the slide is a video -- then the getView will return...
if(slide==slide.video){
public View getView ( int position, View convertView, ViewGroup parent){
ViewHolder holder;
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.act_layout, null);
holder = new ViewHolder();
holder.slide.video = (VideoView) convertView.findViewById(R.id.videolayout);
}
else{
holder = (ViewHolder)convertView.getTag();
}
holder.video.setVideoResource(customVariableDisplay.get(position).getVideoOfTheDay());
}
return convertView;
}
// If the element is a 'blog' then --- then the getView will return...
else if(slide==slide.blog){
public View getView ( int position, View convertView, ViewGroup parent){
ViewHolder holder;
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.act_layout, null);
holder = new ViewHolder();
holder.slide.blog.message = (TextView) convertView.findViewById(R.id.messageInLayout);
holder.slide.blog.image = (ImageView) convertView.findViewById(R.id.imageInLayout);
convertView.setTag(holder);
}
else {
holder = (ViewHolder) convertView.getTag();
}
//Can write to getClass() for either?
//Ex: holder.(setImageResource(cVD) || setText(cVD)).getClass ??
holder.image.setImageResource(customVariableDisplay.get(position).getImageofTheDay());
holder.message.setText(customVariableDisplay.get(position).getMessageOfTheDay());
}
return convertView;
}
//Else if the element of the slide is an 'advertisement' then the getView will return...
else if (slide==slide.advertisement){
public View getView ( int position, View convertView, ViewGroup parent){
ViewHolder holder;
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.act_layout, null);
holder = new ViewHolder();
holder.slide.advertisement.imagead1 = (ImageView)convertView.findViewById(R.id.imageAdOneInAdvertisementLayout);
holder.slide.blog.image = (ImageView)convertView.findViewById(R.id.imageAdTwoInAdvertismentLayout);
convertView.setTag(holder);
}
else {
holder = (ViewHolder) convertView.getTag();
}
holder.imagead1.setImageResource(customVariableDisplay.get(position).getImageViewAd1());
holder.imagead2.setImageResource(customVariableDisplay.get(position).getImageViewAd2());
}
return convertView;
}
else{
//Throw a final View exception for unprecedented errors!!
}
}
}`
I am stuck with what to a way to ask Java what class is it inside the if statements. // If this slide comprises the class blog... etc. ANY HELP APPRECIATED! THANKS!
You can declare one variable slideType in your adapter and pass it to your adapter constructor and based on that value inflate your layout in onBindViewHolder(), onCreateViewHolder()
int slideType;
public CustomListAdapter(Context context, ArrayList<slide>customVariableDisplay, int slideType) {
this.slideType = slideType;
}
and also define three separate method in your adapter to pass your list so that you can bind your data.
Does this ListView show a mix of video, blog etc.. if yes then you need use below checking.
if(null != slide.video){
// add code for video
}
else if(null != slide.blog){
// add code for blog
}
else if (null != slide.advertisement){
// add code for advertisement
}
Also you need to set null for blog and advertisement in slide object or don't initialize them in case the item you want to show is video
I am trying to create a custom adapter for a shop element in my Android app but every time I scroll down the list the images seem to change their position, I have had a look around on here already but suggestions that I have found and tried have been to no avail.
Each item has a title, an image (being loading via an AsyncTask or retrieved from the LRUCache) and a price of the item below is the code I use to generate the adapter.
public class ShopAdapter extends BaseAdapter {
public Context context;
public ArrayList<ShopItem> shopItemList;
public ImageCache imageCache;
String imageToLoad;
Bitmap shopImage;
public ShopAdapter(Context context, ArrayList<ShopItem> shopItemList) {
this.context = context;
this.shopItemList = shopItemList;
imageCache = new ImageCache(this.context);
}
#Override
public int getCount() {
return shopItemList.size();
}
#Override
public Object getItem(int position) {
return shopItemList.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if(convertView == null){
LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.shop_list, null);
holder = new ViewHolder();
holder.title = (TextView) convertView.findViewById(R.id.textView3);
holder.image =(ImageView) convertView.findViewById(R.id.imageView);
holder.price = (TextView) convertView.findViewById(R.id.textView4);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.title.setText(shopItemList.get(position).getTitle());
shopImage = imageCache.getBitmapFromMemoryCache(shopItemList.get(position).getImage());
if(shopImage != null) {
holder.image.setImageBitmap(shopImage);
} else {
new LoadImage(context, holder.image).execute(imageToLoad);
}
holder.price.setText(shopItemList.get(position).getPrice());
return convertView;
}
static class ViewHolder {
TextView title;
ImageView image;
TextView price;
}
}
Any help would be very much appreciated!
I want to check every item which I click in GridView , after I keep hold on a picture and start onItemCheckedStateChanged.. I mean I want to change programatically every background of the each image I would check, and I don't know how...
Here is my GridViewAdapter :
public class GridViewAdapter extends BaseAdapter {
// Declare variables
ImageView image;
private Activity activity;
private String[] filepath;
private String[] filename;
private static LayoutInflater inflater = null;
public GridViewAdapter(Activity a, String[] fpath, String[] fname) {
activity = a;
filepath = fpath;
filename = fname;
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public int getCount() {
return filepath.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
View vi = convertView;
if (convertView == null)
vi = inflater.inflate(R.layout.gridview_item, null);
// Locate the TextView in gridview_item.xml
TextView text = (TextView) vi.findViewById(R.id.text);
// Locate the ImageView in gridview_item.xml
image = (ImageView) vi.findViewById(R.id.grid_image);
// Set file name to the TextView followed by the position
File file = new File(filepath[position]);
Picasso.with(activity).load(file).placeholder(R.drawable.rtrt).fit().centerCrop().into(image);
// Decode the filepath with BitmapFactory followed by the position
// Set the decoded bitmap into ImageView
// image.setImageBitmap(bmp);
return vi;
}
}
And here is the main activity onItemCheckedStateChanged :
public class MultiChoiceModeListener implements
GridView.MultiChoiceModeListener {
#Override
public void onItemCheckedStateChanged(android.view.ActionMode mode, int position, long id, boolean checked) {
selectCount = grid.getCheckedItemCount();
int checkedItemPosition = grid.getCheckedItemPosition();
switch (selectCount) {
case 1:
mode.setSubtitle("One picture selected");
break;
default:
mode.setSubtitle("" + selectCount + " pictures selected");
break;
}
}
#Override
public boolean onCreateActionMode(android.view.ActionMode mode, Menu menu) {
mode.setTitle("Select pictures");
mode.setSubtitle("One picture selected");
return true;
}
#Override
public boolean onPrepareActionMode(android.view.ActionMode mode, Menu menu) {
return true;
}
#Override
public boolean onActionItemClicked(android.view.ActionMode mode, MenuItem item) {
return true;
}
#Override
public void onDestroyActionMode(android.view.ActionMode mode) {
}
}
I'm stucked for 2 days on this issue , any help will be apreciated!!! Thanks!
Make sure for each ImageView or TextView you want to replace with different parameters you need to have their
replacement set visibility for “invisible”, so when you click on Item it would change for “visible”.
XML objects would look like this:
<ImageView
android:id="#+id/grid_image"/>
<ImageView
android:id="#+id/check_grid_image"
android:visibility="invisible"/>
GridViewAdapter:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = LayoutInflater.inflate(R.layout.gridview_item, null);
holder = new ViewHolder();
holder.image = (ImageView)convertView.findViewById(R.id.grid_image);
holder.checkImage = (ImageView)convertView.findViewById(R.id.check_grid_image);
convertView.setTag(holder);
}
GridView gridView = (GridView)parent;
if (gridView.isItemChecked(position)) {
holder.checkImage.setVisibility(View.VISIBLE);
}
else {
holder.checkImage.setVisibility(View.INVISIBLE);
}
// Picasso omitted
return convertView;
}
private static class ViewHolder {
ImageView image;
ImageView checkImage;
}
ActivityMain:
protected AdapterView.OnItemClickListener mOnItemClickListener = new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
ImageView checkImage = (ImageView)view.findViewById(R.id.check_grid_image
if (mGridView.isItemChecked(position)) {
// Action when Item checked
checkImage.setVisibility(View.VISIBLE);
}
else {
// Reverse Action
checkImage.setVisibility(View.INVISIBLE);
}
}
};
This is working in my project, but let me know if that works for you too!
I'm attempting to create a Gridview of icons with the Imageview set to one of two images like in my example below:
I'm retrieving two values from the sqlite content provider, one for the number of stamps and the other for the max number of stamps.
I use a custom adapter with a view holder pattern so I attempt to set the model onLoadFinished() in the Fragment. The model I've currently tried is an int[] with either value of 0 or 1 in the values to determine if green stamp is used or gray. This isn't working however as nothing is being displayed in the GridView.
Here's the code snippet from onLoadFinished() from the Fragment:
imageSourceModel = new int[data.getInt(data.getColumnIndex(RewardsEntry.COLUMN_REW_MAX_POINTS))];
int i = data.getInt(data.getColumnIndex(RewardsEntry.COLUMN_REW_POINTS));
for (int j = 0; j < imageSourceModel.length; j++, i--) {
if (i > 0) {
imageSourceModel[j] = 1;
} else {
imageSourceModel[j] = 0;
}
}
stampGridAdapter.setModel(imageSourceModel);
and the code from the custom Adapter:
#Override
public View getView(int i, View view, ViewGroup parent) {
ViewHolder viewHolder;
if (view == null) {
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.list_item_discover, parent, false);
viewHolder = new ViewHolder(view);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
if (model[i] > 0) {
viewHolder.stampView.setImageResource(R.drawable.ic_approved_stamp);
} else {
viewHolder.stampView.setImageResource(R.drawable.ic_approved_stamp_disabled);
}
return view;
}
And simple ViewHolder:
private class ViewHolder {
public ImageView stampView;
public ViewHolder(View view) {
stampView = (ImageView) view.findViewById(R.id.grid_stamp_image);
}
}
If I had to guess, I would say that it fails because of the creation order such that getView() is completed before onLoadFinished() can pass the model in. I'm just not sure how to work around this or what other methods I could use. Any help is appreciated.
For what you want to achieve, this seems unnecessary complicated to me, especially the double variable loop. To cut it simple I'd just do this:
in onLoadFinished()
int maxPoints = data.getInt(data.getColumnIndex(RewardsEntry.COLUMN_REW_MAX_POINTS));
int currentPoints = data.getInt(data.getColumnIndex(RewardsEntry.COLUMN_REW_POINTS));
mGridView.setAdapter(new RewardPointAdapter(getActivity(), currentPoints, maxPoints);
your adapter could look like this:
public class RewardPointAdapter extends BaseAdapter {
private LayoutInflater mLayoutInflater;
private int mMaxRewardPoints;
private int mCurrentRewardPoints;
public RewardPointAdapter(Context context, int currentRewardPoints, int maxRewardPoints) {
mLayoutInflater = LayoutInflater.from(context);
mMaxRewardPoints = maxRewardPoints;
mCurrentRewardPoints = currentRewardPoints;
}
#Override
public int getCount() {
return mMaxRewardPoints;
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
convertView = mLayoutInflater.inflate(R.layout.list_item_discover, parent, false);
viewHolder = new ViewHolder(convertView);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
if (position < mCurrentRewardPoints) {
viewHolder.stampView.setImageResource(R.drawable.ic_approved_stamp);
} else {
viewHolder.stampView.setImageResource(R.drawable.ic_approved_stamp_disabled);
}
return convertView;
}
private class ViewHolder {
public ImageView stampView;
public ViewHolder(View view) {
stampView = (ImageView) view.findViewById(R.id.grid_stamp_image);
}
}
}