一个聊天对话窗口,类似于微信。源代码来自EOE。我想扩展一下图片和消息时间等功能。聊天的消息能准确无误的传值到对应的控件,但是聊天的消息传送过去的时候会发送“错位”现象,比如2011-10-01 12:01第一条消息
2011-10-01 12:02第二条消息
2011-10-01 12:03第三条消息结果运行出来后就是部分的时间错位但内容不错位(而且消息的时间不是固定的错位):2011-10-01 12:01第一条消息
2011-10-01 12:02第二条消息
2011-10-01 12:01第三条消息
贴代码。希望高人指点一下!刚接触才几天,以前也没接触过JAVA……
package cn.itcast.test.chat.adapter;public class ChatMessage { public static final int MESSAGE_FROM = 0;
public static final int MESSAGE_TO = 1; private int direction; private String content; public ChatMessage(int direction, String content) {
super();
this.direction = direction;
this.content = content;
} public int getDirection() { return direction;}
public void setDirection(int direction) {this.direction = direction;} public void setContent(String content) {this.content = content;} public CharSequence getContent() {return content;}}package cn.itcast.test.chat.adapter;import java.util.List;import jinnuo.test.R;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.ImageSpan;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;public class ChattingAdapter extends BaseAdapter {
protected static final String TAG = "ChattingAdapter";
private Context context; private List<ChatMessage> chatMessages;
//private List<ChatMessage> chatSendTime; public ChattingAdapter(Context context, List<ChatMessage> messages) {
super();
this.context = context;
this.chatMessages = messages;
}
public int getCount() {
return chatMessages.size();
}
public Object getItem(int position) {
return chatMessages.get(position);
}
public long getItemId(int position) {
return position;
} public View getView(int position, View convertView , ViewGroup parent) {
ViewHolder holder = null;
ViewHolder holder1 = null; ChatMessage message = chatMessages.get(position);
String ChatListMsg [] =message.getContent().toString().split("#ApE8#");
if (convertView == null || (holder = (ViewHolder) convertView.getTag()).flag != message.getDirection())
{
holder = new ViewHolder();
holder1 = new ViewHolder();
holder.flag = ChatMessage.MESSAGE_FROM;
holder1.flag = ChatMessage.MESSAGE_FROM;
convertView = LayoutInflater.from(context).inflate(R.layout.chatting_item_from, null);
convertView.setTag(holder); }
holder.text = (TextView) convertView.findViewById(R.id.chatting_content_itv);//这个是绑定到消息内容控件
holder.text.setText(ChatListMsg[3].toString()+ "_" + ChatListMsg[2].toString()) ;
try{
holder1.text = (TextView) convertView.findViewById(R.id.chatting_time_tv);//这个是绑定到消息时间控件,另外这里不TRY就报错,我怀疑原因就在这里,但是死活搞不明白具体怎么弄
holder1.text.setText("_" + ChatListMsg[2].toString()) ;
}catch(Exception e){}
return convertView;
}
static class ViewHolder {
TextView text;
int flag;
}}<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout
android:orientation="vertical"
android:paddingLeft="6.0dip"
android:paddingRight="6.0dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:id="@+id/chatting_time_tv"
style="@style/ChattingUISplit" android:text="aaaaaa" android:gravity="left"/>
<TextView
android:id="@+id/chatting_content_itv"
android:autoLink="web"
android:background="@drawable/chatfrom_bg"
style="@style/ChattingUIText" />
</LinearLayout>
2011-10-01 12:02第二条消息
2011-10-01 12:03第三条消息结果运行出来后就是部分的时间错位但内容不错位(而且消息的时间不是固定的错位):2011-10-01 12:01第一条消息
2011-10-01 12:02第二条消息
2011-10-01 12:01第三条消息
贴代码。希望高人指点一下!刚接触才几天,以前也没接触过JAVA……
package cn.itcast.test.chat.adapter;public class ChatMessage { public static final int MESSAGE_FROM = 0;
public static final int MESSAGE_TO = 1; private int direction; private String content; public ChatMessage(int direction, String content) {
super();
this.direction = direction;
this.content = content;
} public int getDirection() { return direction;}
public void setDirection(int direction) {this.direction = direction;} public void setContent(String content) {this.content = content;} public CharSequence getContent() {return content;}}package cn.itcast.test.chat.adapter;import java.util.List;import jinnuo.test.R;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.ImageSpan;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;public class ChattingAdapter extends BaseAdapter {
protected static final String TAG = "ChattingAdapter";
private Context context; private List<ChatMessage> chatMessages;
//private List<ChatMessage> chatSendTime; public ChattingAdapter(Context context, List<ChatMessage> messages) {
super();
this.context = context;
this.chatMessages = messages;
}
public int getCount() {
return chatMessages.size();
}
public Object getItem(int position) {
return chatMessages.get(position);
}
public long getItemId(int position) {
return position;
} public View getView(int position, View convertView , ViewGroup parent) {
ViewHolder holder = null;
ViewHolder holder1 = null; ChatMessage message = chatMessages.get(position);
String ChatListMsg [] =message.getContent().toString().split("#ApE8#");
if (convertView == null || (holder = (ViewHolder) convertView.getTag()).flag != message.getDirection())
{
holder = new ViewHolder();
holder1 = new ViewHolder();
holder.flag = ChatMessage.MESSAGE_FROM;
holder1.flag = ChatMessage.MESSAGE_FROM;
convertView = LayoutInflater.from(context).inflate(R.layout.chatting_item_from, null);
convertView.setTag(holder); }
holder.text = (TextView) convertView.findViewById(R.id.chatting_content_itv);//这个是绑定到消息内容控件
holder.text.setText(ChatListMsg[3].toString()+ "_" + ChatListMsg[2].toString()) ;
try{
holder1.text = (TextView) convertView.findViewById(R.id.chatting_time_tv);//这个是绑定到消息时间控件,另外这里不TRY就报错,我怀疑原因就在这里,但是死活搞不明白具体怎么弄
holder1.text.setText("_" + ChatListMsg[2].toString()) ;
}catch(Exception e){}
return convertView;
}
static class ViewHolder {
TextView text;
int flag;
}}<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout
android:orientation="vertical"
android:paddingLeft="6.0dip"
android:paddingRight="6.0dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:id="@+id/chatting_time_tv"
style="@style/ChattingUISplit" android:text="aaaaaa" android:gravity="left"/>
<TextView
android:id="@+id/chatting_content_itv"
android:autoLink="web"
android:background="@drawable/chatfrom_bg"
style="@style/ChattingUIText" />
</LinearLayout>
解决方案 »
- android.content.ActivityNotFoundException: No Activity found to handle Intent
- 请问addView进来的东西怎么填满add它的父容器?
- Android中将图片转换为Base64时候OutOfMemoryError
- android gridView或listView拖拽
- handleMessage里面更新ListView内容
- android 端口问题
- 求助:有关文件读取问题!!!
- 难道google地图v2在国内就无人测试成功吗?
- android 类似数码管显示
- 【腾讯android的SDK】mTencent总是实例化失败,各位大神菜鸟求教!!!
- 怎样控制控制数字键盘的显示与隐藏
- Canvas与Bitmap画图的问题
//窗口代码
package cn.itcast.test.chat;import java.util.ArrayList;
import java.util.List;import cn.itcast.test.chat.adapter.ChatMessage;
import cn.itcast.test.chat.adapter.ChattingAdapter;import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.PopupWindow;public class MainActivity extends Activity {
protected static final String TAG = "MainActivity";
private ChattingAdapter chatHistoryAdapter;
private List<ChatMessage> messages = new ArrayList<ChatMessage>(); private ListView chatHistoryLv;
private Button sendBtn;
private EditText textEditor;
private ImageView sendImageIv;
private ImageView captureImageIv;
private View recording;
private PopupWindow menuWindow = null; @Override
public void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
super.onCreate(savedInstanceState);
setContentView(R.layout.chatting);
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.chatting_title_bar);
chatHistoryLv = (ListView) findViewById(R.id.chatting_history_lv);
setAdapterForThis();
sendBtn = (Button) findViewById(R.id.send_button);
textEditor = (EditText) findViewById(R.id.text_editor);
sendImageIv = (ImageView) findViewById(R.id.send_image);
captureImageIv = (ImageView) findViewById(R.id.capture_image);
sendBtn.setOnClickListener(l);
sendImageIv.setOnClickListener(l);
captureImageIv.setOnClickListener(l);
recording = findViewById(R.id.recording);
recording.setOnTouchListener(new View.OnTouchListener() { public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction(); switch (action) {
case MotionEvent.ACTION_UP:
v.setBackgroundResource(R.drawable.hold_to_talk_normal);
if (menuWindow != null)
menuWindow.dismiss();
Log.d(TAG, "---onTouchEvent action:ACTION_UP");
break;
case MotionEvent.ACTION_DOWN:
v.setBackgroundResource(R.drawable.hold_to_talk_pressed);
ViewGroup root = (ViewGroup) findViewById(R.id.chat_root);
View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.audio_recorder_ring, null);
menuWindow = new PopupWindow(view, 180, 180);
// @+id/recorder_ring
view.findViewById(R.id.recorder_ring).setVisibility(View.VISIBLE);
view.setBackgroundResource(R.drawable.pls_talk);
menuWindow.showAtLocation(root, Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL, 0, 0);
Log.d(TAG, "---onTouchEvent action:ACTION_DOWN");
// AudioRecorder recorder=new AudioRecorder(); break; } return true;
}
}); } // 设置adapter
private void setAdapterForThis() {
initMessages();
chatHistoryAdapter = new ChattingAdapter(this, messages);
chatHistoryLv.setAdapter(chatHistoryAdapter);
} // 为listView添加数据
private void initMessages() {
messages.add(new ChatMessage(ChatMessage.MESSAGE_FROM, "1#ApE8#" +"hello"));
messages.add(new ChatMessage(ChatMessage.MESSAGE_TO, "2#ApE8#" + "hello"));
messages.add(new ChatMessage(ChatMessage.MESSAGE_FROM, "3#ApE8#" +"你好吗?"));
messages.add(new ChatMessage(ChatMessage.MESSAGE_TO, "4#ApE8#" + "非常好!"));
messages.add(new ChatMessage(ChatMessage.MESSAGE_FROM, "5#ApE8#" +"欢迎光临我的博客,http://hi.csdn.net/lyfi01"));
messages.add(new ChatMessage(ChatMessage.MESSAGE_TO,"6#ApE8#" + "恩,好的,谢谢"));
} /**
* 按键时间监听
*/
private View.OnClickListener l = new View.OnClickListener() { public void onClick(View v) { if (v.getId() == sendBtn.getId()) {
String str = textEditor.getText().toString();
String sendStr;
if (str != null
&& (sendStr = str.trim().replaceAll("\r", "").replaceAll("\t", "").replaceAll("\n", "")
.replaceAll("\f", "")) != "") {
sendMessage(sendStr); }
textEditor.setText(""); } else if (v.getId() == sendImageIv.getId()) {
Intent i = new Intent();
i.setType("image/*");
i.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(i, Activity.DEFAULT_KEYS_SHORTCUT);
} else if (v.getId() == captureImageIv.getId()) {
Intent it = new Intent("android.media.action.IMAGE_CAPTURE");
startActivityForResult(it, Activity.DEFAULT_KEYS_DIALER);
}
} // 模拟发送消息
private void sendMessage(String sendStr) {
messages.add(new ChatMessage(ChatMessage.MESSAGE_TO, sendStr));
chatHistoryAdapter.notifyDataSetChanged();
} };}
//包cn.itcast.test.chat.adapter 中的 ChatMessage.java
package cn.itcast.test.chat.adapter;public class ChatMessage { public static final int MESSAGE_FROM = 0;
public static final int MESSAGE_TO = 1; private int direction;
private String content; public ChatMessage(int direction, String content) {
super();
this.direction = direction;
this.content = content;
} public int getDirection() {
return direction;
} public void setDirection(int direction) {
this.direction = direction;
} public void setContent(String content) {
this.content = content;
} public CharSequence getContent() {
return content;
}}//包cn.itcast.test.chat.adapter 中的 ChattingAdapter.java
package cn.itcast.test.chat.adapter;import java.util.List;import cn.itcast.test.chat.R;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;public class ChattingAdapter extends BaseAdapter {
protected static final String TAG = "ChattingAdapter";
private Context context; private List<ChatMessage> chatMessages; public ChattingAdapter(Context context, List<ChatMessage> messages) {
super();
this.context = context;
this.chatMessages = messages; }
public int getCount() {
return chatMessages.size();
}
public Object getItem(int position) {
return chatMessages.get(position);
}
public long getItemId(int position) {
return position;
} public View getView(int position, View convertView , ViewGroup parent) {
ViewHolder holder = null;
ViewHolder holder1 = null; ChatMessage message = chatMessages.get(position);
String ChatListMsg [] =message.getContent().toString().split("#ApE8#");
if (convertView == null || (holder = (ViewHolder) convertView.getTag()).flag != message.getDirection())
{
holder = new ViewHolder();
holder1 = new ViewHolder();
if (message.getDirection() == ChatMessage.MESSAGE_FROM) {
holder.flag = ChatMessage.MESSAGE_FROM;
holder1.flag = ChatMessage.MESSAGE_FROM;
convertView = LayoutInflater.from(context).inflate(R.layout.chatting_item_from, null);
} else {
holder.flag = ChatMessage.MESSAGE_TO;
holder1.flag = ChatMessage.MESSAGE_TO;
convertView = LayoutInflater.from(context).inflate(R.layout.chatting_item_to, null);
}
holder.text = (TextView) convertView.findViewById(R.id.chatting_content_itv);
holder1.text = (TextView) convertView.findViewById(R.id.chatting_time_tv);
holder1.text.setText(ChatListMsg[0]);
convertView.setTag(holder);
} holder.text.setText(ChatListMsg[1]+" _文字") ; return convertView;
}
/*public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
ChatMessage message = chatMessages.get(position);
if (convertView == null || (holder = (ViewHolder) convertView.getTag()).flag != message.getDirection()) { holder = new ViewHolder();
if (message.getDirection() == ChatMessage.MESSAGE_FROM) {
holder.flag = ChatMessage.MESSAGE_FROM; convertView = LayoutInflater.from(context).inflate(R.layout.chatting_item_from, null);
} else {
holder.flag = ChatMessage.MESSAGE_TO;
convertView = LayoutInflater.from(context).inflate(R.layout.chatting_item_to, null);
} holder.text = (TextView) convertView.findViewById(R.id.chatting_content_itv);
convertView.setTag(holder);
}
holder.text.setText(message.getContent()); return convertView;
}*/
//优化listview的Adapter
static class ViewHolder {
TextView text;
int flag;
}}
package cn.itcast.test.ui;
import cn.itcast.test.chat.R;
import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.LinearLayout;public class ResizeLayout extends LinearLayout { int count = 0;
int count1 = 0;
int count2 = 0;
//定义默认的软键盘最小高度,这是为了避免onSizeChanged在某些下特殊情况下出现的问题。
private static final int SOFTKEYPAD_MIN_HEIGHT = 50;
private Handler uiHandler = new Handler();
private static final String TAG = "ResizeLayout"; public ResizeLayout(Context context) {
super(context);
} public ResizeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
} @Override
protected void onSizeChanged(int w, final int h, int oldw, final int oldh) {
super.onSizeChanged(w, h, oldw, oldh); Log.i(TAG, "onSizeChanged " + count++ + "=>onResize called! w=" + w + ",h=" + h + ",oldw=" + oldw + ",oldh=" + oldh); uiHandler.post(new Runnable() {
public void run() {
if (oldh - h > SOFTKEYPAD_MIN_HEIGHT)
// 必须设置为View.GONE不占空间
findViewById(R.id.talk_panel).setVisibility(View.GONE);
else
findViewById(R.id.talk_panel).setVisibility(View.VISIBLE);
}
});
}
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
Log.e(TAG, "onLayout " + count1++ + "=>OnLayout called! l=" + l + ", t=" + t + ",r=" + r + ",b=" + b);
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec); Log.e(TAG, "onMeasure " + count2++ + "=>onMeasure called! widthMeasureSpec=" + widthMeasureSpec + ", heightMeasureSpec="
+ heightMeasureSpec); }
}
//布局XML<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout
android:orientation="vertical"
android:paddingLeft="6.0dip"
android:paddingRight="6.0dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:id="@+id/chatting_time_tv"
style="@style/ChattingUISplit" />
<TextView
android:id="@+id/chatting_content_itv"
android:autoLink="web"
android:background="@drawable/chatfrom_bg"
style="@style/ChattingUIText" />
</LinearLayout>
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout android:orientation="vertical" android:paddingLeft="6.0dip" android:paddingRight="6.0dip" android:layout_width="fill_parent" android:layout_height="wrap_content"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:id="@+id/chatting_time_tv"
style="@style/ChattingUISplit" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1.0" />
<ImageView
android:id="@+id/chatting_state_iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:autoLink="web"
android:id="@+id/chatting_content_itv"
android:background="@drawable/chatto_bg"
style="@style/ChattingUIText" />
</LinearLayout>
</LinearLayout>
代码就这些。这个代码是我在EOE的这篇帖子(http://www.eoeandroid.com/thread-74595-1-1.html)略加修改的,其实也没修改,就把原来没有显示的用于显示消息时间的空间拿出来绑定了一下…
感谢您的回复,能否详细指点一下我该怎么添加 convertView.setTag(holder1); ?
我尝试 holder.text = (TextView) convertView.findViewById(R.id.chatting_content_itv);
holder1.text = (TextView) convertView.findViewById(R.id.chatting_time_tv);
holder1.text.setText(ChatListMsg[0]);
convertView.setTag(holder);
convertView.setTag(holder1);但这样更乱了
和convertView.setTag(holder);的问题你参照apidemo里面Adapter的用法改下就好了,判断里面只要 if (convertView == null )后面convertView.setTag(holder)放外面就行了测试通过,就是这个毛病,改过来就好了!!!!!