I'm trying to get the values of a listview that has an edittext for the user to place the values, and I get them when saving the information. I got it; The problem is that I use listview.getchildat (i) and I can only get the children that are visible on the screen, but sometimes they are more than 50 children and I can not get more than the 8 visible, I would like to see if there is any way to get Values not visible. This is the code I have and I get only visible children:
for (i = 0; i < feedList.size(); i++) {
View v = lv.getChildAt(i);
System.out.println("Posicion i: " + i);
TextView cobro = null;
try {
cobro = (TextView) v.findViewById(R.id.col_cobro);
System.out.println("CobroValidador: " + cobro.getText().toString());
sumaValidaCobro += Convert(cobro.getText().toString());
tstSuma += Convert(cobro.getText().toString());
} catch (Exception ex) {
validaCobrado++;
System.out.println("Valida cobrado: " + validaCobrado);
// tstSuma += Convert(cobro.getText().toString());
}
}
I'm using a listview with 4 col, this is the adapter.
SimpleAdapter simpleAdapter = new SimpleAdapter(this, feedList, R.layout.view_item, new String[]{"doc", "emp", "original", "saldo", "cobro"}, new int[]{R.id.col_doc_id, R.id.col_emp, R.id.col_original, R.id.col_saldo, R.id.col_cobro});
lv.setAdapter(simpleAdapter);
I need to get the new values of the last col, it's an EditText
FeedList is the initial adapter with which the listview is loaded, but the user can enter the values manually in the listview. When I save I can not use the original, I need to get all the data that the user entered. Any way to achieve this?
Greetings.
I resolved this problem changing from ListView to RecycleView, works very nice
ListView has a recycling mechanism, invisibel items might be recycled and lost the data they hold. See this answer for more details.
If you wish to reserve data from those EditTexts in the ListView, you might want to implement your own adapter, and put a listener on every EditText when inflating items.
Also, For a more modern, flexible, and performant approach to displaying lists, use RecyclerView.
Related
I am developing an android application, in which I have Edit texts in adapter rows of Recyclerview. Now I want to get sum of these Edit text values entered by user in activity. I have used below code for this purpose:
int count = listArray.size();
int sum = 0;
for (int i = 0; i < count; i++) {
LinearLayout ll = (LinearLayout) mRv_products.getLayoutManager().findViewByPosition(i);
if (ll != null) {
Log.v("TAG", "Item considered:" + i);
EditText t = (EditText) ll.findViewById(R.id.edt_quantity_ship_now);
String amount = t.getText().toString().trim();
if (!amount.isEmpty())
sum += Float.parseFloat(amount);
}
}
Now the problem is, I am getting views only for items which are visible on screen, not all. For example, if I have 10 total items in Recyclerview and only 3 items are visible on screen, I am getting sum of only 3 items which are visible on screen.
So far I have used other options for getting Edit text:
mRv_products.findViewHolderForAdapterPosition(i);
and
mRv_products.getChildAt(i);
Firstly in your adapter class create a string Array list.
private ArrayList<String> list;
Initialize this list in your adapters constructor and also create its getter setter and then in your onBindViewHolder() method add the editext textchangelistener and in this listeners onchangedtext() method add the following code
list.set(position,edittext.getText().toString);
Now you can get all the edittext value through the getter then you combine all the values using string builder.
Here is what i would do:
I will add textWatcher for every editText in RecyclerView item.
then will declare a variable in recyclerView Item model
when any text changed in editText, store the value in that item model.
when sum need to be calculated, iterate the list of model & calculate the result.
Main theme of recyclerView of any adapterView is that your view may or may not exist but your item list always exist. So, always update & use your item list as per as your requirement. It will help you a lot.
Hope it will help you. Thanks in advance.
I'm having a problem of getting item that are not visible in ListView. What I want is once the user has finished putting data in all EditText in a listview, I get all those values using a loop. But the issue is once the user has finished, with the loop I only get values visible on the screen and the rest the view returns null. any help please here is my code below. `
Log.e("size of:"," size listStudent(listview)--"+number);
for (int i=0;i<number;i++) {
View view = listStudent.getChildAt(i);
if(view !=null){
Log.e("size of:","counter"+i);
studentIdTxt = (TextView) view.findViewById(R.id.student_id_ls);
obtainedTxt = (EditText) view.findViewById(R.id.obtained);
maxTxt = (TextView) view.findViewById(R.id.max);
student = studentIdTxt.getText().toString().trim();
obtained_value = obtainedTxt.getText().toString().trim();
max_value = maxTxt.getText().toString().trim();
//updating the new mark list array
HashMap<String,String>studentMark=new HashMap<String,String>();
studentMark.put(TAG_STUDENT_ID,student);
studentMark.put(TAG_MARKS_OBTAINED,obtained_value);
studentMark.put(TAG_MARKS_MAX, max_value);
studentMarksList.add(studentMark);
}
}
//start of calling the JSON transmitter
JSONTransmitter transmitter=new JSONTransmitter();
//set the url
String url=domain+"/app/caller.php";
//transform studentMarksList to json
String studentList=gson.toJson(studentMarksList);
transmitter.setUrl(url);
Everything works fine, it's only that I can't get those item visible when you scroll. "number" is equal to 29 but the counter only iterates up to 4. Any help please!
listStudent.getChildAt(i);
A child view can only be retrieved from listview if it is visible on the screen.
Use a setOnFocusChangeListener for each EditText in the adapter (I assume you're using a custom adapter). When the user is done putting data, retrieve the text and update the list accordingly.
This is a tutorial if you need one.
I'm using a ListView with a custom ArrayAdapter.
The List is an infinite scroll of tweets.
Updates to the list are inserted from the top.
I want to obtain an effect as the Twitter application. I'm not talking about the "scroll to update", but to maintain the position after the update.
I've just implemented some code that works in that way. Here it is:
// get the position of the first visible tweet.
// pausedCounter traces the number of tweets in the waiting line
final int idx = listView.getFirstVisiblePosition() + pausedCounter;
View first = listView.getChildAt(0);
int position = 0;
if (first != null)
position = first.getTop();
// here I update the listView with the new elements
for (Tweet[] tweets1 : pausedTweets)
super.updateTweets(tweets1);
final int finalPosition = position;
// this code maintain the position
listView.post(new Runnable() {
#Override
public void run() {
listView.setSelectionFromTop(idx, finalPosition);
}
});
The problem of this code is that for an instant the listView goes to the first element of the list, then kick in the setSelectionFromTop and it goes to the correct position.
This sort of "flickering" is annoying, and I want to remove it.
I found out only this solution:
// add the new elements to the current ArrayAdapter
for (Tweet[] tweets1 : pausedTweets)
super.updateTweets(tweets1);
// create a NEW ArrayAdapter using the data of the current used ArrayAdapter
// (this is a custom constructor, creates an ArrayAdapter using the data from the passed)
TweetArrayAdapter newTweetArrayAdapter =
new TweetArrayAdapter(context, R.layout.tweet_linearlayout, (TweetArrayAdapter)listView.getAdapter());
// change the ArrayAdapter of the listView with the NEW ArrayAdapter
listView.setAdapter(newTweetArrayAdapter);
// set the position. Remember to add as offset the number of new elements inserted
listView.setSelectionFromTop(idx, position);
In this way I have no "flickering" at all!
I am previously working on PHP and js , and recently I am working on android listview
However, I encountered a problem in creating a custom adapter for listview
public View getView(int arg0, View arg1, ViewGroup arg2) {
// TODO
if (arg1 == null) {
arg1 = myInflater.inflate(R.layout.grid, arg2, false);
}
TextView name = (TextView) arg1.findViewById(R.id.text1);
TextView desc = (TextView) arg1.findViewById(R.id.text2);
ImageView image = (ImageView) arg1.findViewById(R.id.image1);
if (arg0 < images.length) {
image.setImageResource(images[arg0]);
}
name.setText(names[arg0]);
desc.setText(description[arg0]);
return arg1;
}
The problem is I have 3 array of content to pass to the listview grid, for the first two array, there are 10 element and the last one have 5 only. So , it is out of boundries for the last one. I added a condition to check whether it exceed 5 , but args0 seems not increased according to the row?
if (arg0 < images.length) {
image.setImageResource(images[arg0]);
}
The first five row and some other rows also has image setted, why is that and how to fix this? thanks
In General
since you want to display Data to your list, plx create an Object that represents Data.
like you named in your comment above:
public class ListEntry {
String name = "";
String gender = "";//use enum here perhaps -.-
String photoUrl = null; //or use byte[] photo or whatever you've stored in your array before
// write getters/setters for your members
}
then you can use one array ListEntry[] (or List<ListEntry>) to access all data. this way you get around your indexOutOfBoundsException.
lookup any listadapter tutorials online, e.g. the one from Vogella
Why do more than the first five entries have an image?
Androids Adapters for Listviews implement a caching mechanism to reduce the inflating (performance/memory cost intensive) of new list-items (e.g. rows) to a minimum. therefore there are only as many rows (or little more) created as displayed by the list. since you only set images if there are any, but never remove already set images from rows, you result in some rows that replay images they shouldn't. these rows are cached from previously outscrolling rows.
therefore add something like
if (listItem.photo != null) {
image.setImageResource(images[arg0]);
} else {
image.setVisibility(View.GONE);
}
as reference for listviews and their caching mechanism see Romain Guy on ListViews
Edit Regarding usage of Listadapter
The getView(..) you posted above is inside your ListAdapter implementation, prefarrably you've extended an ArrayAdapter<T>. if so, your T should now state ListEntry and you have any line of code that states
MyArrayAdapter myAdapter = new MyArrayAdapter() or something like that.
now you have an array or List of ListEntry like List<ListEntry> myCollection = new ArrayList<ListEntry>() or ListEntry[] listEntries = new ListEntry[10] and use
myAdapter.addAll(listEntries);
to get an item of your list inside your getView(..) you can use:
ListEntry currentEntry = getItem(arg0);
and refer the single members of currentEntry to set them ;-)
What about
if (images[arg0] != null) image.setImageResource(images[arg0]);
?
I create a dialog and populate it with a listview that uses a custom list adapter. It works fine, but I've noticed that when the list is long enough to scroll, doing so back and forth will cause some of my list items to randomly lose some of their data. I've noticed it is always the same list items too. For instance, each list item will have a title, image, and date on it. The dates seem to vanish on some when I scroll. They are always there when I start the dialog, and they always vanish once I scroll.
The weird thing is that my list row consists of a few TextViews in 2 rows and its only the bottom row TextViews that dissapear...Any ideas?
Code for my dialog
itemSendPickerDialog = new Dialog(this);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Select Item to Send");
ListView lv = new ListView(this);
Cursor c = mDbHelper.fetchItemsByDate(id);
c.moveToFirst();
int i = R.layout.send_item_menu_row;
MyListAdapter ia = new MyListAdapter(this, mainListBackground, c, true);
lv.setAdapter(ia);
builder.setView(lv);
itemSendPickerDialog = builder.create();
itemSendPickerDialog.show();
And my custom list adapter class:
class MyListAdapter extends ResourceCursorAdapter {
public MyListAdapter(Context context, int i, Cursor cursor, boolean...sending) {
super(context, i, cursor);
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
TextView title = (TextView) view.findViewById(R.id.item_name);
title.setText(cursor.getString(cursor.getColumnIndex(TripsDbAdapter.KEY_ITEM_TITLE)));
Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int width = display.getWidth();
width = width - 150;
ViewGroup.LayoutParams params = title.getLayoutParams();
params.width = width;
title.setLayoutParams(params);
String cat = cursor.getString(cursor.getColumnIndex(TripsDbAdapter.KEY_ITEM_CATEGORY));
if (cat.equalsIgnoreCase("trip notes")) {
LinearLayout ll = (LinearLayout) view.findViewById(R.id.item_datetime_holder);
ll.setVisibility(View.INVISIBLE);
}
TextView date = (TextView) view.findViewById(R.id.item_date);
date.setText(cursor.getString(cursor.getColumnIndex(TripsDbAdapter.KEY_DEP_DATE)));
TextView time = (TextView) view.findViewById(R.id.item_time);
time.setText(cursor.getString(cursor.getColumnIndex(TripsDbAdapter.KEY_DEP_TIME)));
ImageView iv = (ImageView) view.findViewById(R.id.image_icon);
if (iv != null) {
int index = cursor.getColumnIndex(TripsDbAdapter.KEY_ITEM_TYPE);
String type = cursor.getString(index);
if (type != null) {
} else {
type = "notes";
}
iv.setImageResource(getTypeResource(type));
}
}
}
I have faced this problem too...
The problem you are facing is due to the recycling of views by the LIstView when you scroll up/down. In your case, the ListView is giving you those recycled views , whose properties you have changed by making them invisible. Some possible solutions could be:
1) When cat.equalsIgnoreCase("trip notes")) is becoming true, you are making some views invisible. This invisible view is then recycled and given back. The recycled view is still invisible (when it is given back to you), so what you can do is make this invisible view visible in the beginning of your ListAdapter every time .
You can put this code at the beginning of bindView method where you make the layout visible first and then proceed with rest of the logic.( In short, the dates from your display are not vanishing but are just invisible).
2) Override getViewTypeCount() in you adapter . From your codesnippet, it looks like you have two types of rows( one in which R.id.item_datetime_holder is invisible and other in which it is visible) , so return 2 from this method( please do some trial and error ) . This should take care of the problem.
public int getViewTypeCount() {
return 2;
}
You will find an excellent explanation at this link http://logc.at/2011/10/10/handling-listviews-with-multiple-row-types/
3) You can inflate completely different layouts depending on your if condition. But the effeciency would be a little less.
I had a similar problem, when scrolling a list, only the items after the window height decided to get their data repeating from index 0 - so if the last visible item was 8, the next would be 0 again.
So you could try to check if the index of the view is correct, maybe this method of ListView would help
lv.getPositionForView(view);
I've figured out that the code that is doing this is in my custom list adapter class
String cat = cursor.getString(cursor.getColumnIndex(TripsDbAdapter.KEY_ITEM_CATEGORY));
if (cat.equalsIgnoreCase("trip notes")) {
LinearLayout ll = (LinearLayout) view.findViewById(R.id.item_datetime_holder);
ll.setVisibility(View.INVISIBLE);
}
I hide some of the layout items depending on what the category is, and for some reason when putting a list view in an AlertDialog builder it appears to mix up the items. I don't know exactly how I am going to fix it, but for now if I just remove the invisibility functionality, my data won't go away.
I would use two different layouts, depending on the "type" of list item. It looks like you are switching the "type" based on the cat string containing "trip notes". If it contains it, then you would have a layout that is the same as you have now, but without the item_datetime_holder view. If it doesn't contain it, then you would use the same layout as you're using now (send_item_menu_row).
Here is a good tutorial on how to use multiple layouts in a ListView: http://android.amberfog.com/?p=296
By the way, I think that the reason why some of your rows are not drawing correctly is due to view reuse by the ListView. Utilizing the multiple layouts like I've mentioned above should fix the problem since you won't be changing the visibility of views, but just utilizing two different views to render, depending on what type of list item you're rendering.