I am trying to create my first Custom Adapter to generate a listview for my android app. I am getting my data from an Api call and then process it and store it in an arraylist:-
class Person{
String bioguide;
String image;
String lastname;
String firstname;
String district;
String state;
String party;}
public static ArrayList<Person> personData = new ArrayList<Person>();
Now in the onpostexecute section I am trying to create a listview and custom adapter to display my data as follows:-
ListView yourListView = (ListView) rootView.findViewById(R.id.state_listView);
ListAdapter customAdapter = new ArrayAdapter<Person>(ByState.this, R.layout.bystate_itemview,personData);
yourListView .setAdapter(customAdapter);
}
}
public class ListAdapter extends ArrayAdapter<Person> {
public ListAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
}
public ListAdapter(Context context, int resource, ArrayList<Person> items) {
super(context, resource, items);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi;
vi = LayoutInflater.from(getContext());
v = vi.inflate(R.layout.bystate_itemview, null);
}
Person p = getItem(position);
if (p != null) {
TextView tt1 = (TextView) v.findViewById(R.id.last_name);
TextView tt2 = (TextView) v.findViewById(R.id.first_name);
if (tt1 != null) {
tt1.setText(p.getLastname());
}
if (tt2 != null) {
tt2.setText(p.getFirstname());
}
}
return v;
}
}
}
I got the above code following some internet tutorial. The thing is I am getting an error in the line where I use the customadapter first to invoke the constructor of custom adapter. It says cannot resolve constructor. Can someone help me in understanding this. I know I have not defined the proper constructor for my case please let me know the changes. I am creating the listview inside a fragment and the fragment class name is ByState.
In second line replace
ListAdapter customAdapter = new ArrayAdapter<Person>(ByState.this, R.layout.bystate_itemview,personData);
by
ListAdapter customAdapter = new ListAdapter(ByState.this, R.layout.bystate_itemview, personData);
You create your own adapter class, but invoke standart ArrayAdapter
Related
I am creating a playlist with 2 lines of name and genre, how to I can delete it.
This is MainActivity :
String[] gene, sl;
...
adp = new Adapter(MainActivity.this, gene, sl);
lv.setAdapter(adp);
This is Adapter
public class Adapter extends ArrayAdapter<String> {
private final Activity context;
private final String[] gene;
private final String[] sl;
SharedPreferences preferences;
public Adapter(Activity context, String[] gene ,String[] sl) {
super(context, R.layout.activity_m , gene);
this.context = context;
this.gene = gene;
this.sl = sl;
}
private class ViewHolder{
TextView txtgene, txtsl;
}
#Override
public View getView(final int position, View view, ViewGroup parent) {
ViewHolder holder;
if (view == null) {
LayoutInflater inflater = context.getLayoutInflater();
view = inflater.inflate(R.layout.activity_m, null, true);
holder = new ViewHolder();
holder.txtgene = (TextView) view.findViewById(R.id.txtgene);
holder.txtsl = (TextView) view.findViewById(R.id.txtsl);
view.setTag(holder);
}else{
holder = (ViewHolder) view.getTag();
}
if (gene[position] != null) {
holder.txtgene.setText(gene[position]);
}
holder.txtsl.setText(sl[position]);
return view;
}
}
How to remove an item when you know its exact position ?
Thank !
You are using the ArrayAdapter constructor that takes an array. This in turn will create an immutable List internal to the ArrayAdapter. So, you will not be able to modify your adapter going this route.
Instead, make a new ArrayList from your array and call the ArrayAdapter constructor that takes a List.
So, change the super call in your Adapter constructor to this:
super(context, R.layout.activity_m, new ArrayList<>(Arrays.asList(gene)));
And then, when you want to remove an item given it's position, do this:
adp.remove(getItem(position));
PS: You should consider refactoring your gene and sl arrays into a class and then use it as the type of your List.
I apologize in advance if this is a duplicate. I am still new to android development and tried looking for a resolution however could not find one that works.
I am creating a to-do app and getting this error in my adapter.
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String assignment.Model.getAssignment()' on a null object reference
at assignment.Adapter.getView(Adapter.java:39)
and the line of code that it is referencing to is
assignment.setText(modelItems[position].getAssignment());
I believe that the position that I am setting it as is what is causing the error but I'm not sure how to fix it.
Here's part of the rest of my code for reference:
MainActivity.Java - onActivityResult
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
String assignmentSentBack = data.getStringExtra("editAssignment");
Integer monthSentBack = data.getIntExtra("month", 0);
Integer daySentBack = data.getIntExtra("day", 0);
modelItems = new Model[100];
ArrayList<Model> modelArrayList = new ArrayList<>(Arrays.asList(modelItems));
modelArrayList.add(new Model(assignmentSentBack, (monthSentBack + 1) + "/" + daySentBack, 0));
lv = (ListView) findViewById(R.id.listAssignment);
ListAdapter adapter = new Adapter(this, modelItems);
lv.setAdapter(adapter);
}
Second Activity - onSendActivity (Button)
public void onSendAssignment (View view) {
EditText editAssignmentET = (EditText)
findViewById(R.id.editAssignment);
String editAssignment = String.valueOf(editAssignmentET.getText());
DatePicker datePickerDP = (DatePicker)
findViewById (R.id.datePicker);
Integer month = Integer.valueOf(datePickerDP.getMonth());
Integer day = Integer.valueOf(datePickerDP.getDayOfMonth());
Intent goingBack = new Intent();
goingBack.putExtra("editAssignment", editAssignment);
goingBack.putExtra ("month", month);
goingBack.putExtra("day", day);
setResult(RESULT_OK, goingBack);
finish();
}
Adapter
public class Adapter extends ArrayAdapter {
Model[] modelItems = null;
Context context;
public Adapter(Context context, Model[] resource) {
super(context, R.layout.row, resource);
this.context = context;
this.modelItems = resource;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
convertView = inflater.inflate(R.layout.row, parent, false);
TextView assignment = (TextView) convertView.findViewById(R.id.assignment);
TextView dueDate = (TextView) convertView.findViewById(R.id.dueDate);
CheckBox cb = (CheckBox) convertView.findViewById(R.id.checkBox);
assignment.setText(modelItems[position].getAssignment());
dueDate.setText(modelItems[position].getDueDate());
if (modelItems[position].getValue() == 1)
cb.setChecked(true);
else
cb.setChecked(false);
return convertView;
}
}
Model
public class Model {
String assignment;
String dueDate;
int value;
Model (String assignment, String dueDate, int value){
this.assignment = assignment;
this.dueDate = dueDate;
this.value = value;
}
public String getAssignment(){
return this.assignment;
}
public String getDueDate(){
return this.dueDate;
}
public int getValue(){
return this.value;
}
}
Any help is appreciated. Thank you.
you should try to wrap it in an inner Holder class and define the parameters in that class
public class Adapter extends ArrayAdapter {
Model[] modelItems = null;
Context context;
public Adapter(Context context, Model[] resource) {
super(context, R.layout.row, resource);
this.context = context;
this.modelItems = resource;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
if (convertView == null) {
holder = new ViewHolder();
convertView = vi.inflate(R.layout.list_layout, null);
// Find the child views.
holder.assignment= (TextView) convertView.findViewById(R.id.txt_name);
holder.dueDate= (Button) convertView.findViewById(R.id.btn_invite);
holder.cb= (Button) convertView.findViewById(R.id.btn_track);
convertView.setTag(holder);
//....
}
// Reuse existing row view
else {
holder = (ViewHolder)convertView.getTag();
}
return convertView;
}
class ViewHolder {
TextView assignment;
TextView dueDate;
CheckBox cb;
}
}
change
public class Adapter extends ArrayAdapter {
to
public class Adapter extends ArrayAdapter<Model> {
You have created model array of size 100 here:
modelItems = new Model[100];
So, 100 models are being created but all 100 indexes have null value.
Then you have created ArrayList using that array:
ArrayList<Model> modelArrayList = new ArrayList<>(Arrays.asList(modelItems));
So again your modelArrayList has 100 null objects. Which BTW you are using no where.
You are passing modelItems into constructor of Adapter. So now since all you items are null, you are getting this exception.
Try to do something like this:
ArrayList<Model> modelArrayList = new ArrayList<>();
modelArrayList.add(new Model(assignmentSentBack, (monthSentBack + 1) + "/" + daySentBack, 0));
Similarly add more model objects like that.
Pass this modelArrayList in your adapter's constructor and use this (instead of array) to display the list.
lv = (ListView) findViewById(R.id.listAssignment);
ListAdapter adapter = new Adapter(this, modelArrayList)
And thus your adapter will be like this:
ArrayList<Model> modelArrayList;
Context context;
public Adapter(Context context, ArrayList<Model> resource) {
super(context, R.layout.row, resource);
this.context = context;
this.modelArrayList = resource;
}
I am in Android Studio trying to implement a custom ListView. I have created an xml file called "custom_layout_rachel.xml" and have put it in my "layout" folder. This file contains the code for how I want my ListView to look.
I am trying to make the list view in my page called "activity_urgent__important.xml" to look like the one in "custom_layout_rachel.xml". In this file, I have the following code:
<ListView
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:id="#+id/lvItems"
tools:listitem="#layout/custom_layout_rachel"
/>
In Android Studio, the custom layout is showing up, but when I run the app on my emulator, it is not there.
The java code for this activity, looks like:
lvItems = (ListView) findViewById(R.id.lvItems);
items = new ArrayList<String>();
itemsAdapter = new ArrayAdapter<String>(this, android.R.layout.custom_layout_rachel, items);
lvItems.setAdapter(itemsAdapter);
on the third line is where my error is.
Does anyone know why I can't do this or why I am getting an error?
Thank you!!!
New:
lvItems = (ListView) findViewById(R.id.lvItems);
items = new ArrayList<String>();
readItems();
itemsAdapter = new CustomListAdapter(this, items);
lvItems.setAdapter(itemsAdapter);
Getting an error on "Custom List Adapter(this, items)
I do not have adapter code, but I did start the following, I could implement it if it would work:
public class CustomListAdapter extends ArrayAdapter {
private Context mContext;
private int id;
private List<String> items ;
public CustomListAdapter(Context context, int textViewResourceId , List<String> list )
{
super(context, textViewResourceId, list);
mContext = context;
id = textViewResourceId;
items = list ;
}
public CustomListAdapter(Context context , List<String> list) {
super(context, items);
}
#Override
public View getView(int position, View v, ViewGroup parent)
{
View mView = v ;
if(mView == null){
LayoutInflater vi = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mView = vi.inflate(id, null);
}
TextView text = (TextView) mView.findViewById(R.id.textView);
if(items.get(position) != null )
{
text.setTextColor(Color.WHITE);
text.setText(items.get(position));
text.setBackgroundColor(Color.RED);
int color = Color.argb( 200, 255, 64, 64 );
text.setBackgroundColor( color );
}
return mView;
}
In your second CustomListAdapter constructor, initialize mContext and items since mContext will be used in inflating the view in getView() method.
public CustomListAdapter(Context context , List<String> list) {
super(context, items);
mContext = context;
items = list ;
}
If you are creating your own adpater extending String type. You don't have to pass android.R.layout.custom_layout_rachel in your third line of code.
You will be inflating your custom_layout for listview inside getView method ,within adapter.
Simply pass the context and values needed to be populated in Listview.
new ArrayAdapter<String>(this,items);
Change your adapter constructor to the same.
if it doesn't work please post the adapter code.
Update your code like this.
public class CustomListAdapter extends ArrayAdapter<String> {
private Context mContext;
private int id;
private List<String> items ;
private LayoutInflater inflater;
public CustomListAdapter(Context context,List<String> list )
{ super(context,list);
this.mContext = context;
this.items = list ;
this.inflater=LayoutInflater.from(context)
}
public int getCount()
{
items.length;
(or)
items.size();
}
#Override
public View getView(int position, View v, ViewGroup parent)
{
if(v== null){
v = this.inflater.inflate(R.layout.custom_layout_rachel, null);
}
TextView text = (TextView) v.findViewById(R.id.textView);
if(items.get(position) != null )
{
text.setTextColor(Color.WHITE);
text.setText(items.get(position));
text.setBackgroundColor(Color.RED);
int color = Color.argb( 200, 255, 64, 64 );
text.setBackgroundColor( color );
}
return v;
}
changes in your code
lvItems = (ListView) findViewById(R.id.lvItems);
items = new ArrayList<String>();
readItems();
itemsAdapter = new CustomListAdapter<String>(this, items);
lvItems.setAdapter(itemsAdapter);
How do I program my adapter in order to visualize the contents of an ArrayList in a onPostExecute inside an AsynkTask?
I have got the following class:
class PlatoCuenta{
public String id;
public String name;
public Integer served_as;
public String served;
public String price;
public String quantity;
public String title_cuenta;
}
I have got the following array list:
ArrayList<PlatoCuenta> bebidas=new ArrayList<PlatoCuenta>();
bebidas=new ArrayList<PlatoCuenta>();
JSONArray mArray = new JSONArray(jsonstr);
for(int i = 0; i < mArray.length(); ++i) {
JSONObject currentObject = mArray.getJSONObject(i);
PlatoCuenta producto= new PlatoCuenta();
SectionItem SectionCuenta = new SectionItem();
producto.id=currentObject.getString("id");
producto.served=currentObject.getString("served");
if(currentObject.getString("price").equals("None"))
producto.price="0.00";
else
producto.price=currentObject.getString("price");
producto.name= currentObject.getString("product_name");
producto.quantity=currentObject.getString("product_number");
producto.served_as = currentObject.getInt("serv_order");
if(producto.served_as==0){
SectionCuenta.title="bebidas";
producto.title_cuenta=SectionCuenta.title;
bebidas.add(producto);
}
if(producto.served_as==2){
SectionCuenta.title="entrantes";
producto.title_cuenta=SectionCuenta.title;
bebidas.add(producto);
}
}
Assume that you have ArrayList<PlatoCuenta> bebidas=new ArrayList<PlatoCuenta>();. The general steps for visualize a listview are:
Create a row layout row.xml
Create an adapter for the row
Set adapter to the listview.
Again, suppose that you already have the design of your row.xml. To create an adapter (step 2).
public class MyAdapter extends BaseAdapter {
public MySimpleArrayAdapter(Context context, ArrayList list) {
super(context, R.layout.rowlayout, values);
//....
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.row.xml, parent, false);
//continue creating your row here
return rowView;
}
}
And in onPostExecute:
MyAdapter adapter = new MyAdapter(context,bebidas);
listView.setAdapter(adapter);
Good tutorial: Custom ListView
Is there a working example out there that demonstrates how to append additional rows in ListView dynamically?
For example:
you are pulling RSS feeds from
different domains
you then display the first 10 items
in the ListView (while you have
other threads running in the
background continue pulling feeds)
you scroll and reach the bottom of
the List and click at a button to
view more items
the ListView will then get appended
with additional 10 items, which
makes 20 items now in total.
Any advice how to accomplish this?
Nicholas
To add new item to your list dynamically you have to get adapter class from your ListActivity and simply add new elements. When you add items directly to adapter, notifyDataSetChanged is called automatically for you - and the view updates itself. You can also provide your own adapter (extending ArrayAdapter) and override the constructor taking List parameter. You can use this list just as you use adapter, but in this case you have to call adapter.notifyDataSetChanged() by yourself - to refresh the view.
Please, take a look at the example below:
public class CustomList extends ListActivity {
private LayoutInflater mInflater;
private Vector<RowData> data;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mInflater = (LayoutInflater) getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
data = new Vector<RowData>();
RowData rd = new RowData("item1", "description1");
data.add(rd);
rd = new RowData("item2", "description2");
data.add(rd);
rd = new RowData("item2", "description3");
data.add(rd);
CustomAdapter adapter = new CustomAdapter(this, R.layout.custom_row,R.id.item, data);
setListAdapter(adapter);
getListView().setTextFilterEnabled(true);
}
public void onListItemClick(ListView parent, View v, int position, long id) {
CustomAdapter adapter = (CustomAdapter) parent.getAdapter();
RowData row = adapter.getItem(position);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(row.mItem);
builder.setMessage(row.mDescription + " -> " + position );
builder.setPositiveButton("ok", null);
builder.show();
}
/**
* Data type used for custom adapter. Single item of the adapter.
*/
private class RowData {
protected String mItem;
protected String mDescription;
RowData(String item, String description){
mItem = item;
mDescription = description;
}
#Override
public String toString() {
return mItem + " " + mDescription;
}
}
private class CustomAdapter extends ArrayAdapter<RowData> {
public CustomAdapter(Context context, int resource,
int textViewResourceId, List<RowData> objects) {
super(context, resource, textViewResourceId, objects);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
//widgets displayed by each item in your list
TextView item = null;
TextView description = null;
//data from your adapter
RowData rowData= getItem(position);
//we want to reuse already constructed row views...
if(null == convertView){
convertView = mInflater.inflate(R.layout.custom_row, null);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
}
//
holder = (ViewHolder) convertView.getTag();
item = holder.getItem();
item.setText(rowData.mItem);
description = holder.getDescription();
description.setText(rowData.mDescription);
return convertView;
}
}
/**
* Wrapper for row data.
*
*/
private class ViewHolder {
private View mRow;
private TextView description = null;
private TextView item = null;
public ViewHolder(View row) {
mRow = row;
}
public TextView getDescription() {
if(null == description){
description = (TextView) mRow.findViewById(R.id.description);
}
return description;
}
public TextView getItem() {
if(null == item){
item = (TextView) mRow.findViewById(R.id.item);
}
return item;
}
}
}
You can extend the example above and add "more" button - which just add new items to your adapter (or vector). Regards!