I have a problem with my custom list adapter.
My main activity consist of a ListView, Button and a EditText field.
When the user inputs something in the EditText field, and presses the button. The text should
appear in the ListView. For the ListView i have made a custom adapter. That at the moment only consist of a TextView, but i will later add more stuff so i can not use a standard adapter.
The problem is that when the user types something, and presses the button, the string is placed in the ListView, (great!), but the problem is when the user presses again, that the old text is replaced by the new (the list has 2 items, both contain same text). When the user adds a third item to the list, this item replaces the old ones, and i now have 3 of the newest in the list?
So the problem is that the newest item replaces the old ones?
In my mainActivity i have this:
private ListView list_messages;
private Button send_button;
private TextView input_message;
public Custome_list_item adapter;
public ArrayList<String> message_holder;
message_holder = new ArrayList<String>();
adapter = new Custome_list_item(this,message_holder);
list_messages.setAdapter(adapter);
The custom list adapter only has a getView, like this:
LayoutInflater inflater = context.getLayoutInflater();
View rowView= inflater.inflate(R.layout.list_row, null, true);
TextView txtTitle = (TextView) rowView.findViewById(R.id.message_in_list_row);
ImageView imageView = (ImageView) rowView.findViewById(R.id.user_profile);
TextView timeView = (TextView) rowView.findViewById(R.id.date_and_time);
txtTitle.setText(message_holder.get(message_holder.size()-1));
//imageView.setImageResource(imageId);
timeView.setText("DD:MM:YY");
return rowView;
when the user clicks the button in the main activity, i do this:
mainActivity.message_holder.add(item);
mainActivity.adapter.notifyDataSetChanged();
Any help is appreciated
Your getview is using size in the .get function, so it will always return the last string in the array as the text. It should be using the position passed in to the call.
Try Changing
txtTitle.setText(message_holder.get(message_holder.size()-1));
to
txtTitle.setText(message_holder.get(position));
Because position will replace the view's position to the item,i.e. On first item the txtTitle from first adapter position will be displayed.On second listItem the second Adapter View will be displayed and so on.
Related
I'm trying to make a Music Player in Android, and yesterday I got the idea to set the currently playing song colored in the ListView.
At the beginning I set that every time I start a song, a new BaseAdapter inflate a layout with 2 TextView (title and artist) and if the song is the same in the MediaPlayer, the 2 TextView become blue.
It was working fine, but i noticed that when I pick a song, the ListView scrolls immediately up because the Adapter is recreated.
Searching the web I found that I could create a new method in the BaseAdapter class, where if I pass the ListView and the song position I could color it, so I would call the setAdapter(songList) only in the onCreate method.
Yeah, but it doesn't work.
-SongAdapter:
public void updateData(ListView listView, int position){
if (MainActivity.isMusicStarted) {
//These 2 lines of code return a NullPointerException
songView = (TextView) listView.getSelectedView().findViewById(R.id.song_title);
artistView = (TextView) listView.getSelectedView().findViewById(R.id.song_artist);
//The following 2 lines, if de-commented, color only the two TextView in the first shown row instead of the selected row
//songView = (TextView) listView.findViewById(R.id.song_title);
//artistView = (TextView) listView.findViewById(R.id.song_artist);
if (position==MusicService.getCurrentSong()) {
songView.setTextColor(ContextCompat.getColor(context, R.color.colorPrimary));
artistView.setTextColor(ContextCompat.getColor(context, R.color.colorPrimary));
}
else{
songView.setTextColor(ContextCompat.getColor(context, android.R.color.primary_text_light));
artistView.setTextColor(ContextCompat.getColor(context, android.R.color.secondary_text_light));
}
}
}
-MainActivity: (called at the end of a OnCompletitionListener())
public static void colorSongSelected(int position){
songAdapter.updateData(songView, position);
}
listview.getSelectedView() return the view corresponding to the currently selected item, or null if nothing is selected.
For more information how to select a item in listview you can see this answer
Maybe there is a simple solution to my problem, but i´m not able to find it.
I have a ListView with a list of users. Each row has an EditText to enter the username. I want to set hint text for each user like: "user1, user2, user3, etc", used as default name. The user can click on the EditText and change this name, so the hint text dissapears and the user can enter his name, or leave this default name if he wants.
When the ListView is too long, I have the problem of the view recycling, that duplicates the names. I solved it by using a setOnFocusChangeListener for the EditText, and storing the name for each row, and it´s working fine, but I´d like that when I have a long list, keep the hint text or text introduced by the user for each EditText when scrolling the list.
I don´t know how to modify my adapter to set the name/hint for each EditText.
Any idea?
Thanks a lot.
Create one list in your activity
List<String> yourlist = new ArrayList();
yourlist.add("user1");
yourlist.add("user2");
yourlist.add("user3");....
pass this list to adapter then in adapter,
holder.youredittext.setHint(yourlist.get(position));
if your passing number of items to adapter then create one model class then pass to adapter.
I have an adapter like this:
public View getView(final int position, View convertView, ViewGroup parent)
{
View item = convertView;
if(item == null)
{
LayoutInflater inflater = context.getLayoutInflater();
item = inflater.inflate(R.layout.setup_jugador, null);
holder = new ViewHolder();
holder.nombre = (EditText) item.findViewById(R.id.nombre);
// Establecemos el tag
item.setTag(holder);
}
else
{
holder = (ViewHolder)item.getTag();
}
holder.nombre.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if(!hasFocus){
EditText et = (EditText) v.findViewById(R.id.nombre);
// Here I store the name
jugadores.get(position).setNombre(et.getText().toString());
}
}
});
// Update EditText
holder.nombre.setText(jugadores.get(position).getNombre());
// Another option is
holder.nombre.setHint(jugadores.get(position).getNombre());
return(item);
}
jugadores is a list that stores the names. Initially it has user1, user2, etc.
I could setHint when Item==null, but I have to update the text at the end of the adapter, and when scrolling, the view recycling changes the items that are invisible.
I only see 8 items, and when scrolling, if I change first item, item number 9 also change. If I use setText, it becomes black, and if I use setHint, first item becomes grey.
I can´t put hint value in layout because I´d like to add the row number to the name. I tried using a boolean value in the class used as model in the adapter to show that the name has been modified, check this value using position index in the list, and use setText or setHint according to that, but doesn´t work.
so I have this huge problem with applying a strikethrough on a ListView item while populating it from the List of my objects.
private void setListItems() {
DatabaseHandler db = new DatabaseHandler(this);
List<ToDoTask> taskList = db.getAllTasks();
for (ToDoTask tt : taskList) {
this.listAdapter.add(tt.getName());
}
this.listAdapter.notifyDataSetChanged();
}
This part of the code populates my ListView. Now i want to add a strikethrough to item if
tt.getActive() == 0
I don't know how can i get a TextView item from my ListView. I tried in my for loop to:
TextView textView = (TextView) this.listView.getChildAt(this.listView.getCount() -1);
but the app crashes.
The only solution that didn't crash my app was:
TextView textView = this.listAdapter.getView(this.listView.getCount() -1, null, null)
but it didn't actually change anything in the ListView. I think it's not referencing the object itself.
Here's some code that instantiates my variables:
this.listView = (ListView) findViewById(R.id.listViewItem);
this.listItems = new ArrayList<String>();
this.listAdapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, this.listItems);
this.listView.setAdapter(this.listAdapter);
The list view is not in charge of instantiating or modifying the underlying state of the views it contains. That's the job of the adapter. When you scroll a ListView, it calls the adapter method getView() and the adapter will hand it a row (possibly a recycled view from the rows that scrolled off-screen).
Inside the getView() method, the adapter should consult the underlying data set and modify the row as needed - that would include crossing out text, or setting any visual properties of the row content.
I have a listview in which every listitem has one image and 4 textviews. I want to change only 2 textviews without changing the list and list of items.
Those textviews are changed every second.
Is it possible in android?
You can update the text items of listView like this:
private void updateText(int index){
View v = ListView.getChildAt(index);
TextView updatedText = (TextView) v.findViewById(R.id.txt_view);
updatedText .setText("changed Text");
}
I want to create a layout composed of :
textview, as a title
listview
and all when the user scrolls down/up all the content scrolls together (not only inside the listview)
Any ideas?
Why don't you load the title into the listview, as the top item, and make your activity extend ListActivity?
If you want the title to be formatted differently, you can specify this on the getView() method --
if (position == 0) {
//format title item }
else {
//format other items
You can define your textview like this:
View textView = ((LayoutInflater)Activity.this.getSystemService(Activity.this.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.textview_title, null, false);
and then add it as a listview header
myListView.addHeaderView(textView);
If you want to set the selection to be the first list item after the header view you can use
myListView.setSelectionAfterHeaderView();