【发布时间】:2016-06-15 20:34:09
【问题描述】:
我正在尝试构建一个使用列表视图来显示消息的聊天应用程序。我正在使用 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);
}
}
这是列表视图适配器的代码:
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()。我不明白为什么我必须滚动才能在接收器端显示更改。谁能指出我的代码中的错误?
【问题讨论】:
-
我不知道我是否理解这个问题,您正在更新列表,将元素添加到列表视图的最后位置,这就是为什么您需要滚动才能看到它。
-
是但不应该“messagesContainer.SetSelection(messagesContainer.Count - 1);”自动滚动以显示列表中的最后一项?此外,即使列表为空,列表项也不会出现,我必须滚动才能显示新添加的项。
-
请检查我的答案