Currently my listview is working fine to return one view but I want it to
check when the currentVerse.getVerseNumber()==1 and return two different views (rows) if the condition is true. I cannot figure it out, Any help will be highly appreciated.
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);
viewHolder = new ViewHolder();
font = Typeface.createFromAsset(convertView.getContext().getAssets(), "my_font.ttf");
viewHolder.textView = (TextView) convertView.findViewById(R.id.textView_Verse);
viewHolder.nView = (TextView) convertView.findViewById(R.id.textView_verseNumber);
viewHolder.textView.setTypeface(font);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.textView.setText(currentVerse.getVerseText().toString());
viewHolder.nView.setText(currentVerse.getVerseNumber() + "");
convertView.setTag(viewHolder);
return convertView;
}
Its simple according to me ....
Create a layout with both views in the same layout which you want to show...
And suppose for condition true you want to show LinearLayout-A and for false u want to show LinearLayout-B then its simple use View.Visibility
if(true)
{
LinearLayout-B.setVisibility(View.GONE);
LinearLayout-A.setVisibility(View.VISIBLE);
}
else
{
LinearLayout-A.setVisibility(View.GONE);
LinearLayout-B.setVisibility(View.VISIBLE);
}
btw im using both because rememember listview paints everytime the view is created after its hidden so to make it easy and robust otherwise it wud just mess up alot...
Hope it helps u ...
Thanks
Related
I'm working on making a custom ArrayAdapter so that my list has the first element in a different color.
The thing is, when I execute this code in the get view method:
#Override
public View getView(int position, View convertView, ViewGroup parent){
Club club = (Club)getItem(position);
if(convertView == null){
convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_item, parent, false);
}
TextView textView = (TextView)convertView.findViewById(R.id.txtListItem);
if(position == 0 && club.getName().contains("All")){
textView.setTextColor(ContextCompat.getColor(getContext(), R.color.orange));
}
textView.setText(club.getName());
return convertView;
}
The first item is orange, yes, but the 10th one (below the screen) is also when I scroll down :( in another list with more elements than what the screen can hold, I have several that are orange.. I don't understand why, please help!
This is happening because views are recycling/reused. You are setting orange color for the first item but not setting default color for the rest. Just add an else clause to your if statement above, something like this
if(position == 0 && club.getName().contains("All")){
Log.d(ClubAdapter.class.getName(), club.getName());
textView.setTextColor(ContextCompat.getColor(getContext(), R.color.orange));
}else{
textView.setTextColor(ContextCompat.getColor(getContext(), R.color.your_default_color));
}
Most likely this happens because Android is recycling the view which was originally used for the first row. You need an else clause to set the color back to normal.
This happens because the adapter tries to reuse as many views as possible for performance improvement. That's why you should not create a view in getView, but reuse them (only create if it is null):
if(convertView == null){
convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_item, parent, false);
}
Even though you shouldn't create a new view, you have to make sure that you set the parameters that you want for each getView call (also called "binding"), so:
if(position == 0){
//set your first view color and whatever
}else{
//set your common view colors..
}
Because listview recycle views Google suggests to use the ViewHolder pattern. You should also set a default color if the cell is different. It would look something like this.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if(convertView == null){
convertView = LayoutInflater.from(context).inflate(R.layout.list_item, parent, false);
viewHolder = new ViewHolder();
viewHolder.textView = (TextView) convertView.findViewById(R.id.txtListItem);
convertView.setTag(viewHolder);
}
else {
viewHolder = (ViewHolder) convertView.getTag();
}
if(position == 0 && club.getName().contains("All")){
viewHolder.textView.setTextColor(ContextCompat.getColor(getContext(), R.color.orange));
}else{
//Set default color
}
viewHolder.textView.setText(club.getName());
return convertView;
}
static class ViewHolder {
protected TextView textView;
}
I have AudioListFile with Player Program.
When i click an item of GridView, sound will be played.!
enter image description here
Now, i wonder, How can i update ProgressBar in GridView?
I need mediaplayer.getDuration() in adapter.
please help me. thank you so much.
My adapter:
public View getView(final int position, View convertView, ViewGroup parent) {
if (convertView == null) {
// Initialize views
holder = new Holder();
convertView = inflater.inflate(R.layout.raw_audio_list_item, null);
holder.tvFileName = (TextView) convertView.findViewById(R.id.row_audio_list_item_tv_file_name);
holder.tvFileSize = (TextView) convertView.findViewById(R.id.row_audio_list_item_tv_file_size);
holder.pbPlayProgress = (ProgressBar) convertView.findViewById(R.id.audio_file_list_pb);
convertView.setTag(holder);
} else {
holder = (Holder) convertView.getTag();
}
// get the map object from list
AudioDataModel audioFileModel = audioFileList.get(position);
// set data to view
holder.tvFileName.setText(audioFileModel.getFileName());
holder.tvFileSize.setText(audioFileModel.getFileSize());
holder.pbPlayProgress.setMax(Integer.parseInt(audioFileModel.getFileDuration()));
convertView.setId(Integer.valueOf(audioFileModel.getFileId()));
return convertView;
}
actually you can easily do this but you have to use sparseIntegerHashmap to track the current progress for particular view because gridview or listview recycle the view they reuse the view for efficiency. so first check in getview method check whether this particular view are for this particular progress bar (means it not reused ) then set it's value from hashmap and if this view is newly created (no entry found in hashmap then) please apply default value for progress bar . simple you have to track individual view with progress in hashmap . current code might not be working because i am not on my workstation right now hope you will understand e.g
public View getView(final int position, View convertView, ViewGroup parent) {
if (convertView == null) {
// Initialize views
holder = new Holder();
convertView = inflater.inflate(R.layout.raw_audio_list_item, null);
holder.tvFileName = (TextView) convertView.findViewById(R.id.row_audio_list_item_tv_file_name);
holder.tvFileSize = (TextView) convertView.findViewById(R.id.row_audio_list_item_tv_file_size);
holder.pbPlayProgress = (ProgressBar) convertView.findViewById(R.id.audio_file_list_pb);
convertView.setTag(holder);
} else {
holder = (Holder) convertView.getTag();
}
// get the map object from list
AudioDataModel audioFileModel = audioFileList.get(position);
// set data to view
holder.tvFileName.setText(audioFileModel.getFileName());
holder.tvFileSize.setText(audioFileModel.getFileSize()); holder.pbPlayProgress.setMax(Integer.parseInt(audioFileModel.getFileDuration()));
convertView.setId(Integer.valueOf(audioFileModel.getFileId()));
//your unique id for compare
if(map.get(audioFileModel.getFileId())==holder.getId) {
holder.pbPlayProgress.setProgress(map.get(audioFileModel.getFileId()));
} else {
holder.pbPlayProgress.setProgress(//add default value );
// also add entry in hashmap
map.add(audioFileModel.getFileId(),default value)
}
return convertView;
}
i have a big problem with my ListViewAdapter.
My listview shows 2 entrys at the same time. Each entry should get a different picture from my server.
The first and the second entrys working fine, but if i'm scrolling down, the next entrys will have the same pictures.
My Code looks like this:
if (viewHolder.imgPic != null) {
String strUrl = mainUrl+list.get(position).getUrl();
new ImageDownload(viewHolder.imgPic).execute(strUrl);
}
I'm checking the view and just doing it, if it's null.
Can someone help me?
Thanks
from your question I can assume that you don't know about the ListView recycling mechanisem
basically, view that that not visible anymore (after user scrolled it away from sight) it been recycled to displayed new item that need to shown. that's the convertView parameter at the getView() method...
probably you are see the same image because the recycled view stays with the same image..
also there is the issue of the asynchronous task (your ImageDownload class) that can finish it execute when the original item that started the request already been recycled.
I recommend you to "dig" as dipper as you can to understand all about ListView - this is one of the most complex and important UI component. reading the post I linked you is a good start.
also this video is very important:
http://www.youtube.com/watch?v=wDBM6wVEO70
Here is my GetView:
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View view = null;
if(rowResourceId!=R.layout.search_empty_list) {
if (convertView == null) {
LayoutInflater inflator = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflator.inflate(rowResourceId, null);
final ViewHolder viewHolder = new ViewHolder();
viewHolder.textName = (TextView) view.findViewById(R.id.textView1);
viewHolder.imgPic = (ImageView) view.findViewById(R.id.imgPic);
if (viewHolder.imgPic != null) {
String strUrl = mainUrl+list.get(position).getUrl();
new ImageDownload(viewHolder.imgPic).execute(strUrl);
}
view.setTag(viewHolder);
} else {
view = convertView;
}
ViewHolder holder = (ViewHolder) view.getTag();
holder.textName.setText(list.get(position).getName());
} else {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(rowResourceId, parent, false);
TextView textView1 = (TextView) view.findViewById(R.id.textView1);
textView1.setText(list.get(0).getName());
}
return view;
}
I have a ListView that I put through a complex bit of coding. The list changes often with different types of data that require different views. On rare occasion, I'll end up with 1 view being reused by Android for a row that's supposed to look different. It seems to only happen when the data being displayed radically changes. I was hoping there was a way to programmatically wipe the ListView's memory clean. Is this possible?
Here is the beginning of my getView:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
SearchHolder holder = null;
int type = getItemViewType(position);
if (null == convertView) {
holder = new SearchHolder();
if (type == SEARCH_TYPE_FREETEXT) {
convertView = mInflater.inflate(R.layout.layout_search_item_freetext, null);
holder.txtText = (TextView) convertView.findViewById(R.id.search_itemname);
holder.vHeaderWrapper = (LinearLayout) convertView.findViewById(R.id.search_headerwrapper);
holder.txtHeader = (TextView) convertView.findViewById(R.id.search_header);
}
else {
if (items.get(position).mData == null) {
convertView = mInflater.inflate(R.layout.layout_loadmoreresults_white, null);
}
else {
convertView = mInflater.inflate(R.layout.layout_search_item, null);
holder.txtText = (TextView) convertView.findViewById(R.id.search_itemname);
holder.vHeaderWrapper = (LinearLayout) convertView.findViewById(R.id.search_headerwrapper);
holder.txtHeader = (TextView) convertView.findViewById(R.id.search_header);
}
}
convertView.setTag(holder);
}
else {
holder = (SearchHolder)convertView.getTag();
}
...
ListView does something called "recycling" when you scroll through a list, and what you will need to do is override the getView() method to update the individual listView item that is being recycled. By default android does not clear out these views. Check out the following link on ListView recycling:
http://mobile.cs.fsu.edu/the-nuance-of-android-listview-recycling-for-n00bs/
Without code it is hard to tell if you already know about this or not, but this is the cause of such problems in my experience.
If you use more than one layout for your list items then I suggest to inflate the appropriate layout from the xml every time in the getView() method.
I've a custom adapter for my ListView where I send to it a List, and if the position is in the list then the imageview (that is in the custom row) change its src to another.. Here is the GetView method:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.start_row, null); // line
// 47
holder = new ViewHolder();
holder.tv_SuraName = (TextView) convertView.findViewById(R.id.Start_Name);
holder.tv_SuraName.setTypeface(Font);
holder.tv_PageNumber = (TextView) convertView.findViewById(R.id.Start_Numbering);
holder.im_Audio = (ImageView) convertView.findViewById(R.id.Start_ImageView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.tv_SuraName.setText(SuraList_SuraNamesCode[position]);
holder.tv_PageNumber.setText(Integer.toString(PageNumber[position]));
holder.im_Audio.setOnClickListener(new imageViewClickListener(position));
if (TilawaAvailable.contains(position))
holder.im_Audio.setImageResource(R.drawable.quran_list_audioavailable);
return convertView;
}
I send a List with 1 position.If I scroll the ListView slowly, this works good and only 1 imageview gets changed as it should be. But if I scroll fast, other imagesviews that are close to the correct position also gets changed!
Can anyone tell me why?
You don't ever set the imageResource to something else if position isn't contained in your list. When the view with the custom image leaves the screen it is probably getting placed at a lower position in the list and getting reused.
Try changing this:
if (TilawaAvailable.contains(position))
holder.im_Audio.setImageResource(R.drawable.quran_list_audioavailable);
To this:
if (TilawaAvailable.contains(position))
holder.im_Audio.setImageResource(R.drawable.quran_list_audioavailable);
else
holder.im_audio.setImageResource(r.drawable.SOME_THING_ELSE);