Link : ListView MyExample
So I followed the tutorial link above to add subitem using :
static final ArrayList<HashMap<String,String>> list = new ArrayList<HashMap<String,String>>();
to add String for subitem.
Now, I wanted to add a boolean checkbox to the existing String, I use
static final ArrayList<HashMap<String,Boolean>> DAMN=new ArrayList<HashMap<String,Boolean>>();
Example of my private void listViewItem():
private void listViewItem(){
HashMap<String,String> hash=new HashMap<String, String>();
hash.put("Student_name","Joshua");
hash.put("Student_ID","111111464");
list.add(hash);
HashMap<String,Boolean>boo=new HashMap<String,Boolean>();
boo.put("attend",true);
DAMN.add(boo);'
On my onCreate, I include both SimpleAdapter for adapter ( String,String) and (String, Boolean)
SimpleAdapter adapter=new SimpleAdapter(
this,OMG,R.layout.tolist_row,
new String[]{"Student_name","Student_ID"},
new int[] {R.id.StudenName,R.id.studentID});
SimpleAdapter adapter1=new SimpleAdapter(this,DAMN,R.layout.tolist_row1,
new String[] {"attend"},
new int[] {R.id.attend});
listViewItem();
setListAdapter(adapter);
setListAdapter(adapter1);
The problem I can only get is my checkbox checked or unchecked but not the ID and name.
Unless I comment
//setListAdapter(adapter1) only I can get my Student_name and Student_name but without the checkbox ticked.
How do I have both result ?
I cannot give you the whole code but for a start, do something like this:
First create DataHolder for your data i.e: Strings and Booeleans etc. idea if to use a composite custom object as data holder instead of raw Strings and booleans.
public class DataHolder{
private String studentNname;
private Boolean attended;
//add getters and setters etc.
}
Now implement your adapter like this.
public class MyCustomAdapter extends BaseAdapter{
//populate this data using constructor or a setter or any other way
private List<DataHolder> data;
private LayoutInflater inflater = ....
//get the inflater form the fragment or the activity which ever you are using;
//implement overridden and abstract methods
//for counts of items return the size of HashMap
#Override
public View getView(int position, View convertView, ViewGroup parent){
if (convertView == null){
convertView = inflater.inflate(R.layout.<your list item layout xml file>, null);
}
DataHolder dataHolder = this.getItem(position);
//now you have the convertView (your list item view)
//and the data to be show in that view (dataHolder object)
//populate the convertView with the data from the dataHolder
return convertView;
}
}
Finally create an instance of this adapter, provide it the data i.e: List and pass this instance to setAdapter of listView.
Related
I need my application to apply a strike through to the contents of each item in my ListView based on whether or not the content of each item is marked as checked off or not in my SQLite database. Right now I obtain the text for each item in the list view from a database table, store it in a List, pass that into a ArrayAdapter, and then use that to set my ListView adapter. This is my code:
private ListView taskList = (ListView) view.findViewById(R.id.task_list);
// Get text for each TextView from database
db.getWritableDatabase();
tasks = db.readTasks((int) listId);
// Set up adapter for ListView
adapter = new ArrayAdapter<String>(
view.getContext(),
android.R.layout.simple_expandable_list_item_1,
tasks);
taskList.setAdapter(adapter);
My thought was to iterate through each item in the ListView after it has been set and check to see if the corresponding record in the database had it marked as checked or not, and then act accordingly on the item. I don't know how to iterate over the contents of a ListView however, nor am I certain this is the best way to do this. Does anyone know how to iterate over the contents of a ListView or is there an entirely better way to do this?
Firstly define a Task object with useful properties:
class Task {
public boolean isComplete() {...};
#override String toString() {...};
}
Then make your db method return a list of such objects:
ArrayList<Task> tasks = db.readTasks((int) listId);
Finally, subclass the ArrayAdapter:
private static class TaskAdapter extends ArrayAdapter<Task> {
private ArrayList<Task> mTasks;
TaskAdapter (Context c, ArrayList<Task> list) {
super(c, android.R.layout.simple_spinner_item, list);
mTasks = list;
}
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
View v = super.getView(position, convertView, parent);
TextView txt = v.findViewById(android.R.id.text1);
int flags = txt.getPaintFlags();
if (mList.get(position).isComplete()) {
flags = flags | Paint.STRIKE_THRU_TEXT_FLAG;
} else {
flags = flags & ~Paint.STRIKE_THRU_TEXT_FLAG;
}
txt.setPaintFlags(flags);
}
}
You can also do a lot more when you subclass the adapter: eg. create your own view layout (eg. if you wanted a 'tick' graphic instead of a strikethough).
Google for examples of this kind of thing. There are many.
I try to implement a ListView with specific icon, title and subtitle at each item.
The data of all items is in an ArrayList of objects from following class:
class ItemObject{
String title="";
String subTitle="";
String unit="";
int icon;
int quantity;
int parentID;
int orderInList;
}
ArrayList<ItemObject> listViewData;
Here is the code I used first:
class ExtendedArrayAdapter<String> extends ArrayAdapter<String>{
private Context context;
private String[] items;
public ExtendedArrayAdapter(Context context, String[] items){
super(context,-1,items);
this.context = context;
this.items=items;
}
#Override
public View getView(int position, View convertView, ViewGroup parent){
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View itemView = inflater.inflate(R.layout.lv_item_bg,parent,false);
TextView itemTitle = (TextView)itemView.findViewById(R.id.itemTitle);
TextView itemSubTitle = (TextView)itemView.findViewById(R.id.itemSubTitle);
ImageView itemIcon = (ImageView)itemView.findViewById(R.id.itemIcon);
itemTitle.setText(listViewData.get(position).title);
itemSubTitle.setText(listViewData.get(position).subTitle);
itemIcon.setBackgroundResource(listViewData.get(position).icon);
return itemView;
}
}
But the problem regarding this custom ArrayAdapter is that ExtendedArrayAdapter needs a String[] of items to get the number of ListView items.
Question:
Is it possible to change the ExtendedArrayAdapter class to get directly the length of ListView instead of String[] items?
EDIT1:
In super(), I can use only following set of parameters:
and all need Array<String> or List<String>. So I cannot use my ArrayList of objects here.
Is it possible to change the ExtendedArrayAdapter class to get
directly the length of ListView instead of String[] items?
the length of the ListView in terms of item it is handling, is given from Adapter.getCount(). The answer to your question, if I understand it correctly, is then no. The definition of your Adapter should change like
class ExtendedArrayAdapter extends ArrayAdapter<ItemObject>{
you will have to change the constructor and the type of items as well
I want to create a scrollable list of progress bars. The number of progress bars and the content of each progress bar is decided dynamic and decided at run time.
Is it possible to put create and put progress bars in a ListView? I couldn't find any relevant resources on the internet and hence wanted to confirm if this is even possible in the current android framework.
Yes it is possible, you have to create a custom listView and can add items dynamically whenever you want to add
create a layout that will contain your listView
<ListView
android:id="#+id/listView"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
create an item layout which will represent your single item of the listView and create a listViewAdapter that will assign your values each of your item of the list
public class ListAdapter extends ArrayAdapter{
private final Context context;
private int layoutResourceID;
private ArrayList<YourDataModel> objects;
public ListAdapter(Context context, int layoutResourceID, ArrayList<YourDataModel> objects) {
super(context, layoutResourceID, objects);
this.context = context;
this.layoutResourceID = layoutResourceID;
this.objects = objects;
}
#Override
public View getView(int position, final View convertView, ViewGroup parent) {
View row = convertView;
final ListHolder listHolder;
if(row == null) {
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(layoutResourceID, parent, false);
itemProgressBar = (ProgressBar) row.findViewById(R.id.item_progressbar);
row.setTag(listHolder);
} else {
listHolder = (ListHolder) row.getTag();
}
final DataCategory list = objects.get(position); // get your data object
// assign values to your items of listView
return row;
}
class ListHolder {
ProgressBar itemProgressBar;
}
}
in the above code YourDataModel your java class containing your data
and last in your main set all the things to make it work
ListAdapterHome listAdapter = new ListAdapter(YourActivity.this,
R.layout.item, ArrayListOfYourDataModel); // pass the arrayList of your dataModel there
ListView listView = (ListView) view.findViewById(R.id.listView);
listView.setAdapter(listAdapterHome);
It is possible. You would have to write your own ListAdapter (i would recommend overwriting SimpleArrayAdapter, but it depends on your Data) and overwrite the getView Method to generate Views that contain a ProgressBar.
Check this question: Custom Adapter for List View
FYI: The ListAdapter is the class that generates the Views of the ListView and assigns their values. Usually if you generate a SimpleArrayAdapter you pass the Layout you want it to create. That works if you only want to set some text in the layout. However to work with a View as specific as a ProgressBar you would have to create your own ListAdapter to handle that specific view.
I am using a custom ListView, in which I need to add a new item. Since there will be a lot of items needed to be added, I want to code it in the most efficient way so the smartphone is not loosing a lot of memory. Here is the code of my custom ListView:
class MessageActivityAdapter extends ArrayAdapter<String>
{
Context context;
String[] message;
String time;
MessageActivityAdapter(Context c, String[] message, String time)
{
super(c, R.layout.messagescreen_list_row, R.id.textView1, message);
this.context = c;
this.message = message;
this.time = time;
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View row = inflater.inflate(R.layout.messagescreen_list_row, parent, false);
TextView tvMessage = (TextView) row.findViewById(R.id.textView1);
tvMessage.setText(message[position][0]);
return row;
}
}
This is how I load the ListView on the first time:
adapter = new MessageActivityAdapter(this, values, time);
listView.setAdapter(adapter);
This is how I change the text in one of the items and update the ListView:
adapter.message[itemPos] = newItemText;
adapter.notifyDataSetChanged();
And thats how I thought I can add a new item to the ListView. Basically I copy the old array "message" and create a new array "messageNew" which has a +1 bigger size. Then I use "messageNew" as the new array in my MessageActivityAdapter and update the adapter. The problem: copying and creating a new array costs a lot of memory. Why I don't use an ArrayList? Because later I will change the array into a multidimensional array and multidimensional ArrayLists don't exist.
String[] messageNew = getNewMessageArray();
adapter.message = messageNew;
adapter.notifyDataSetChanged();
I'm also not sure if changing the "message" array and using the notifyDataSetChanged() method is the best way at all...
Situation:
I have an android app where users do certain actions and those actions should be shown in a feed like Facebook's feed. Actions are 4 types - become friends with, follow somebody, comment and rate.
What I know how to do (see example below*)
I know how to extend BaseAdapter and customize its getView method so I can create a custom list item that I can later populate a listview with. Example - a list of a user's friends having their avatars, their names and a couple of buttons for each.
What I dont know how to do and Im asking your help with
I dont know how to make the feed show different customized layouts for the last 10 actions that happened - this guy became friends with that guy, then this guy rated that guy's work, then this guy commented on that thing...
How do I implement that?
*An example of creating a custom adapterable item and then populating a list view with a bunch of them:
public class MyProfileFriendAdapter extends BaseAdapter {
private ArrayList<String> userNames = new ArrayList<String>();
private ArrayList<String> userAvatarPaths = new ArrayList<String>();
private ArrayList<Integer> userIds = new ArrayList<Integer>();
private Context context;
private LayoutInflater layoutInflater;
private ImageButton iMyFriendsFriendAvatarImage;
private TextView tvMyFriendsListFriendName;
private Button bMyFriendsMessage;
private Button bMyFriendsUnfriend;
public MyProfileFriendAdapter(Context context, ArrayList<String> userNames, ArrayList<String> userAvatarPaths, ArrayList<Integer> userIds){
this.context = context;
this.userNames = userNames;
this.userAvatarPaths = userAvatarPaths;
this.userIds = userIds;
layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return userIds.size();
}
#Override
public Object getItem(int arg0) {
return userIds.get(arg0) ;
}
#Override
public long getItemId(int position) {
return userIds.get(position);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView==null) {
convertView = layoutInflater.inflate(R.layout.item_adapterable_my_profile_friend, parent, false);
}
iMyFriendsFriendAvatarImage = (ImageButton) convertView.findViewById(R.id.iMyFriendsFriendAvatarImage);
tvMyFriendsListFriendName = (TextView) convertView.findViewById(R.id.tvMyFriendsListFriendName);
bMyFriendsMessage = (Button) convertView.findViewById(R.id.bMyFriendsMessage);
bMyFriendsUnfriend = (Button) convertView.findViewById(R.id.bMyFriendsUnfriend);
tvMyFriendsListFriendName.setText(userNames.get(position));
iMyFriendsFriendAvatarImage.setImageBitmap(BitmapFactory.decodeFile(userAvatarPaths.get(position)));
return convertView;
}
}
then in the activity that holds the list view I do as follows:
listOfFriends = (ListView) findViewById(R.id.lvMyProfileFriendsHolder);
MyProfileFriendAdapter myProfileFriendAdapter = new MyProfileFriendAdapter(this, userNames, userAvatarPaths, userIds);
listOfFriends.setAdapter(myProfileFriendAdapter);
So what do I do when I need to use various different adapterable items in the same list, according to the last actions that users did in my app?
Have a look at this:
http://www.jiahaoliuliu.com/2012/08/android-list-view-with-different-views.html
It's a siple exmaple.
For further information you can look for getViewCount & getItemViewType