i have created a custom array adapter for my list view but for some reason the data is not getting displayed in listview item. even the log cat doesnt show anything when i put log statement in getView method of the custom adapter which extends ArrayAdapter.
This is the activity that holds listview
public class booktable extends AppCompatActivity {
ListView mylv;
int[] array = new int[5];
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_booktable);
mylv = findViewById(R.id.mylv);
array = new int[]{1, 0, 0, 0, 1};
ListAdapter la = new customadapter(getApplicationContext(),R.layout.activity_booktable,array);
mylv.setAdapter(la);
}
}
this is my custom adapter
public class customadapter extends ArrayAdapter {
LayoutInflater li;
int[] table = new int[5];
public customadapter(#NonNull Context context,int resource, int [] array) {
super(context,resource);
li = LayoutInflater.from(context);
table = array;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
View v = li.inflate(R.layout.custom_row,parent);
ImageView img = v.findViewById(R.id.img);
TextView tv = v.findViewById(R.id.tv);
if(table[position]==0)
{
tv.setText("FULL");
tv.setTextColor(Color.RED);
}
if(table[position]==1)
{
tv.setText("AVAILABLE");
tv.setTextColor(Color.GREEN);
}
return v;
}
}
try to pass the parameter array or collection to ArrayAdapter constructor, Looks like this:
public customadapter(#NonNull Context context,int resource, int [] array) {
super(context, resource, array);
li = LayoutInflater.from(context);
table = array;
}
Related
I made adapter for ListView. If I fill the elements array before creating the adapter and linking it to the listView, the elements are displayed.
But if I use the updateItems () method to add items when the button is clicked, nothing happens.
Code of adapter:
public class ListAdapter extends ArrayAdapter<Lf> {
private LayoutInflater inflater;
private int layout;
private List<Lf> lfs;
public ListAdapter(Context context, int resource, List<Lf> lfs) {
super(context, resource, lfs);
this.lfs = lfs;
this.layout = resource;
this.inflater = LayoutInflater.from(context);
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if(convertView==null){
convertView = inflater.inflate(this.layout, parent, false);
viewHolder = new ViewHolder(convertView);
convertView.setTag(viewHolder);
}
else{
viewHolder = (ViewHolder) convertView.getTag();
}
Lf lf = lfs.get(position);
viewHolder.name.setText(lf.getLf());
viewHolder.freq.setText((int)lf.getFreq() + "");
return convertView;
}
public void updateItems(List<Lf> lfs) {
this.lfs.clear();
this.lfs.addAll(lfs);
this.notifyDataSetChanged();
}
private class ViewHolder {
final TextView name, freq;
ViewHolder(View view){
name = (TextView) view.findViewById(R.id.text_item_1);
freq = (TextView) view.findViewById(R.id.text_item_2);
}
}
}
Code of MainActivity:
public class MainActivity extends AppCompatActivity {
EditText editText1;
ListView listView;
ListAdapter adapter;
List<Lf> elements = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText1 = (EditText) findViewById(R.id.edit_text);
listView = (ListView) findViewById(R.id.fragment_list);
// Working... Elements print on screen
for(int i = 0; i < 10; i++) {
Lf temp = new Lf();
temp.setLf("mean");
temp.setFreq(100);
elements.add(temp);
}
adapter = new ListAdapter(this, R.layout.list_item, elements);
listView.setAdapter(adapter);
}
public void activity_button(View view) {
adapter.updateItems(elements);
}
}
If I click on the button, the existing items on the screen are cleared instead of a new one added. But in debug I see that elements normally passed to ListAdapter.
The problem is that your adapter's lfs's field and your activity's elements field both refer to the same List instance. This happens because you pass elements to the ListAdapter constructor, and then simply assign this.lfs = lfs.
So let's look at what happens when you pass elements to updateItems()...
public void updateItems(List<Lf> lfs) {
this.lfs.clear(); // this.lfs and the input lfs are the same list, so this clears both
this.lfs.addAll(lfs); // input lfs is now empty, so addAll() does nothing
this.notifyDataSetChanged();
}
Probably the best thing to do is to create a copy of the list in your adapter's constructor.
this.lfs = new ArrayList<>(lfs);
Now your adapter and activity will reference different lists, so this.lfs.clear() won't accidentally clear out the very list you're passing to it.
I have done the code but it appears the Search is not working
public class MainActivity extends AppCompatActivity implements SearchView.OnQueryTextListener {
ListView lv;
SearchView searchView;
ArrayAdapter<String> adapter;
String[] apptitle = {"†orch", "Quiz It!"};
String[] inf = {"click for info", "click for info"};
int[] img = {R.drawable.ic_launcher, R.drawable.ic_launcher};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
lv = (ListView) findViewById(R.id.idlistview);
searchView = (SearchView) findViewById(R.id.idsearch);
Adapterim adapter = new Adapterim(getApplicationContext(), apptitle, inf, img);
lv.setAdapter(adapter);
/*adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, appTitle);
lv.setAdapter(adapter);*/
searchView.setOnQueryTextListener(this);
}
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
}
// ArrayAdapter extends, Let's create class
class Adapterim extends ArrayAdapter<String> {
//For the information we need for our content
//Create array variable
int[] img = {};
String[] apptitle = {};
String[] inf = {};
//Context and layoutinflater as required
//Let's create them
Context c;
LayoutInflater inflater;
//The parameters of the generated method
public Adapterim(Context context, String[] apptitle, String[] inf, int[] img) {
//Values to be entered into the super method
//
super(context, R.layout.listview_class, apptitle);
// Equalize the parameters to the variables in this class
this.img = img;
this.apptitle = apptitle;
this.inf = inf;
this.c = context;
}
// Let's create our inner class and
// create our components
public class Viewholder {
TextView attv;
TextView inftv;
ImageView imgim;
}
//With this automatic method, each element in the array can be edited one by one
//We add data to the components in ListView
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
inflater = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.listview_class, null, true);
}
// Create an object from our class we created
final Viewholder holder = new Viewholder();
// And the components we create in our inner structure
//I sync with the components in the layout
holder.attv = (TextView) convertView.findViewById(R.id.custom_textView);
holder.inftv = (TextView) convertView.findViewById(R.id.custom_textView2);
holder.imgim = (ImageView) convertView.findViewById(R.id.custom_imageView);
//In order to assign the array elements as data for each component
//Assign position value to our arrays
//And set the values of our components
holder.imgim.setImageResource(img[position]);
holder.attv.setText(apptitle[position]);
holder.inftv.setText(inf[position]);
//It must be a return value and I will return View
return convertView;
}
}
I have a simple list view where each item is a view that has a title, from an ArrayList of strings and button, so that each entry in the ArrayList creates a new list item.
I also have another ArrayList of corresponding primary keys, which I want to use to delete specific items from an SQLite database but which isn't used in the list view(I don't want to display the ID's, but the strings that poplulate the list might not necessarily be unique so I can't use them to delete).
I have a onClick listener and method in the getView method for the list view, so that when someone clicks the delete button, I know the position in the list that the button was pressed in, so hopefully, I can then call a delete method on the database using id[position], however, I think due to the list view itself being created after the activity it's inside of, it can't resolve the id array, so I can't call delete.
public class TodayListActivity extends AppCompatActivity {
private ArrayList<String> names = new ArrayList<>();
FoodDB Db = null;
int deleteId;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_todaylist);
ListView lv = (ListView) findViewById(R.id.today_meal_list);
Bundle a = this.getIntent().getExtras();
String[] id = a.getStringArray("idArray"); //used to delete
String[] mealNames = a.getStringArray("mealNamesArray"); //displayed
Collections.addAll(names, mealNames);
//call the list adapter to create views based off the array list 'names'
lv.setAdapter(new MyListAdapter(this, R.layout.list_item, names));
}
protected class MyListAdapter extends ArrayAdapter<String> {
private int layout;
private MyListAdapter(Context context, int resource, List<String> objects) {
super(context, resource, objects);
layout = resource;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
viewHolder viewholder;
if (convertView == null) {
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(layout, parent, false);
viewholder = new viewHolder();
viewholder.title = (TextView) convertView.findViewById(R.id.report_meal_name);
viewholder.delButton = (Button) convertView.findViewById(R.id.button_delete_meal);
viewholder.delButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int position = (Integer)v.getTag();
//int deleteId derived from id[position]
deleteId = Integer.parseInt(id[position]);
idToDelete(deleteId);
//update the list view to exclude the deleted item
names.remove(position);
notifyDataSetChanged();
}
});
convertView.setTag(viewholder);
} else {
viewholder = (viewHolder) convertView.getTag();
}
//set string value for title
viewholder.title.setText(getItem(position));
viewholder.delButton.setTag(position);
return convertView;
}
}
public class viewHolder {
TextView title;
TextView delButton;
}
//delete from database
public void idToDelete(int DeleteId){
Db.deleteFoods(deleteId);
}
}
Any suggestions as to how or where to get either the position index out of the list view (to the activity, where the id array is) or get access to the id array inside the listview would be appreciated!
You can pass the id array to the MyListAdapter adapter, by changing this class' constructor to accept it as a parameter. Also, you are already passing the names list as a parameter, you should keep a reference to it so you can access it when the button is pressed.
Here is an example:
protected class MyListAdapter extends ArrayAdapter<String> {
private int layout;
private List<String> names;
private String[] ids;
private MyListAdapter(Context context, int resource, List<String> names, String[] ids) {
super(context, resource, names);
layout = resource;
this.names = names;
this.ids = ids;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
...
viewholder.delButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int deleteId = Integer.parseInt(ids[position]);// the "position" variable needs to be set to "final" in order to access it in here.
idToDelete(deleteId);
names.remove(position);
notifyDataSetChanged();
}
});
....
}
}
and here is how you can create an instance of this adapter:
lv.setAdapter(new MyListAdapter(this, R.layout.list_item, names, id));
I have an array named societies:
List<Society> societies = new ArrayList<>();
That holds the following data:
[{"society_id":1,"name":"TestName1","email":"Test#email1","description":"TestDes1"},
{"society_id":2,"name":"TestName2","email":"Test#email2","description":"TestDes2"},
{"society_id":3,"name":"TestName3","email":"Test#email3","description":"TestDes3"}}
I will be using this to populate a ListView but am having trouble writing the loop that will assign each array of values to its spot in the ListView.
I would like to find a way of pulling the values from the Array and assigning them to each list item by using a loop, can anybody help me with this?
My code (should be sufficient but if you need to see more please ask):
public class SocietySearch extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_society_search);
List<Society> societies = new ArrayList<>();
ServerRequests serverRequest1 = new ServerRequests(SocietySearch.this);
serverRequest1.GetSocietyDataAsyncTask(societies, new GetSocietyCallback() {
#Override
public void done(List<Society> societies) {
ListView lv = (ListView) findViewById(R.id.ListView);
List<ListViewItem> items = new ArrayList<>();
items.add(new ListViewItem() {{
ThumbnailResource = R.drawable.test;
Title = societies.socName;
Subtitle = societies.socDes;
}});
CustomListViewAdapter adapter = new CustomListViewAdapter(SocietySearch.this, items);
lv.setAdapter(adapter);
}
});
}
class ListViewItem {
public int ThumbnailResource;
public String Title;
public String Subtitle;
}
Adapter Class:
public class CustomListViewAdapter extends ArrayAdapter {
LayoutInflater inflater;
List<SocietySearch.ListViewItem> items;
public CustomListViewAdapter(Activity context, List<SocietySearch.ListViewItem> items) {
super(context, R.layout.item_row);
this.items = items;
this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
//Auto-generated method stub
ListViewItem item = items.get(position);
View vi = convertView;
if (convertView == null)
vi = inflater.inflate(R.layout.item_row, null);
ImageView test = (ImageView) vi.findViewById(R.id.imgThumbnail);
TextView txtTitle = (TextView) vi.findViewById(R.id.txtTitle);
TextView txtSubTitle = (TextView) vi.findViewById(R.id.txtSubTitle);
test.setImageResource(item.ThumbnailResource);
txtTitle.setText(item.Title);
txtSubTitle.setText(item.Subtitle);
return vi;
}
}
So we came to the conclusion, that we need to have the for loop to iterate through all the Society classes in the SocietySearch class:
#Override
public void done(List<Society> societies) {
ListView lv = (ListView) findViewById(R.id.ListView);
List<ListViewItem> items = new ArrayList<>();
for(Society s : societies) {
items.add(new ListViewItem() {{
ThumbnailResource = R.drawable.test;
Title = s.socName;
Subtitle = s.socDes;
}});
}
CustomListViewAdapter adapter = new CustomListViewAdapter(
SocietySearch.this, items);
lv.setAdapter(adapter);
}`
And we also had to fix the ArrayAdapter implementation:
public class CustomListViewAdapter extends ArrayAdapter {
LayoutInflater inflater;
List<SocietySearch.ListViewItem> items;
public CustomListViewAdapter(Activity context, List<SocietySearch.ListViewItem> items) {
super(context, R.layout.item_row, **items**); // the constructor
//needs the reference of the list, even though we use our variable to
//populate the rows. I guess it has to know how many elements it contains to
//iterate then through getView method, which is called for each row
this.items = items;
this.inflater = (LayoutInflater) context.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
}
Are you looking for a custom solution? So that you would bind each ListViewItem state to the corresponding column, then you have to create the custom solution like it is here. You would need to have a custom layout for each line and extend the ArrayAdapter where you bind each column for a line.
Is this what you want to know? If not, can you be more specific please.
You are creating an anonymous class and trying to assign values in it's object initializer. Object initializer doesn't have a reference to societies, that's why you are getting the compilation error. Try this instead:
class ListViewItem {
private final int ThumbnailResource;
private final String Title;
private final String Subtitle;
public ListViewItem(int thumbnail, String title, String subtitle) {
ThumbnailResource = thumbnail;
Title = title;
Subtitle = subtitle;
}
}
When adding list items:
items.add(new ListViewItem(R.drawable.test, societies.socName, societies.socDes);
I have a list that can be updated by the user, but notifyDataSetChanged() is not working on the adapter associated with the listView. I am using it in a fragment. Datbase gets updated, however the adpater doesn't. Following is my implementation:
My Main Fargment:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myArrayList = new ArrayList<myList>();
myArrayList = Database.getSharedObject(getActivity()).getMyList();
if (myArrayList != null && myArrayList.size() > 0) {
adapter = new myListAdapter(getActivity(), 0, myArrayList);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.mainfragment, container, false);
myListView = (ListView) v.findViewById(R.id.my_list_view);
myListView.setOnItemClickListener(this);
if (adapter != null) {
myListView.setAdapter(adapter);
}
return v;
}
After some navigations process List gets updated and in my onResume() method I get the updated List from database and call notifyDatasetChanged() method that does not update my view, however corresponding array from DB is updated one.
#Override
public void onResume() {
super.onResume();
myArrayList = Database.getSharedObject(getActivity()).getMyList();
adapter.setItems (myArrayList);
adapter.notifyDataSetChanged();
}
MyListAdapter
public class MyListAdapter extends ArrayAdapter<Message> {
private ArrayList<Message> myList;
/* Context */
private Context context;
public void setItems (ArrayList<Message> myList) {
this.myList = myList;
}
public MyListAdapter (Context context, int textViewResourceId, ArrayList<Message> myList) {
super(context, textViewResourceId, myList);
this.context = context;
this.myList = myList;
}
#Override
public View getView (int position, View v, ViewGroup parent) {
// Keeps reference to avoid future findViewById()
MyViewHolder viewHolder;
if (v == null) {
LayoutInflater li = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = li.inflate(R.layout.list_row, parent, false);
viewHolder = new MyViewHolder();
viewHolder.txtImage = (ImageView) v.findViewById(R.id.message_icon);
viewHolder.txtMessage = (TextView) v.findViewById(R.id.message);
viewHolder.txtDate = (TextView) v.findViewById(R.id.date);
v.setTag(viewHolder);
} else {
viewHolder = (MyViewHolder) v.getTag();
}
Message myMessage = new Message();
myMessage = myList.get(position);
if (myMessage != null) {
viewHolder.txtMessage.setText(myMessage.getText());
viewHolder.txtDate.setText(myMessage.getDate());
}
return v;
}
static class MyViewHolder {
ImageView txtImage;
TextView txtMessage;
TextView txtDate;
}
}
Any thought on what is going wrong? Why is not listview getting updated? Any helps is appreciated.
notifyDataSetChanged() won't work for you. Reasons why
Your adapter loses reference to your list.
Always creating and adding a new list to the Adapter. Do like this:
initialize the ArrayList while declaring globally.
ArrayList<MyItemType> myArrayList=new ArrayList<>(); // as a global variable
Add List to the adapter directly without checking null and empty condition. Set the adapter to the list directly(don't check for any condition)
myListView.setAdapter(adapter);
Add data to the myArrayList Every time(if your data is completely new, then you can call adapter.clear() and myArrayList.clear() before actually adding data to the list) but don't set the adapter
i.e If the new data is populated in the myArrayList, then just adapter.notifyDataSetChanged()
adapter = new myListAdapter(getActivity(), 0, myArrayList);
Remove this line
adapter.setItems (myArrayList);
Just overrige getCount method
#Override
public int getCount() {
return myArrayList.count();
}
In your setItems method try to clear the old ArrayList.
instead of this:
public void setItems(ArrayList<Message> myList) {
this.myList = myList;
}
Try this:
public void setItems(ArrayList<Message> myList) {
this.myList.clear();
this.myList.addAll(myList);
notifyDataSetChanged();
}
The problem is in the constructor of MyListAdapter
Instead of
public MyListAdapter(Context context, int textViewResourceId, ArrayList<Message> myList) {
super(context, textViewResourceId, scheduledMessageList);
this.context = context;
this.myList = myList;
}
try
public MyListAdapter(Context context, int textViewResourceId, ArrayList<Message> myList) {
super(context, textViewResourceId, myList);
this.context = context;
this.myList = myList;
}
also instead of you own Method setItems you should call adapter.clear(); followed by adapter.addAll(myArrayList);
If you can use notifyDataSetChanged() but in Adapter !
create a little method inside