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
Related
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'm pulling data and loading it into a BaseAdapter for my List View. Currently, the items in the listview are the same as the last item added, so the list looks like this:
Item 3
Item 3
Item 3
Instead of:
Item 1
Item 2
Item 3
I've checked over the data sources, and the data that's loaded from the source is unique each time. I think there's somehting wrong with my BaseAdapter, but I'm not sure what it is. Here's my BaseAdapter:
BaseAdapter.java
ArrayList<ThreadListData> myList = new ArrayList<>();
LayoutInflater inflater;
Context context;
public ThreadBaseAdapter(Context context, ArrayList<ThreadListData> myList) {
this.context = context;
inflater = LayoutInflater.from(this.context);
this.myList = myList;
}
#Override
public int getCount() {
return myList.size();
}
#Override
public ThreadListData getItem(int position) {
return myList.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = LayoutInflater.from(this.context);
convertView = inflater.inflate(R.layout.listitem_newthread, parent, false);
}
ThreadListData listData = getItem(position);
TextView name = (TextView)convertView.findViewById(R.id.name_newthread);
TextView username = (TextView)convertView.findViewById(R.id.username_newthread);
name.setText(listData.getName());
username.setText(listData.getName());
ParseImageView profile = (ParseImageView)convertView.findViewById(R.id.profilepicture);
BitmapTask task = new BitmapTask(listData.getImage());
task.execute(profile);
return convertView;
}
I'll start with my BaseAdapter, and can show more code if requested. All Help Is Appreciated!
You missed to return the position
Modifiy your getItemId as
#Override
public long getItemId(int position) {
return position;
}
There are 2 things you need to change:
1. You return wrong item position
#Override
public long getItemId(int position) {
return 0;
}
It should be
#Override
public long getItemId(int position) {
return position;
}
2. Your declared a LayoutInflater and create new instance in constructor. But in the getView(), you create another LayoutInflater. Look at updated code below
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
// LayoutInflater inflater = LayoutInflater.from(this.context);
inflater = LayoutInflater.from(this.context);
convertView = inflater.inflate(R.layout.listitem_newthread, parent, false);
}
ThreadListData listData = getItem(position);
TextView name = (TextView)convertView.findViewById(R.id.name_newthread);
TextView username = (TextView)convertView.findViewById(R.id.username_newthread);
name.setText(listData.getName());
username.setText(listData.getName());
ParseImageView profile = (ParseImageView)convertView.findViewById(R.id.profilepicture);
BitmapTask task = new BitmapTask(listData.getImage());
task.execute(profile);
return convertView;
}
in my application i have custom BaseAdapter for Spinner for insert data from List into that,
in this method i can return List as an data:
public List<String> getSmsNumberList() {
return Arrays.asList(smsNumbers.split("\\s*,\\s*"));
}
after geting successfull data from that i'm prepare to insert into Spinner:
smsNumbers = G.getInfo().getSmsNumberList();
panel_numbers = (String[]) smsNumbers.toArray(new String[smsNumbers.size()]);
SpinnerArrayAdapter dataAdapter = new SpinnerArrayAdapter(this);
spinner_panel_numbers.setAdapter(dataAdapter);
smsNumbers have some data returned by getSmsNumberList() function, now i'm using this below custom BaseAdapter for view data into Spinner :
Adapter code UPDATED
private class SpinnerArrayAdapter extends BaseAdapter {
private final LayoutInflater mInflater;
List<String> list;
public SpinnerArrayAdapter(ActivitySmsSendGroup con, List<String> list) {
mInflater = LayoutInflater.from(con);
this.list = list;
}
#Override
public int getCount() {
return list.length;
}
#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) {
final ListContent holder;
View v = convertView;
if (v == null) {
v = mInflater.inflate(R.layout.panel_number_spinner_style, null);
holder = new ListContent();
holder.name = (TextView) v.findViewById(R.id.textView1);
v.setTag(holder);
} else {
holder = (ListContent) v.getTag();
}
holder.name.setText(list[position] + "");
return v;
}
}
static class ListContent {
TextView name;
}
unfortunately my Spinner dialog dont have data and that empty
Here:
panel_numbers = (String[]) smsNumbers.toArray(new
String[smsNumbers.size()]);
Because already have List so no need to convert it to Array just add one more parameter to constructor of SpinnerArrayAdapter class :
List<String> list;
public SpinnerArrayAdapter(ActivitySmsSendGroup con,List<String> list) {
mInflater = LayoutInflater.from(con);
this.list=list;
}
Now use list instead of panel_numbers everywhere in SpinnerArrayAdapter class
Pass List from Activity in SpinnerArrayAdapter class constructor when create object:
SpinnerArrayAdapter dataAdapter = new SpinnerArrayAdapter(this,smsNumbers);
In your adapter you should add a method, and variable for your ArrayList (add your own object here)
public static ArrayList<ListObject> listItems;
public void addItems(ArrayList<ListObject> mListItems) {
listItems = new ArrayList<ListObject>();
listItems.clear();
listItems.addAll(mListItems);
notifyDataSetChanged();
}
Then in your main class call
SpinnerArrayAdapter.addItems(myList);
Note: Ensure within getView that your'e setting variables based on listItem in the class ie. title.setText(listItems.get(position).name);
Your adapter should look like this:
#Override
public View getDropDownView(int position, View convertView, ViewGroup parent){
return getCustomView(position, convertView, parent);
}
#Override
public View getView(int position, View convertView, ViewGroup parent){
return getCustomView(position, convertView, parent);
}
public View getCustomView(final int position, View convertView, ViewGroup parent){
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
View rowView = inflater.inflate(R.layout.spinner_row, parent, false);
spnItemName = (TextView) rowView.findViewById(R.id.spnItemName);
spnItemDel = (TextView) rowView.findViewById(R.id.spnItemDel);
spnItemName.setText(iName.get(position)+"");
spnItemDel.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(context, "Deleted", Toast.LENGTH_SHORT).show();
//iName[position] = null;
iName.remove(position);
notifyDataSetChanged();
}
});
return rowView;
}
For full source code please see my github project
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;
}
I have an ArrayAdapter with ArrayList filled. Each time I click on any of its item I re-fill the ArrayList and send notifyOnDataSetChange() to the adapter. But for unknown for me reason it goes out of ArrayList bounds in it's getView() method where it populates its items. I don't understand why this happens. Can you guys explain the theory of getView() invokation so I understand why this going on. Thanks in advance!
Here it is:
class MAdapter extends ArrayAdapter<String> {
public MAdapter(Context context, int textViewResourceId, List<String> objects) {
super(context, textViewResourceId, objects);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.file_explorer_row, null);
} else {
}
String txt = itemsList.get(position); // Out of bounds happens here
if (!txt.equals("")) {
TextView tt = (TextView) v.findViewById(R.id.file_explorer_tv_filename);
tt.setText(txt);
}
return v;
}
itemsList is declared in Outer Class.
change like this
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if (view == null)
{
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.file_explorer_row, parent, false);
}
Though i am not getting a clear view of what you are asking..i am assuming that , you are refilling the entire ArrayAdapter again....
So try this.........
Use removeView() on ListView before setting the adapter to it...
Eg:
ListView.removeView();
ListView.setAdapter(yourAdapter);
String txt = itemsList.get(position);
itemsList.get(position) returns a Integer Value and that you are try to store in a String..this might be the reason.
Try this code:
class MAdapter extends BaseAdapter {
List<String> objects;
Context context;
public MAdapter(Context context,List<String> objects) {
super();
this.context=context;
this.objects=objects;
}
public int getCount() {
return objects.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return 0;
}
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
Holder holder;
LayoutInflater vi;
if (v == null) {
holder=new Holder();
vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.file_explorer_row, null);
holder.tt= (TextView) v.findViewById(R.id.file_explorer_tv_filename);
v.setTag(holder);
} else {
holder = (Holder) v.getTag();
}
String txt = objects.get(position); // Out of bounds happens here
if (!txt.equals("")) {
holder.tt.setText(txt);
}
return v;
}
static class Holder{
TextView tt;
}
}