So I am attempting to set a different layout resource for my first ListItem element using this code:
int type;
#Override
public int getItemViewType(int position) {
if(position==0) {
type = R.layout.queue_item_next;
} else {
type = R.layout.queue_item;
}
return type;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = (View) inflater.inflate(getItemViewType(position), parent, false);
}
This code works however with some unexpected behavior. For some reason the last element of the ListView is also being set to have this alternate layout and I have no idea why.
What could cause this to happen?
Thanks.
Issue is coming due getItemViewType() is returning value greater than number of view types. You can use bellow code working perfectly fine for me.
#Override
public int getItemViewType(int position) {
if(position==0) {
return 0;
}
return 1;
}
#Override
public int getViewTypeCount() {
return 2;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
int type = getItemViewType(position);
if(type == 0)
convertView = (View) inflater.inflate(R.layout.first_layout, parent, false);
else
convertView = (View) inflater.inflate(R.layout.second_layout, parent, false);
}
}
Note : If only first view is different then best option is to use headerView using function listview.addHeaderView() function using this link
because you are using if(convertView == null) {}
that means if previous view is available in memory use that one else create a new one. So, sometimes on scroll fast/slow depends on resources available of phone it varies.
to solve this problem dont check if(convertView == null)
use like this
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = (View) inflater.inflate(getItemViewType(position), parent, false);
}
Related
I am just adapting my custom adapter code with ViewHolder so that i can optimize my list view with a recycler, but i am not sure if i do it right.
My view holder class:
public class ViewHolderTask {
int positionHolder;
TextView nameHolder;
TextView timeHolder;
TextView sessionHolder;
TextView dateHolder;
FloatingActionButton mFabTaskHolder;
public ViewHolderTask(View v, int position) {
this.positionHolder = position;
this.nameHolder = v.findViewById(R.id.taskNameText);
this.timeHolder = v.findViewById(R.id.timeTextView);
this.sessionHolder = v.findViewById(R.id.textViewSession);
this.dateHolder = v.findViewById(R.id.dateTextView);
this.mFabTaskHolder = v.findViewById(R.id.myFabTask);
}
My custom adapter class:
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
ViewHolderTask holder;
if(convertView == null){
LayoutInflater inflater = (LayoutInflater) context.getSystemService(
Context.LAYOUT_INFLATER_SERVICE );
convertView = inflater.inflate(R.layout.task_row, parent, false);
holder = new ViewHolderTask(convertView, position);
convertView.setTag(holder);
}else{
holder = (ViewHolderTask) convertView.getTag();
}
Task task = taskArrayList.get(position);
//set the configurations
holder.getTimeHolder().setText(getTimeString(task.getTime()));
holder.getNameHolder().setText(task.getName());
holder.getDateHolder().setText(getDateString(task.getDate()));
holder.getSessionHolder().setText(getSessionString(task.getSession()));
//Set the FAB listener
addFabListener(holder.getmFabTaskHolder(), position);
//set the clicked background
if(TaskActivity.getIsClicked() && TaskActivity.getPositionClicked()-1 == position){
convertView.setBackgroundResource(R.color.backgroundSelectedItem);
}
return convertView;
}
Do I use it right?
Seems to be fine for me other than this portion of the code
//set the clicked background
if(TaskActivity.getIsClicked() && TaskActivity.getPositionClicked()-1 == position){
convertView.setBackgroundResource(R.color.backgroundSelectedItem);
}
You might need to reset the background resource back to default for the item which is not clicked. maybe you have to add "else" part to the "if"
So today I created Expandable List View, everything went well without any error, excepts this in Adapter.java
I'm getting error: Operator '==' cannot be applied to 'android:view.View', 'int' in the if loop just below String title line.
Adapter.java
#Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
String title = (String)this.getGroup(groupPosition);
if(convertView == 0){
LayoutInflater layoutInflater = (LayoutInflater)this.ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.parent_531_layout, null);
}
TextView textView = (TextView) convertView.findViewById(R.id.heading_item);
textView.setTypeface(null, Typeface.BOLD);
textView.setText(title);
return convertView;
}
#Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
String title = (String)this.getChild(groupPosition, childPosition);
if (convertView == 0){
LayoutInflater layoutInflater = (LayoutInflater)this.ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.child_531_layout, null);
}
TextView textView = (TextView) convertView.findViewById(R.id.child_item);
textView.setText(title);
return convertView;
}
So if anyone can correct my errors and tell me what I did wrong, I would appreciate it!
View is an object and there is not logical(possible to compare this againt an int)
try checking if is a null reference or not.
if (convertView == null){
...
}
View here is the expandable list view item, you cann't directly compare it to any integer like you have done.
If you want to check whether view is empty than check like this :
if (convertView == null){
//your code here
}
Hope it helps !
I'm basically trying to display multiple views via the same ListView adapter. However, the adapter ends up generating multiple duplicates and crashes sometimes as well with a NullPointer. My guess is that I have implemented the adapter all wrong. Here's my complete code:
The item could either be a photo or a text.
Adapter:
public class FeedAdapter extends BaseAdapter {
static private Activity activity;
private static LayoutInflater inflater = null;
ArrayList<ActivityTable> actList = new ArrayList<ActivityTable>();
Holder holder;
public FeedAdapter(Activity a, ArrayList<ActivityTable> actList) {
activity = a;
this.actList = actList;
}
public View getView(int position, View convertView, ViewGroup parent) {
Holder holder;
final ActivityTable act = actList.get(position);
inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
if (act.getType().equals("text")) {
convertView = inflater.inflate(R.layout.feed_single_text, null);
holder = new Holder();
//More code that Set the caption to the holder
convertView.setTag(holder);
}
if (act.getType().equals("photo")) {
convertView = inflater.inflate(R.layout.feed_single_picture, parent, false);
holder = new Holder();
holder.media = (ImageView) convertView.findViewById(R.id.postphoto);
//More code that Set the photo to the holder
convertView.setTag(holder);
}
} else {
holder = (Holder) convertView.getTag();
}
return convertView;
}
public static class Holder {
ImageView media;
TextView caption;
}
}
Am I inflating multiple views in the same adapter the wrong way? Can anyone point out the error?
You have 2 diffrent layout for each row so I think you should add
#Override
public int getViewTypeCount() {
return 2;
}
to your listview adapter
In your code, try to initial your LayoutInflater inside the constructor of your adapter
public FeedAdapter(Activity a, ArrayList<ActivityTable> actList) {
...
inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
And also you should optimize your ListView performance
Here is my experience
It is good to have these 3 in place.
#Override
public int getCount() {
return actList().size();
}
#Override
public Object getItem(int position) {
return actList().get(position);
}
#Override
public long getItemId(int position) {
return position;
}
Here is the important part,
first you have to tell the adapter how many type,
and then you have to tell the adapter how to determine the type.
Here I tell type View Type = 2
#Override
public int getViewTypeCount() {
return 2;
}
and Here I tell the adapter How I put the type number into the array
I use setType = 0 || set Type = 1
personal preference here: I like to use int instead of String
#Override
public int getItemViewType(int position) {
return act.get(position).getType();
}
and then later at the getView
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
int listViewItemType = getItemViewType(position);
if (v == null) {
..whatevever you doing to make v not null
}
if (listViewItemType == 0) {
//Do something
}else if(listViewItemType == 1){
// Do something different
}
return v;
}
Yes you will get duplicate Item, Because Convertview is reusing. Once convertview is created that view using if you scroll.
So better use single layout and with both Image and text. Based type hide any one.
xml file
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageView
android:id="#+id/ImgFeed"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/txtCaption"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
try this you are using ImageView insted of TextView
public View getView(int position, View convertView, ViewGroup parent) {
Holder holder;
final ActivityTable act = actList.get(position);
inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = inflater.inflate(R.layout.feed_layout, null);
holder = new Holder();
holder.caption = (TextView) convertView.findViewById(R.id.txtCaption);
holder.media = (ImageView) convertView.findViewById(R.id.ImgFeed);
if (act.getType().equals("text")) {
holder.media.setVisibility(View.GONE)
}
else if (act.getType().equals("photo")) {
holder.caption.setVisibility(View.GONE)
}
convertView.setTag(holder);
} else {
holder = (Holder) convertView.getTag();
}
return convertView;
}
I am a beginner. And I've tried a lot but I don't know how I can do this:
I have an ArrayAdapter. That displays all items and if position == 3 it should display also a label.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView;
if (position == 3){
rowView = inflater.inflate(R.layout.event_date, parent, false);
// set text of label ...
// now I want to display also the normal item
} else {
rowView = inflater.inflate(R.layout.events_list, parent, false);
// set text of item ...
}
return rowView;
}
It displays the label but I don't know how I can also show the normal item if it shows the label. How can I do this?
Try using a new layout which would contains both the event_date and events_lists
Something like this:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView;
if (position == 3){
rowView = inflater.inflate(R.layout.event_date_plus_events_list, parent, false);
// set text of label ...
} else {
rowView = inflater.inflate(R.layout.events_list, parent, false);
}
// set text of item ...
return rowView;
}
I have a gridview in Android which is populated by a custom view which inherits from imagebuttons.
What I would like to do is modify the size of the imagebuttons inside the gridview as well as their padding between cells.
Here is my getView() code. I've tried using layouts but can't because I don't have access to the parent view.
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (image == null)
image = BitmapFactory.decodeResource(context.getResources(), R.drawable.dollar);
ExpenseIcon ic = new ExpenseIcon(context);
ic.setImageBitmap(image);
return ic;
}
How do I do that?
You can set the with with setColumnWidth(int) or set the column count by calling setNumColumns(int) depending on what you extactly trying. By the way you can also set that values by xml (android:columnWidth and android:numColumns).
For the spacing you can use android:horizontalSpacing or setHorizontalSpacing(int) and android:verticalSpacing or setVerticalSpacing(int).
For controling the highe you need to change your getView function:
public YourConstructor() {
// inflater should be a private member variable
inflater = (LayoutInflater)context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// other code...
}
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null) {
// create new one and put it into convertView. e.g.:
convertView = new ExpenseIcon(context);
AbsListView.LayoutParams lp = new AbsListView.LayoutParams(HEIGHT,WIDTH);
convertView.setLayoutParams(lp);
}
// set the image to the currient convertView. e.g.:
((ExpenseIcon)convertView).setImageBitmap(image);
return convertView;
}
Create an XML and inflate.I gave sample to use in getview...Set imagesize in the layout..
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.grid_item, null);
holder = new ViewHolder();
holder.image = (ImageView) convertView.findViewById(R.id.grid_item_image);
convertView.setTag(holder);
}else {
holder = (ViewHolder) convertView.getTag();
}
holder.image.setImageResource(list.get(position).getIconid());
return convertView;
}
static class ViewHolder {
ImageView image;
}