| have almost got my application working. Now i am in final stage. I am struck with an issue to display sent and received message in dynamic listview. Based on data sent or received i need to display the text in listview. I am able to view sent message in. I am able to receive the message from receiver but i am unable to display that in a listview.
sample code:
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = getLayoutInflater();
View row;
String query = null;
// String even_color, odd_color;
SharedPreferences prefList = getSharedPreferences("PrefsFile",
MODE_PRIVATE);
if(query == data){
row = inflater.inflate(R.layout.list_row_layout_odd, parent,
false);
TextView textLabel = (TextView) row.findViewById(R.id.text);
textLabel.setText(data);
}
else
{
row = inflater.inflate(R.layout.list_row_layout_even, parent,
false);
TextView textLabel = (TextView) row.findViewById(R.id.text);
textLabel.setText(datas);
}
return row;
}
}
If i sent message i need to display the msg in ie(list_row_layout_odd) and if i recieve message i need to display in (list_row_layout_even) layout.
please help me in solving this issue.
Thanks in advance.
Related
i have a big problem with my ListViewAdapter.
My listview shows 2 entrys at the same time. Each entry should get a different picture from my server.
The first and the second entrys working fine, but if i'm scrolling down, the next entrys will have the same pictures.
My Code looks like this:
if (viewHolder.imgPic != null) {
String strUrl = mainUrl+list.get(position).getUrl();
new ImageDownload(viewHolder.imgPic).execute(strUrl);
}
I'm checking the view and just doing it, if it's null.
Can someone help me?
Thanks
from your question I can assume that you don't know about the ListView recycling mechanisem
basically, view that that not visible anymore (after user scrolled it away from sight) it been recycled to displayed new item that need to shown. that's the convertView parameter at the getView() method...
probably you are see the same image because the recycled view stays with the same image..
also there is the issue of the asynchronous task (your ImageDownload class) that can finish it execute when the original item that started the request already been recycled.
I recommend you to "dig" as dipper as you can to understand all about ListView - this is one of the most complex and important UI component. reading the post I linked you is a good start.
also this video is very important:
http://www.youtube.com/watch?v=wDBM6wVEO70
Here is my GetView:
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View view = null;
if(rowResourceId!=R.layout.search_empty_list) {
if (convertView == null) {
LayoutInflater inflator = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflator.inflate(rowResourceId, null);
final ViewHolder viewHolder = new ViewHolder();
viewHolder.textName = (TextView) view.findViewById(R.id.textView1);
viewHolder.imgPic = (ImageView) view.findViewById(R.id.imgPic);
if (viewHolder.imgPic != null) {
String strUrl = mainUrl+list.get(position).getUrl();
new ImageDownload(viewHolder.imgPic).execute(strUrl);
}
view.setTag(viewHolder);
} else {
view = convertView;
}
ViewHolder holder = (ViewHolder) view.getTag();
holder.textName.setText(list.get(position).getName());
} else {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(rowResourceId, parent, false);
TextView textView1 = (TextView) view.findViewById(R.id.textView1);
textView1.setText(list.get(0).getName());
}
return view;
}
i've built a chat application.
inside my chat messages Activity, i have a ListView which shows all text message.
inside each text messages i have a TextView which will by default write "Sending..." and i want it to be updated after the message is sent.
inside each ChatMessage object i have a sent and time property. if sent is true i will show in the TextView the time, and if it's false i will write "Sending" as written above.
when i'm sending a new message, i'm adding a new view to the ListView adapter, and from some reason it shows that message was sent although it didn't... can't really understand why.
this is my ArrayAdapter's getView() and holder class:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
ChatMessage chatMessage = chatMessagesArrayList.get(position);
ChatMessageHolder chatMessageHolder = null;
if (row == null)
{
if (chatMessage.getSenderId() == app.getFacebookCurrentUser().getId())
row = LayoutInflater.from(context).inflate(layoutResourceId, null);
else
row = LayoutInflater.from(context).inflate(R.layout.chat_green, null);
chatMessageHolder = new ChatMessageHolder();
chatMessageHolder.message = (TextView) row.findViewById(R.activity_chat.message);
chatMessageHolder.sentTime = (TextView) row.findViewById(R.activity_chat.sent_time);
chatMessageHolder.isSent = chatMessage.isSent();
row.setTag(chatMessageHolder);
}
else
{
chatMessageHolder = (ChatMessageHolder) row.getTag();
}
chatMessageHolder.message.setText(chatMessage.getMessage());
if (chatMessageHolder.isSent)
chatMessageHolder.sentTime.setText(app.getDateTime(chatMessage.getTime()));
return row;
}
private static class ChatMessageHolder
{
TextView message, sentTime;
boolean isSent = false;
}
i can't really understand why doesn't it write the time or "Sending..." according to the isSent boolean flag...
It's because the ListView recycles previous views (that's what the convertView variable is). Likely it's recycling another view that was already set to "Sent", and you're never handling the alternate case where chatMessagerHolder.isSent is false. You should avoid setting chatMessageHolder.isSent = chatMessage.isSent(); until after that first if-else block. That first if-else should just be to initialize the view or recycle the object. Also, when you check if(chatMessageHolder.isSent) you should also handle what the TextView should say if that is false (i.e. in a followup else statement) since the views are recycled.
I am working on android chat application. I am facing a problem in send and receive function using xmpp. I am able to send message from emulator to xmpp and receive message from xmpp. But i am facing issue in displaying the incoming and outgoing message in a list view. I am confused how to give the condition to set view layout.
if(message from xmpp) {
TextView textLabel = (TextView) row.findViewById(R.id.textb); // if message received dislay in left side textview
textLabel.setText(receiveddata); //receiveddata contains arraylist of incoming message
} else (message from me) {
TextView textLabel = (TextView) row.findViewById(R.id.texts); // if message sent by me dislay in right side textview
textLabel.setText(sentdata); //sentdata contains arraylist of outgoing message
}
Kindly tell me how can i do this.
Thanks
You can create an adapter class having two layout having same field. use if condition for incoming and outgoing messages. and inflate accordingly.
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
entry = list.get(position);
if (convertView == null) {
if (getItemViewType(position) == 0) {
convertView = inflator.inflate(
R.layout.messages_even_list_layout, null);
} else {
convertView = inflator.inflate(
R.layout.messages_odd_list_layout, null);
}
i am working on a chat application. I am able to send and receive message normally. But when i try to integrate bubble message, i need guidance. i have 2 layouts
left layout(Display sent message by me, 2. right layout() display received messages. I am able to display message i am sending in bubble message. I am not able to display the received message. How should i go ahead.
sample code is given below:
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = getLayoutInflater();
View row = null;
String jid = null;
String even_color, odd_color;
SharedPreferences prefList = getSharedPreferences("PrefsFile",
MODE_PRIVATE);
even_color = prefList.getString("even_bubble_color", "pink");
odd_color = prefList.getString("odd_bubble_color", "green");
int even_color_id = getResources().getIdentifier(even_color,
"drawable", "com.teks.chilltwit"), odd_color_id = getResources()
.getIdentifier(odd_color, "drawable", "com.teks.chilltwit");
//ImageView even_view, odd_view;
// System.out.println("Timeline: Position: "+position+", Length: "+data.length);
// if(position!=data.length-1){
if (jid != null) {
row = inflater.inflate(R.layout.list_row_layout_odd, parent,
false);
TextView textLabel = (TextView) row.findViewById(R.id.text);
textLabel.setText(datav);
}
else {
row = inflater.inflate(R.layout.list_row_layout_even, parent,
false);
TextView textLabel = (TextView) row.findViewById(R.id.text);
textLabel.setText("" + messages);
}
return row;
}
}
In the above code, i need to display left layout if i send the message and else i need to display right layout if i receive message. Please guide me in this issue.
Thanks.
So, the problem here is that the jid is always not null?
I have a ListView, and I have added a header (with getListView().addHeaderView) that simply contains a TextEdit widget.
Then when I tap the TextEdit to start writting, the keyboard appears and it messes up the list!
If I tap everywhere else to hide the keyboard, the list messes up again!
I don't know why is this happening. I thought it was something related with the onConfigurationChanged method, but after implementing it (and adding the corresponding attribute in the manifest file) the problem persists.
How could I fix it? Why is Android messing up my list?
EDIT:
My list uses a custom adapter, this is the getView method:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v != null) {
return v;
}
LayoutInflater vi = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.list_row, null);
ListTask list_item = items.get(position);
if (list_item != null) {
TextView item_name = (TextView) v.findViewById(R.id.item_name);
item_name.setText(list_item.getTitle());
}
return v;
}
The problem is not the value of my items, but their order. They are displayed in a different order when the keyboard appears, but the values are correct.
EDIT2:
Ok, I have changed my getView method with rekaszeru's suggestion and now it works as expected. But now I'm facing another problem: what if my items have two textviews?
Let's say the second textview is optional, and "Item 1" and "Item 3" have it, but "Item 2" does not, so it's initialized as a void String (length == 0).
The first time the list is displayed, it shows "Item1" and "Item 3" with their second textview, and "Item 2" without it. That's correct. But when the keyboard appears, the "Item 2" takes the second textview of another item and displays it!
This is the modified code I have right now:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater vi = (LayoutInflater) getContext().
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.list_row, null);
}
ListTask list_item = items.get(position);
TextView item_name = (TextView) convertView.findViewById(R.id.item_name);
TextView item_optional_text = (TextView) convertView.findViewById(R.id.item_optional_text);
item_name.setText(list_item.getTitle());
// if the item has defined the optional text, make some room and display it
if (item_optional_text.isNotEmpty()) {
LayoutParams layout_params = (LayoutParams) item_name.getLayoutParams();
layout_params.topMargin = 10;
layout_params.height = -2; // -2: wrap_content
item_name.setLayoutParams(layout_params);
item_optional_text.setText(list_item.getOptionalText());
}
return convertView;
}
The isNotEmpty() does this in the Item class:
public boolean isNotEmpty() {
return this.optional_text.length() > 0;
}
Maybe it's too complex to understand in a written question. If so, I can make a short video showing the problem and my source code. Thanks in advance for your help guys.
Your row recycling is messed up. Android is not changing the order of the items, you are.
Right now, if you are passed a row to recycle, you return it without modification. This is a mistake. You are supposed to modify the contents of the row to reflect the data at the supplied position. The only piece of logic you can skip in this case is inflating a brand-new row.
Here is a free excerpt from one of my books that goes through all of this.
You should override the getView method in your ListAdapter implementation, and make sure that you always assign a new value to the view that you are returning (or at least always update it to contain the proper data).
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
convertView = inflater.inflate(R.layout.list_row, parent, false);
//set the necessary data in your TextViews, Checkboxes, etc...
return convertView;
}
If you don't inflate your item renderer, then you can instantiate it from code, like:
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
convertView = new TextView([...]);
convertView.setText(textBasedOnYourData);
return convertView;
}
Edit
As #CommonsWare noted, attention should be payed to the recycling of your list item renderer. So instead of instantiating it every time, you should check whether it already exists or not, and update the underlying TextView afterwards.
So I'd suggest give a try to this slightly modified getView implementation:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater vi = (LayoutInflater) getContext().
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.list_row, null);
}
ListTask list_item = items.get(position);
TextView item_name = (TextView) convertView.findViewById(R.id.item_name);
//the item should never be null, but just in case:
item_name.setText((list_item == null) ? "" : list_item.getTitle());
return convertView;
}