我正在开发一个有点聊天的应用程序,并希望使用ListView
来显示消息。目前我正在尝试获取用户的输入并将其显示为“外发消息”。我的row
布局如下:TextView
(时间戳),TextView
(消息),ImageView
(消息状态指示符)。我的问题:文本和时间戳没有设置,只是“虚拟”布局膨胀。我想我必须以某种方式在适配器内设置文本..有人能告诉我我做错了什么吗?代码如下。
我的适配器:
public class ChatAdapter extends BaseAdapter {
private Context context;
private List<String> chat;
public ChatAdapter(Context context, List<String> listchat) {
this.context = context;
this.chat = listchat;
}
public int getCount() {
return chat.size();
}
public Object getItem(int position) {
return chat.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup viewGroup) {
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.row, null);
}
TextView tvTS = (TextView) convertView.findViewById(R.id.tvTS);
// TODO set timestamp
TextView tvMessage = (TextView) convertView
.findViewById(R.id.tvMessage);
// TODO set the text to the actual message text from etInput
ImageView indicator = (ImageView) convertView.findViewById(R.id.imgInd);
// TODO set the image Resource according to message state
return convertView;
}
我的活动:
public class ChatActivity extends ListActivity {
private EditText input;
private String tmpMessage;
ListView lv;
ChatAdapter adapter;
List<String> messages;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.lis);
Button send = (Button) findViewById(R.id.btnSend);
input = (EditText) findViewById(R.id.etInput);
lv = getListView();
messages = new ArrayList<String>();
adapter = new ChatAdapter(this, messages);
lv.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
// TODO
}
});
lv.setAdapter(adapter);
send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
sendMessage();
}
});
}
public void sendMessage() {
tmpMessage = input.getText().toString();
input.setText("");
messages.add(tmpMessage);
adapter.notifyDataSetChanged();
}
@SuppressLint("SimpleDateFormat")
public String generateTimestamp() {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
String ts = sdf.format(new Date());
return ts;
}
更新
我添加了一个持有人并使用以下代码设置文本:
String message = (String) getItem(position);
holder.message.setText(message);
它可以工作,但现在可以随机定位膨胀的布局,请参见下面的截图。它应该看起来像
测试
TEST1
TEST2
...
是什么原因?
答案 0 :(得分:1)
您必须在setText
中调用getView
方法获取文字方法,并为您需要的每个视图设置文字。并设置你的形象。 getView
负责为列表创建单个视图,因此您必须以每次返回就绪视图的方式实现它。
你现在正在做的只是通过他们的身份找到元素而不对他们做任何事情。您只需返回默认的膨胀行。
P.S。另请阅读有关性能问题的ViewHolder模式。
答案 1 :(得分:1)
在getView中尝试以下更改
public View getView(int position, View convertView, ViewGroup viewGroup) {
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.row, null);
TextView tvTS = (TextView) convertView.findViewById(R.id.tvTS);
TextView tvMessage = (TextView) convertView.findViewById(R.id.tvMessage);
ImageView indicator = (ImageView) convertView.findViewById(R.id.imgInd);
}
tvMessage.setText("......");
return convertView;
}
答案 2 :(得分:1)
您可以使用ViewHolder模式在列表中获得更好的性能
ViewHolder类:
public class ViewHolder{
public TextView message;
public TextView timestamp;
public ImageView indicator
}
然后在你的适配器getView方法中使用它以下方式:
public View getView(int position, View convertView, ViewGroup viewGroup) {
ViewHolder holder = null;
if(convertView == null ){
convertView = inflater.inflate(R.layout.<your_layout>, null);
holder = new ViewHolder();
holder.message = (TextView) convertView.findViewById(R.id.message);
holder.timestamp = (TextView) convertView.findViewById(R.id.timestamp);
holder.indicator = (ImageView) convertView.findViewById(R.id.indicator);
convertView.setTag(holder);
} else{
holder = (ViewHolder) convertView.getTag();
}
holder.message.setText(chat.get(position).<whatever>);
holder.timestamp.setText(chat.get(position).<whatever>);
holder.indicator.<method>
return convertView;
}
希望有所帮助。
BR, mybecks
答案 3 :(得分:1)
您似乎没有将数据设置为TextViews / ImageView。您需要在ChatAdapter的getView()方法中执行此操作,如下所示:
public View getView(int position, View convertView, ViewGroup viewGroup) {
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.row, null);
}
String chatMessage = getItem(position);
TextView tvTS = (TextView) convertView.findViewById(R.id.tvTS);
// TODO set timestamp
TextView tvMessage = (TextView) convertView
.findViewById(R.id.tvMessage);
//Set the message to the TextView
tvMessage.setText(chatMessage);
ImageView indicator = (ImageView) convertView.findViewById(R.id.imgInd);
// TODO set the image Resource according to message state
return convertView;
}
考虑使用自定义对象(而不是字符串列表)来保存消息,时间戳和要显示的消息状态指示符的类型。在这种情况下,你可以这样做
ChatMessage msgObj = getItem(position);
...
tvMessage.setText(msgObj.getMessage());
tvTS.setText(msgObj.getTimestamp());
if ( msgObj.getStatus() == ChatMessage.DELIVERED )
{
indicator.setBackgroundResource(R.drawable.delivered);
}
else if (....)