I'm trying to create a row in listview dynamically by giving external data.
Each row in a listview has a string data and a switch. String data taken from an Edittext externally.
I have a EditText field. I will input the data through this.
I have a button . When it is pressed, the EditText content should be added to a new row of the listview along with a Switch
While adding the new row , care should be taken to retain the previously added row.
I got the code skeleton from web. This code is manipulated by me for my requirement.
The following code adds the row dynamically but it is clearing the previously added row. Kindly help . Thanks
This is my MainActivity.java
public class MainActivity extends Activity {
Switch sw1;
private ListView listView1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_main);
}
public void getdata(View v) {
EditText et;
String dev_name;
et = (EditText)findViewById(R.id.editText1) ;
dev_name = et.getText().toString() ;
create(dev_name, null);
}
public void create (String str, Switch sw1) {
Items Items_data[] = new Items[]
{
new Items( str,sw1)
};
ItemsAdapter adapter = new ItemsAdapter (this,R.layout.items_row, Items_data);
listView1 = (ListView)findViewById(R.id.listView1);
listView1.setAdapter(adapter);
}
}
This is my ItemsAdapter.java
public class ItemsAdapter extends ArrayAdapter<Items>{
Context context;
int layoutResourceId;
Items data[] = null;
public ItemsAdapter(Context context, int layoutResourceId, Items[] data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
ItemsHolder holder = null;
if(row == null)
{
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new ItemsHolder();
holder.txtTitle = (TextView)row.findViewById(R.id.listtext);
holder.switch1= (Switch)row.findViewById(R.id.listswitch);
row.setTag(holder);
}
else
{
holder = (ItemsHolder)row.getTag();
}
Items item = data[position];
holder.txtTitle.setText(Items.tv);
holder.switch1.setChecked(false);
return row;
}
static class ItemsHolder
{
TextView txtTitle;
Switch switch1;
}
}
This is my Item class.
public class Items {
public static String tv;
public static Switch switc;
public Items() {
super();
}
public Items(String tv, Switch switc ) {
super();
this.tv = tv;
this.switc = switc;
}
}
You are assigning an array with one Items object that you create with the arguments passed in create(). You should try something like this:
public class MainActivity extends Activity {
private Items[] items = new Items[0]; //We're making this a field, so we can create a new array containing our new item.
...
public void create (String str, Switch sw1) {
int i = items.length+1; //plus one because we are adding one element at a time. If you'd like to add more at once, change the 1 accordingly.
Items[] tmp = new Items[i];
System.arrayCopy(items, 0, tmp, 0, items.length);
tmp[i] = new Items(str, sw1);
items = tmp; //use items like you would use Items_data
...
}
}
This adds the contents of items to tmp, and then adds our new item at the end. If you'd like your new item to be at the top of the stack, we can simply:
System.arrayCopy(items, 0, tmp, 1, items.length);
tmp[0] = new Items(str, sw1);
Change your adapter declaration. May be below code help you.
public class MainActivity extends Activity {
Switch sw1;
private ListView listView1;
ItemsAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_main);
adapter = new ItemsAdapter (this,R.layout.items_row, Items_data);
}
public void getdata(View v) {
EditText et;
String dev_name;
et = (EditText)findViewById(R.id.editText1) ;
dev_name = et.getText().toString() ;
create(dev_name, null);
}
public void create (String str, Switch sw1) {
Items Items_data[] = new Items[]
{
new Items( str,sw1)
};
adapter = new ItemsAdapter (this,R.layout.items_row, Items_data);
listView1 = (ListView)findViewById(R.id.listView1);
listView1.setAdapter(adapter);
}
}
Check this link : Dynamically add elements to a listView Android
Related
I am an intern at this company and I have a task assigned to me by my team leader where I need to make an app that displays a list of items that I can add to and edit/delete the items on the list. I am following the requirements given to me on what the app needs to do.
The problem I'm having is that I need to pass values from an item when clicked on a ListView which uses a custom adapter, and have them sent to a new activity and displayed on the new activity's textviews and imageview. I have tried using putExtras() methods in the list click method and getting the values using getExtras() methods but they didn't work and I've already deleted those codes, so they are no longer there. If you need more of the classes/activities I'm using please let me know. I am using Android Studio 3.1.4
ItemListView.java
public class ItemListView extends AppCompatActivity {
DatabaseHelper myDB;
ArrayList<Item> itemList;
ListView listView;
Item item;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_item_list_view);
listView = (ListView) findViewById(R.id.listView);
myDB = new DatabaseHelper(this);
itemList = new ArrayList<>();
Cursor data = myDB.getListContents();
int numRows = data.getCount();
if(numRows == 0){
Toast.makeText(ItemListView.this, "There is nothing in the database.", Toast.LENGTH_LONG).show();
} else {
while(data.moveToNext()){
item = new Item(data.getString(1), data.getString(2), data.getString(3));
itemList.add(item);
}
Row_ListAdapter adapter = new Row_ListAdapter(this, R.layout.list_adapter_view, itemList);
listView = (ListView) findViewById(R.id.listView);
listView.setAdapter(adapter);
}
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = new Intent(ItemListView.this, ViewItemClicked.class);
startActivity(intent);
}
});
}
ViewItemClicked.java
I want the values displayed onto the layout of this activity when a row is clicked.
public class ViewItemClicked extends AppCompatActivity {
ImageView image;
TextView name, desc;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_item_clicked);
}
}
Other classes I used:
Row_ListAdapter.java
public class Row_ListAdapter extends ArrayAdapter<Item> {
private LayoutInflater mInflater;
private ArrayList<Item> items;
private int mViewResourceId;
ImageView image;
TextView name;
TextView description;
public Row_ListAdapter(Context context, int textViewResourceId, ArrayList<Item> items){
super(context, textViewResourceId, items);
this.items = items;
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mViewResourceId = textViewResourceId;
}
public View getView(int position, View convertView, ViewGroup parents){
convertView = mInflater.inflate(mViewResourceId, null);
Item item = items.get(position);
if(item != null){
image = (ImageView) convertView.findViewById(R.id.iconIV);
name = (TextView) convertView.findViewById(R.id.nameTV);
description = (TextView) convertView.findViewById(R.id.descTV);
if(image != null){
image.setImageBitmap(item.getImage());
}
if(name != null){
name.setText(item.getName());
}
if(description != null){
description.setText(item.getDescription());
}
}
return convertView;
}
}
Link to GUI: https://i.stack.imgur.com/wHfgv.png
Before you pass the data, implement your Item Class with Serializable like this:
public class Item implements Serializable{
/*your class code here*/
}
Then pass the data in the listView.setOnItemClicklistener like this
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Item passItem = itemList.get(position);
Intent intent = new Intent(ItemListView.this, ViewItemClicked.class);
Bundle itemBundle = new Bundle();
itemBundle.putSerializable("dataItem",passItem)// put the data and define the key
intent.putExtras(itemBundle)
startActivity(intent);
}
});
and to open the data in the ViewItemClicked.Class
public class ViewItemClicked extends AppCompatActivity {
ImageView image;
TextView name, desc;
Item item;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
item = (Item) getIntent().getSerializableExtra("dataItem"); // use the key
setContentView(R.layout.activity_view_item_clicked);
/*now u can use the item data*/
}
}
Try the codes below:
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = new Intent(ItemListView.this, ViewItemClicked.class);
String name = itemList.get(position).getString(1);
String description = itemList.get(position).getString(2);
String something_else = itemList.get(position).getString(3);
intent.putExtra("name", name);
intent.putExtra("description", description);
intent.putExtra("something_else", something_else);
startActivity(intent);
}
In your Details Activity:
Intent intent = getIntent();
String name = intent.getStringExtra("name");
String description = intent.getStringExtra("description");
String something_else = intent.getStringExtra("something_else");
Now use the strings to show the values in the desired places.
as
edittext.setText(name);
WHAT FORMAT TYPE OF IMAGE YOUR ARE USING
Is it Base64 or Bitmap if it is Base64 try this code..
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = new Intent(ItemListView.this, ViewItemClicked.class);
String name = list.get(position).getName();
String description = list.get(position).getDescription();
String image= list.get(position).getImage();
startActivity(intent);
}
In Your Second Activity use this code..
Intent intent = getIntent();
String name = intent.getStringExtra("name");
String description = intent.getStringExtra("description");
String image = intent.getStringExtra("image");
Convert here Base64 to Bitmap..
byte[] decodedString = Base64.decode(image, Base64.DEFAULT);
Bitmap decodedByte = BitmapFactory.decodeByteArray(decodedString, 0,
decodedString.length);
Define an interface for listening item click event
public class Row_ListAdapter extends ArrayAdapter<Item> {
private LayoutInflater mInflater;
private ArrayList<Item> items;
private int mViewResourceId;
ImageView image;
TextView name;
TextView description;
OnItemListener mListener;
public Row_ListAdapter(Context context, int textViewResourceId, ArrayList<Item> items){
super(context, textViewResourceId, items);
this.items = items;
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mViewResourceId = textViewResourceId;
}
public View getView(int position, View convertView, ViewGroup parents){
convertView = mInflater.inflate(mViewResourceId, null);
Item item = items.get(position);
if(item != null){
image = (ImageView) convertView.findViewById(R.id.iconIV);
name = (TextView) convertView.findViewById(R.id.nameTV);
description = (TextView) convertView.findViewById(R.id.descTV);
if(image != null){
image.setImageBitmap(item.getImage());
}
if(name != null){
name.setText(item.getName());
}
if(description != null){
description.setText(item.getDescription());
}
}
convertView.setOnClickListener((v) -> {
if(mListener != null) {
mListener.onItemClick(v, item);
}
})
return convertView;
}
public void setOnItemListener(OnItemListener listener) {
mListener = listener;
}
public interface OnItemClickListener {
void onItemClick(View v, Item item);
}
}
Then, implement OnItemClickListener in the activity and set it to the adapter:
Row_ListAdapter adapter = new Row_ListAdapter(this, R.layout.list_adapter_view, itemList);
adapter.setOnItemListener("your implement");
I just wanna update my ListView, but I cant. I dont know what. What did I do Wrong? I guess that the Adapter that I created is missing something to return the real adapter that I can handle.
Home.java (MainActivity)
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
MenuItem item = navigation.getMenu().findItem(R.id.navigation_home);
item.setCheckable(true);
item.setChecked(true);
BoxStore boxStore = AppMain.getBoxStore();
equipamentoBox = boxStore.boxFor(Equipamento.class);
lancamentoBox = boxStore.boxFor(Lancamento.class);
loadObjects();
////FOCUS HERE/////------------------------------
List<Equipamento> equipamentos = new ArrayList<>();
EquipamentoAdapter adapter;adapter = new EquipamentoAdapter(this, equipamentos);
listEquipamentos = (ListView) findViewById(R.id.listEquipamentos);
listEquipamentos.setAdapter(adapter);
registerForContextMenu(listEquipamentos);
}
EquipamentoAdapter.JAVA
public class EquipamentoAdapter extends ArrayAdapter<Equipamento> {
private final Activity context;
private final List<String> idArray = new ArrayList<String>();
private final List<String> qtdArray = new ArrayList<String>();
private final ArrayList<String> nomeArray = new ArrayList<String>();
private List<Equipamento> equipamentos = new ArrayList<>();
public EquipamentoAdapter(Activity context, List<Equipamento> equipamentos) {
super(context, R.layout.listview_row, equipamentos);
for (Iterator iterator = equipamentos.iterator(); iterator.hasNext(); ) {
Equipamento equipamento = (Equipamento) iterator.next();
this.idArray.add(Integer.toString((int)equipamento.getId()));
this.qtdArray.add(Integer.toString(equipamento.getQuantidade()));
this.nomeArray.add(equipamento.getNome());
}
this.context = context;
this.equipamentos = equipamentos;
}
public void callDialogTransaction(Equipamento equipamento) {
AlertDialog.Builder mBuilder = new AlertDialog.Builder(getContext());
LayoutInflater inflater = (LayoutInflater) context.getSystemService( Context.LAYOUT_INFLATER_SERVICE );
View mView = inflater.inflate(R.layout.dialog_lancamento,null);
TextView title = (TextView) mView.findViewById(R.id.txtTitle);
final EditText quantidade = (EditText) mView.findViewById(R.id.edtQtd);
final EditText Observacao = (EditText) mView.findViewById(R.id.edtObs);
Button addTransaction = (Button) mView.findViewById(R.id.btnAddTranD);
title.setText(equipamento.getNome());
addTransaction.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view) {
if(!quantidade.getText().toString().isEmpty()){
Toast.makeText(getContext(), "Success!", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getContext(), "Erro. Fill everything.", Toast.LENGTH_SHORT).show();
}
}
});
mBuilder.setView(mView);
AlertDialog dialog = mBuilder.create();
dialog.show();
}
public View getView(final int position, View view, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View rowView = inflater.inflate(R.layout.listview_row,null,true);
//this code gets references to objects in the listview_row.xml file
TextView txtQtd,txtName;
txtQtd = (TextView) rowView.findViewById(R.id.txtQtd);
txtName = (TextView) rowView.findViewById(R.id.txtName);
final ImageButton btnAddTransaction = (ImageButton) rowView.findViewById(R.id.btnAddTransaction);
//this code sets the values of the objects to values from the arrays
txtQtd.setText(qtdArray.get(position));
txtName.setText(nomeArray.get(position));
btnAddTransaction.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Equipamento equipamento = equipamentos.get(position);
callDialogTransaction(equipamento);
Animation animation = new AlphaAnimation(1.0f,0.8f);
animation.setDuration(100);
btnAddTransaction.startAnimation(animation);
}
});
return rowView;
}
}
I read that I could try to use adapter.notifyDataSetChanged(); but its not working. Also I tryed to add this on EquipamentoAdapter.java and call from my MainActivity when I needed to refresh, but it didn work as well. I dont know why. Everything seems right.
public void refreshData(){
this.equipamentos.clear();
for(Equipamento equipamento : equipamentoBox.getAll()){
this.equipamentos.add(equipamento);
}
notifyDataSetChanged();
}
I'll suggest the following changes:
Reference the equipamento object directly from List inside the getView the so that the getView function becomes
public View getView(final int position, View view, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View rowView = inflater.inflate(R.layout.listview_row,null,true);
//this code gets references to objects in the listview_row.xml file
TextView txtQtd,txtName;
txtQtd = (TextView) rowView.findViewById(R.id.txtQtd);
txtName = (TextView) rowView.findViewById(R.id.txtName);
final ImageButton btnAddTransaction = (ImageButton) rowView.findViewById(R.id.btnAddTransaction);
//this code sets the values of the objects to values from the arrays
Equipamento equipamento = equipamentos.get(position);
txtQtd.setText(String.valueOf(equipamento.getId()));
txtName.setText(String.valueOf(equipamento.getQuantidade()));
btnAddTransaction.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Equipamento equipamento = equipamentos.get(position);
callDialogTransaction(equipamento);
Animation animation = new AlphaAnimation(1.0f,0.8f);
animation.setDuration(100);
btnAddTransaction.startAnimation(animation);
}
});
return rowView;
}
Set the Items count with the getCount method
public int getCount(){
return equipamentos.size();
}
with these, calling notifyDataSetChanged(); should update the list without need to reinitialize the adapter.
One thing that you can do is reinflaiting the adapter, try this
public void refreshData(){
this.equipamentos.clear();
for(Equipamento equipamento : equipamentoBox.getAll()){
this.equipamentos.add(equipamento);
}
EquipamentoAdapter adapter;adapter = new EquipamentoAdapter(this, equipamentos);
listEquipamentos.setAdapter(adapter);
}
GUYS, I've noticed that if I use:
equipamentos.clear(); //Clear List
for(Equipamento equipamento : equipamentoBox.getAll()){
equipamentos.add(equipamento); //Populate List
}
adapter = null;
adapter = new EquipamentoAdapter((Activity) Home.this, equipamentos);
listEquipamentos.setAdapter(adapter);
adapter.notifyDataSetChanged();
Its gonna work. But this seems VERY wrong in terms of performance. My application is small but I dont want to make bad practices.
Create a method to replace the data and check the size of your adapter after you add new elements.
Add something like this to the adapter:
public void replaceData(List<Equipamento> equipamentos) {
this.equipamentos = equipamentos;
notifyDataSetChanged();
}
#Override
public int getCount() {
return equipamentos.size();
}
Then check the size from the Activity:
adapter.getCount();
As your following logic is in constructor of adapter-
enter code here
for (Iterator iterator = equipamentos.iterator(); iterator.hasNext(); ) {
Equipamento equipamento = (Equipamento) iterator.next();
this.idArray.add(Integer.toString((int)equipamento.getId()));
this.qtdArray.add(Integer.toString(equipamento.getQuantidade()));
this.nomeArray.add(equipamento.getNome());
}
after notifyDataSetChange, adapter is not called so you can do 2 things -
1) Initialize the Adapter as #Gastón Saillén answered.
2) Put that in some method and call it before you call notifydatasetchange.
I want to hide the 2nd option from the list on switch on off, I know how switch works, just tell me how to hide-unhide the option from the list. I want to hide list view item by item position or something like that.
New query : Is it possible to add two different adapter and switch them on switch preference change? if yes then how to do that?
This is 100% possible.
String [] titles = {"abc","def","ghi"};
String [] descriptions = {"abc","def","ghi"};
int [] images = {R.drawable.ic_abc,R.drawable.ic_def,R.drawable.ic_ghi};
ListView lv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_view);
lv = (ListView) findViewById(R.id.listView);
final Adapter adapter = new Adapter(getApplicationContext(), titles, descriptions, images);
lv.setAdapter(adapter);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
}
});
}
List view adapter
class Adapter extends ArrayAdapter {
int[] imageArray;
String[] titleArray;
String[] descriptionArray;
public Adapter(Context context, String[] titles1, String [] description1, int[] img1) {
super(context, R.layout.list_row, R.id.Titles, titles1);
this.imageArray = img1;
this.titleArray = titles1;
this.descriptionArray = description1;
}
#NonNull
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View row = inflater.inflate(R.layout.list_row,parent,false);
ImageView myImage = (ImageView) row.findViewById(R.id.Icons);
TextView myTitle = (TextView) row.findViewById(R.id.Titles);
TextView myDescription = (TextView) row.findViewById(R.id.Descriptions);
myImage.setImageResource(imageArray[position]);
myTitle.setText(titleArray[position]);
myDescription.setText(descriptionArray[position]);
return row;
}
}
Switch preference
public SwitchPreference sw;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_sw);
sw = (SwitchPreference) findPreference("001");
}
on switch on/off in main activity
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
boolean sw = sharedPreferences.getBoolean("001", true);
if (sw) {
//hide list view item (only one)
} else {
//unhide list view item (only one)
}
Well, take a look, so you can call remove properly:
class Adapter extends ArrayAdapter {
List<ItemObject> data = new ArrayList();
public Adapter(Context context, String[] titles1, String [] description1, int[] img1) {
super(context, R.layout.list_row, R.id.Titles, titles1);
for(int i = 0; i < titles1.lenght; i++)
data.add(new ItemObject(titles1[i], description1[i], img1[i]);
}
static class ItemObject {
String title, description;
int image;
ItemObject(String ti, String desc, int img) {
title = ti;
description = desc;
image = img;
}
}
//plus the rest of your class
And change at getView
ItemObject row = data.get(position);
myImage.setImageResource(row.image);
myTitle.setText(row.title);
myDescription.setText(row.description);
And add this method in the adapter:
public void removeObject(int at) {
data.remove(at);
notifyDataSetChanged();
}
So you can call removeObject with a position.
I am trying to create an onDisimiss listener to my app as for now this is what i have
The activity
public class listview_test extends Activity {
ListView list;
String[] web = {
"Google Plus",
"Twitter",
"Windows",
} ;
Integer[] imageId = {
R.drawable.ic_launcher,
R.drawable.icon,
R.drawable.ic_launcher,
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.list_test);
final CustomList adapter = new
CustomList(listview_test.this, web, imageId);
list=(ListView)findViewById(R.id.list);
list.setAdapter(adapter);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Toast.makeText(listview_test.this, "You Clicked at " +web[+ position], Toast.LENGTH_SHORT).show();
}
});
SwipeDismissListViewTouchListener touchListener =
new SwipeDismissListViewTouchListener(
list,
new SwipeDismissListViewTouchListener.DismissCallbacks() {
#Override
public boolean canDismiss(int position) {
return true;
}
#Override
public void onDismiss(ListView listView, int[] reverseSortedPositions) {
for (int position : reverseSortedPositions) {
adapter.remove(adapter.getItem(position));
}
adapter.notifyDataSetChanged();
}
}
);
list.setOnTouchListener(touchListener);
// Setting this scroll listener is required to ensure that during ListView scrolling,
// we don't look for swipes.
list.setOnScrollListener(touchListener.makeScrollListener());
}
}
And the custom adapter
public class CustomList extends ArrayAdapter<String>{
private final Activity context;
private final String[] web;
private final Integer[] imageId;
public CustomList(Activity context,
String[] web, Integer[] imageId) {
super(context, R.layout.weather_item, web);
this.context = context;
this.web = web;
this.imageId = imageId;
}
#Override
public View getView(int position, View view, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View rowView= inflater.inflate(R.layout.weather_item, null, true);
TextView txtTitle = (TextView) rowView.findViewById(R.id.city);
ImageView imageView = (ImageView) rowView.findViewById(R.id.info_image);
txtTitle.setText(web[position]);
imageView.setImageResource(imageId[position]);
return rowView;
}
For some reason every time i am swiping an item to dismiss it force closes and gives me this exception
java.lang.UnsupportedOperationException
In this line
adapter.remove(adapter.getItem(position));
java.lang.UnsupportedOperationException
is thrown when you back an Adapter by an array or non-modifiable List. Since you cannot change their size, deleting is impossible.
Instead, modify your Adapter so it accepts a List instead of an array and make sure that the List you pass off is fully flexible.
Something like
List <String> web = new ArrayList <String> ();
web.add ("Google Plus");
web.add ("Twitter");
//etc.
is enough to ensure a flexible list.
This means that your CustomList adapter should also call up to the superclass constructor that also accepts in a List, which in this case is
public ArrayAdapter (Context context, int resource, List<T> objects)
For more information refer to the ArrayAdapter documentation.
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!