I need to show multiple text views in only one list item and the rest of the list view items will have just one textview.
How do I achieve this? Any samples or tutorials you can point me at?
Thank you.
Make your own adapter:
BaseAdapter already provieds methods for working with different View types (different layout for list item cells) and to effektivly recycle views:
getViewTypeCount(): The count of how many different Views (layouts) are present.
getItemViewType(): Returns a integer to identify the view type of the item in the cell. Note the internally BaseAdapter implementation uses an array. Therefore your values returned here must be from 0 to n. You are not allowed to skip indexes.
public class MyAdapter extends BaseAdapter {
private final int VIEW_TYPE_NORMAL = 0;
private final int VIEW_TYPE_4_TEXTS = 1;
/**
* The inflater for
*/
protected LayoutInflater inflater;
protected Context context;
public MyAdapter(Context context) {
this.context = context;
this.inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getViewTypeCount() {
// There are two view types
return 2;
}
#Override
public int getItemViewType(int position) {
if (position == 0)
return VIEW_TYPE_4_TEXTS;
else
return VIEW_TYPE_NORMAL;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
int type = getItemViewType(position);
if (convertView == null) {
convertView = newView(type, parent);
}
bindView(position, type, convertView);
return convertView;
}
#Override
public long getItemId(int position) {
return 0; // replace it with your id, if you have stable ids in your
// adapter
}
/** Inflates the correct view accorind the view type **/
public View newView(int type, ViewGroup parent) {
if (VIEW_TYPE_4_TEXTS == type) {
View view = inflater.inflate(R.layout.your_layout_with_4_textviews,
parent, false);
view.setTag(new ViewHolder4TextViews(view)); // ViewHolder pattern
return view;
}
// Otherwise its a normal item with VIEW_TYPE_NORMAL
View view = inflater
.inflate(R.layout.your_normal_layout, parent, false);
view.setTag(new NormalViewHolder(view)); // ViewHolder pattern
return view;
}
/** Bind the data for the specified {#code position} to the {#code view}. */
public void bindView(int position, int type, View view) {
if (VIEW_TYPE_4_TEXTS == type) {
// set the 4 text view values
ViewHolder4TextViews holder = (ViewHolder4TextViews) view.getTag();
holder.textview1.setText("...");
holder.textview2.setText("...");
holder.textview3.setText("...");
holder.textview4.setText("...");
} else {
// VIEW_TYPE_NORMAL
NormalViewHolder holder = (NormalViewHolder) view.getTag();
holder.textview.setText("...");
}
}
}
Use a custom adapter for you list and edit the getView function:
public class MyListAdapter extends BaseAdapter {
[...]
#Override
public View getView(int position, View view, ViewGroup parentView) {
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if(position < 1) {
/* Inflate a layout with 4 textview */
view = inflater.inflate(R.layout.your_4_textview_layout, parentView, false);
} else {
/* Inflate a layout with 1 textview */
view = inflater.inflate(R.layout.your_1_textview_layout, parentView, false);
}
return view;
}
[...]
}
Take care about pass Context context to MyListAdapter in constructor like this answer
You can make changes in your adapter...some thing like this.
#position 1: "blank" view will be diplayed
#rest positions: "triplistrow" will bw displayed
#Override
public View getView(final int position, View convertView, final ViewGroup parent)
{
View rowView = convertView;
if(position !=1)
{
if (rowView == null)
{
LayoutInflater inflater = context.getLayoutInflater();
rowView = inflater.inflate(R.layout.triplistrow, null);
ViewHolder viewHolder = new ViewHolder();
viewHolder.no = (TextView) rowView.findViewById(R.id.TVTripNo);
viewHolder.name = (TextView) rowView.findViewById(R.id.TVTripName);
viewHolder.date = (TextView) rowView.findViewById(R.id.TVTripDate);
rowView.setTag(viewHolder);
}
}
else
{
LayoutInflater inflater = context.getLayoutInflater();
rowView = inflater.inflate(R.layout.triplistrow, null);
ViewHolder viewHolder = new ViewHolder();
rowView.setTag(viewHolder);
}
if(position!=1)
{
final ViewHolder holder = (ViewHolder) rowView.getTag();
holder.no.setText(String.valueOf(position+1));
holder.name.setText(values.get(position).name);
holder.date.setText(values.get(position).fromdate + " to " + values.get(position).tilldate);
}else
{
}
return rowView;
}
Related
I want to update (and delete) specific rows in my ListView knowing the attributes (id and name) of the object contained in the ListView. I don't know the position, therefore I can't use
View v = mListView.getChildAt()
I'm using an adapter for the List View, which is extending an ArrayAdapter of my model class.
How can I override the method getPosition ?
Here my ListViewAdapter
public class ListViewAdapter extends ArrayAdapter<ModelTimer> {
public List<ModelTimer> mListOfTimers;
private Context mContext;
public ListViewAdapter(Context context, List<ModelTimer> modelTimerList) {
super(context, R.layout.item_active_timer, modelTimerList);
this.mListOfTimers = modelTimerList;
this.mContext = context;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Get the data item for this position
ModelTimer modelTimer = getItem(position);
// Check if an existing view is being reused, otherwise inflate the view
ViewHolder holder;// view lookup cache stored in tag
if (convertView == null) {
holder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.item_active_timer, parent, false);
holder.tvTime = (TextView) convertView.findViewById(R.id.active_timer_timeLeft);
holder.tvTitle = (TextView) convertView.findViewById(R.id.active_timer_name);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
// Populate the data into the template view using the data object
holder.tvTime.setText(modelTimer.expirationTime);
holder.tvTitle.setText(modelTimer.name);
// Return the completed view to render on screen
return convertView;
}
#Override
public int getPosition(ModelTimer item) {
return super.getPosition(item);
}
// View lookup cache
public class ViewHolder {
TextView tvTitle;
TextView tvTime;
}
}
Not the best way to do it, but look this code:
#Override
public int getPosition(ModelTimer item) {
int pos = -1;
for(int i = 0; i < mListOfTimers.size(); i++ )
if(mListOfTimers.name.equals(item.name) // and check id
pos = i;
return pos;
}
Whats wrong with this adapter, when i scroll down i see repeated rows at the bottom and then when scroll up again i see also repeated rows at the top that were not exist before, and the rest of Data items does not appear
the adapter:
public class ClassesListViewAdapter extends BaseAdapter {
private Context mContext;
ArrayList<String> Data = new ArrayList<>();
public ClassesListViewAdapter(Context context, ArrayList<String> data) {
Data = data;
mContext = context;
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getCount() {
return Data.size();
}
private class ViewHolder{
TextView ClassDataTV;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = ((Activity)mContext).getLayoutInflater();
ViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.classes_list_view_item, parent, false);
holder = new ViewHolder();
holder.ClassDataTV = (TextView) convertView.findViewById(R.id.ClassDataTV);
holder.ClassDataTV.setText(Data.get(position));
convertView.setTag(holder);
}else{
holder=(ViewHolder)convertView.getTag();
}
return convertView;
}
}
and here how i use it:
ArrayList<String> v = new ArrayList<>();
v.add("AAAAAAA");
v.add("WWWWWwW");
v.add("VVVVVVV");
v.add("SSSSSSSSS");
v.add("QQQQQQQQQ");
v.add("YYYYYYYY");
v.add("TTTTTTT");
v.add("UUUUUUUUUU");
v.add("zzzzzzzzzzzz");
v.add("CCCCCCCCCC");
v.add("HHHHHHHHHHH");
v.add("IIIIIIIIII");
v.add("PPPPPPPPP");
mListView.setAdapter(new ClassesListViewAdapter(getActivity(), v));
Put following part of your code outside if-block and it will be fixed :
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = ((Activity)mContext).getLayoutInflater();
ViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.classes_list_view_item, parent, false);
holder = new ViewHolder();
holder.ClassDataTV = (TextView) convertView.findViewById(R.id.ClassDataTV);
convertView.setTag(holder);
}else{
holder=(ViewHolder)convertView.getTag();
}
// initialize your view here
holder.ClassDataTV.setText(Data.get(position));
return convertView;
}
The logic behind ViewHolder pattern tells that you should do it in this way. when you scroll some of reference will not created again and else block called so this cause your list not updated as you expected.
I want to add section headers in the list view in android like the attached image. Can some one help me with the code. I don't want to implement the side section indexer like in contacts.image
This is the custim list adapter that I have created-
public class CustomListAdapter extends BaseAdapter {
private Activity mContext;
private List<String> mList;
private LayoutInflater mLayoutInflater = null;
public CustomListAdapter(Activity context, List<String> list){
mContext = context;
mList = list;
mLayoutInflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return mList.size();
}
#Override
public Object getItem(int pos) {
return mList.get(pos);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
return super.getDropDownView(position, convertView, parent);
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ListViewHolder viewHolder;
if (convertView == null) {
LayoutInflater layoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.players_name_with_options, parent, false);
viewHolder = new ListViewHolder(convertView);
convertView.setTag(viewHolder);
} else {
viewHolder = (ListViewHolder) convertView.getTag();
}
// Setting the name of the player on the text view
viewHolder.textView.setText(mList.get(position));
return convertView;
}
// Class that contains the views as the variables
private class ListViewHolder {
TextView textView;
// Constructor of the class
public ListViewHolder(View item) {
// Initialising the text view and the spinner
textView = (TextView) item.findViewById(R.id.list_textView);
}
}
}
I am initializing this ArrayAdapter and then adding the names of the players. I want that when ever the name is added then the section header be created and the player's name should be set below the header like the image that I had attached.
There are many library available for this. Hope the below link will help you to figure out, what you need.
pinned-section-listview
Example 1
Example 2
below is my ListView adapter class i want to change color of last position value, suppose my ListView shows 6 elements and i want to change the color of 6th element how i will do that??? i want to change only color of last element text
public class CustomAlertAdapter extends BaseAdapter{
TextView titlename;
Context ctx=null;
ArrayList<String> listarray=null;
private LayoutInflater mInflater=null;
public CustomAlertAdapter(Activity activty, ArrayList<String> list)
{
this.ctx=activty;
mInflater = activty.getLayoutInflater();
this.listarray=list;
}
#Override
public int getCount() {
return listarray.size();
}
#Override
public Object getItem(int arg0) {
return null;
}
#Override
public long getItemId(int arg0) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup arg2) {
final ViewHolder holder;
if (convertView == null ) {
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.alertlistrow, null);
holder.titlename = (TextView)
convertView.findViewById(R.id.textView_titllename);
convertView.setTag(holder);
}
else {
holder = (ViewHolder) convertView.getTag();
}
String datavalue=listarray.get(position);
holder.titlename.setText(datavalue);
return convertView;
}
private static class ViewHolder {
TextView titlename;
}
}
Just change a property of the inflated view based on position in the data structure
public View getView(int position, View convertView, ViewGroup arg2) {
// inflate view
convertView = mInflater.inflate(R.layout.alertlistrow, null);
...
// modify view
if(position == listArray.size()-1){
convertView.setBackgroundColor(R.color.some_color_resource_id);
}
...
// return view
return convertView;
so long as that is completed before you return the view inside you getView function.
Worth remembering that is called for each element in the list, and the position is supplied to you.
Hope this helps
Try this inside getView(..)
if (position == listarray.size()-1) {
convertView.setBackgroundColor(Color.BLUE);
}
public View getView(int position, View convertView, ViewGroup arg2)
Here position is the position of particular item.
So check if position==total items(total number in your case could be size of arraylist)
and change color by
convertView.setBackground("Your Color here");
you could check the position and change the color accordingly. For instance:
#Override
public View getView(int position, View convertView, ViewGroup arg2) {
final ViewHolder holder;
if (convertView == null ) {
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.alertlistrow, null);
holder.titlename = (TextView)
convertView.findViewById(R.id.textView_titllename);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
String datavalue=listarray.get(position);
holder.titlename.setText(datavalue);
int color = (position == getCount() - 1) : Color.BLACK : Color.YELLOW;
holder.titlename.setTextColor(color)
return convertView;
}
I have a custom listView in which i want to inflate three different layouts.
I have seen many questions but they are all for odd and even position but in my listView the layout that should be inflated to the listView depends on other condition and its dynamic like
if (i == 0) i get the first Layout to be inflated and if (i==1) second one and so on,
The variable "i" is equal to the value I would be getting from my main Activity.
public class SocialListAdapter extends ArrayAdapter<Item> {
private Activity activity;
private List<Item> items;
private Item objBean;
private int row;
private int i;
public SocialListAdapter(Activity act, int resource, List<Item> arrayList) {
super(act, resource, arrayList);
// TODO Auto-generated constructor stub
this.activity= act;
this.items = arrayList;
this.row = resource;
}
#Override
public int getViewTypeCount() {
return 2;
}
#Override
public int getItemViewType(int position) {
return position;
}
#Override
public int getCount() {
return items.size();
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View view = convertView;
ViewHolder holder;
objBean = items.get(position);
i = objBean.getI();
if (view == null) {
LayoutInflater inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if(i == 0){
view = inflater.inflate(R.layout.list, null);
} else if (i == 1){
view = inflater.inflate(R.layout.row1, null);
}
holder = new ViewHolder();
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
I tried this code but dint work...
I was getting an error when i scroll through the listView arrayoutofbondexception
getItemViewType has to return a number from 0 to getViewTypeCount.
Try this :
public class CustomAdapter extends BaseAdapter {
private ArrayList<String> comments;
Context mContext;
public CustomAdapter(Context context, ArrayList<String> comments) {
this.mContext = context;
this.comments = comments;
}
public View getView(final int position, View convertView, ViewGroup parent){
String item = comments.get(position);
if (getItemViewType(position) == 0) {
View v = convertView;
if (v == null) {
//GET View 1
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ViewGroup viewGroup = (ViewGroup)inflater.inflate(R.layout.item_comment2, null);
v = viewGroup;
}
//Fill Data for Ist view
TextView comm = (TextView) v.findViewById(R.id.comment);
comm.setText(item);
return v;
} else if (getItemViewType(position) == 1) {
View v = convertView;
if (v == null) {
//GET View 2
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ViewGroup viewGroup = (ViewGroup)inflater.inflate(R.layout.item_comment1, null);
v = viewGroup;
}
//Fill Data for IInd view
TextView comm = (TextView) v.findViewById(R.id.comment);
comm.setText(item);
return v;
} else {
//GET View 3
View v = convertView;
if (v == null) {
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ViewGroup viewGroup = (ViewGroup)inflater.inflate(R.layout.item_comment3, null);
v = viewGroup;
}
//Fill Data for IInd view
TextView comm = (TextView) v.findViewById(R.id.comment);
comm.setText(item);
return v;
}
}
#Override
public int getCount() {
return comments.size();
}
#Override
public Object getItem(int position) {
return comments.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getViewTypeCount() {
return 2;
}
#Override
public int getItemViewType(int position) {
if(position == 0)
return 0;
else if (position == 1)
return 1;
else
return 2;
}
}
You can optimize and make your scrolling smooth by defining view holder :
Try this also
in getItemViewType you can set your condition where do you want to show which type of view.
use "if(position==0)" inside getView method
You can check the condition and inflate the layout that you want.
Here is the example. I have three category depending on it I inflate different layouts.
public class ApplicationAdapter extends BaseAdapter
{
private Context cntx;
/**
* 0 - featured 1- Top rated 2- other
*/
private int whichCategory;
/**
* Constructor
*
* #param context
* #param iwhichCategory
* 0 - featured 1- Top rated 2- other
*/
public ApplicationAdapter(Context context, int iwhichCategory)
{
cntx = context;
whichCategory = iwhichCategory;
}
#Override
public int getCount()
{
return entApplications.size();
}
#Override
public Object getItem(int position)
{
return null;
}
#Override
public long getItemId(int position)
{
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
if (convertView == null)
{
// This a new view we inflate the new layout
LayoutInflater inflater = (LayoutInflater) cntx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (whichCategory == 0)
convertView = inflater.inflate(R.layout.featured_app_grid_item, parent, false);
if (whichCategory == 1)
convertView = inflater.inflate(R.layout.other_app_grid_item, parent, false);
if (whichCategory == 2)
convertView = inflater.inflate(R.layout.other_app_grid_item1, parent, false);
}
}
}