我正在尝试构建一个使用listview显示消息的聊天应用。我正在使用SignalR进行实时通信。我遇到的问题是,当我滚动时,listview适配器仅更新接收器端的列表,但在发件人端,消息立即显示。 这是聊天的活动:
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
ISharedPreferences pref = Application.Context.GetSharedPreferences("UserInfo", FileCreationMode.Private);
loggeduser = pref.GetString("Username", String.Empty);
SetContentView(Resource.Layout.chat_activity);
initControls();
}
private async void initControls()
{
SignalRClientHelper proxySubscriber = SignalRClientHelper.GetInstance();
await proxySubscriber.StartConnection();
proxySubscriber.OnMessageReceived += proxySubscriber_OnMessageReceived;
messagesContainer = FindViewById<ListView>(Resource.Id.messagesContainer);
messageET = FindViewById<EditText>(Resource.Id.messageEdit);
sendBtn = FindViewById<Button>(Resource.Id.chatSendButton);
adapter = new ChatAdapter(this, new List<ChatMessage>(), loggeduser);
messagesContainer.Adapter = adapter;
//loadDummyHistory();
sendBtn.Click += (o, e) =>
{
string messageText = messageET.Text.ToString();
if (TextUtils.IsEmpty(messageText))
{
return;
}
proxySubscriber.InvokeSendMessage("psyoptica", messageText);
ChatMessage chatMessage = new ChatMessage();
chatMessage.Message = messageText;
chatMessage.Username = loggeduser;
messageET.Text = "";
displayMessage(chatMessage);
};
RelativeLayout container = FindViewById<RelativeLayout>(Resource.Id.container);
}
void proxySubscriber_OnMessageReceived(string username, string message)
{
ChatMessage chatMessage = new ChatMessage { Username = username, Message = message };
displayMessage(chatMessage);
}
public void displayMessage(ChatMessage message)
{
adapter.add(message);
adapter.NotifyDataSetChanged();
scroll();
}
private void scroll()
{
messagesContainer.SetSelection(messagesContainer.Count - 1);
}
}
这里是listview适配器的代码:
class ChatAdapter : BaseAdapter
{
private List<ChatMessage> messages;
private Activity context;
private string loggedUsername;
public ChatAdapter(Activity context, List<ChatMessage> messages, string loggedUsername)
{
this.messages = messages;
this.context = context;
this.loggedUsername = loggedUsername;
}
public override int Count
{
get { return messages.Count; }
}
public override Java.Lang.Object GetItem(int position)
{
return null;
}
public override long GetItemId(int position)
{
return position;
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
View view;
ViewHolder holder;
if (convertView == null)
{
view = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.chatMessage, parent, false);
holder = createViewHolder(view);
}
else
{
view = convertView;
holder = createViewHolder(view);
}
bool isMe = messages[position].Username == loggedUsername;
setAlignment(holder, isMe);
holder.txtMessage.Text = messages[position].Message;
return view;
}
private void setAlignment(ViewHolder holder, bool isMe)
{
if (!isMe)
{
holder.contentWithBG.SetBackgroundResource(Resource.Drawable.in_message_bg);
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams)holder.contentWithBG.LayoutParameters;
layoutParams.Gravity = GravityFlags.Right;
holder.contentWithBG.LayoutParameters = layoutParams;
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams)holder.content.LayoutParameters;
lp.AddRule(LayoutRules.AlignParentLeft, 0);
lp.AddRule(LayoutRules.AlignParentRight);
holder.content.LayoutParameters = lp;
layoutParams = (LinearLayout.LayoutParams)holder.txtMessage.LayoutParameters;
layoutParams.Gravity = GravityFlags.Right;
holder.txtMessage.LayoutParameters = layoutParams;
}
else
{
holder.contentWithBG.SetBackgroundResource(Resource.Drawable.out_message_bg);
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams)holder.contentWithBG.LayoutParameters;
layoutParams.Gravity = GravityFlags.Left;
holder.contentWithBG.LayoutParameters = layoutParams;
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams)holder.content.LayoutParameters;
lp.AddRule(LayoutRules.AlignParentRight, 0);
lp.AddRule(LayoutRules.AlignParentLeft);
holder.content.LayoutParameters = lp;
layoutParams = (LinearLayout.LayoutParams)holder.txtMessage.LayoutParameters;
layoutParams.Gravity = GravityFlags.Left;
holder.txtMessage.LayoutParameters = layoutParams;
}
}
public void add(ChatMessage message)
{
messages.Add(message);
}
public void add(List<ChatMessage> chatMessages)
{
messages.AddRange(chatMessages);
}
private ViewHolder createViewHolder(View v)
{
ViewHolder holder = new ViewHolder();
holder.txtMessage = v.FindViewById<TextView>(Resource.Id.txtMessage);
holder.content = v.FindViewById<LinearLayout>(Resource.Id.content);
holder.contentWithBG = v.FindViewById<LinearLayout>(Resource.Id.contentWithBackground);
holder.txtInfo = v.FindViewById<TextView>(Resource.Id.txtInfo);
return holder;
}
private class ViewHolder
{
public TextView txtMessage { get; set; }
public TextView txtInfo { get; set; }
public LinearLayout content { get; set; }
public LinearLayout contentWithBG { get; set; }
}
}
每次有新消息添加到列表时,都会调用方法displayMessage()
。我不明白为什么我必须滚动更改以显示在接收器端。任何人都可以在我的代码中指出错误吗?
答案 0 :(得分:1)
尝试使用scrollToPosition()而不是setSelection(),并在适配器notifyDataSetChanged()中的add()方法中尝试;
在您的班级ChatAdapter上:
public void add(ChatMessage message)
{
messages.Add(message);
NotifyDataSetChanged();
}
public void add(List<ChatMessage> chatMessages)
{
messages.AddRange(chatMessages);
NotifyDataSetChanged();
}
尝试在proxySubscriber_OnMessageReceived()中运行该进程:
void proxySubscriber_OnMessageReceived(string username, string message)
{
runOnUiThread(new Runnable() {
@Override
public void run() {
ChatMessage chatMessage = new ChatMessage { Username = username, Message = message };
displayMessage(chatMessage);
}
});
}