首先看一下最终的效果,显示了消息时间,用户昵称,用户头像。

大致实现方法:

  用最简单的ListView显示消息内容。

  不同的用户使用不同的消息布局文件,从而达到头像左右显示的效果,如上图有2个用户"Tony","Hill",头像分别显示在左右两边。

代码文件清单:

  主布局文件activity_main.xml:

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
tools:context=".MainActivity" >
<ListView
android:id="@+id/lv_message"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:layout_above="@+id/ll_send_1"
android:scrollbars="none"
android:divider="@null"
android:footerDividersEnabled="false">
</ListView>
<LinearLayout
android:id="@+id/ll_send_1"
android:layout_height="50dp"
android:layout_width="fill_parent"
android:orientation="horizontal"
android:layout_above="@+id/ll_send_2">
<EditText
android:id="@+id/et_tony_message"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="3"
android:hint="Tony请输入"/>
<Button
android:id="@+id/but_tony_send"
android:layout_height="fill_parent"
android:layout_width="0dp"
android:layout_weight="1"
android:text="send"/>
</LinearLayout>
<LinearLayout
android:id="@+id/ll_send_2"
android:layout_height="50dp"
android:layout_width="fill_parent"
android:orientation="horizontal"
android:layout_alignParentBottom="true">
<EditText
android:id="@+id/et_hill_message"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="3"
android:hint="Hill请输入"/>
<Button
android:id="@+id/but_hill_send"
android:layout_height="fill_parent"
android:layout_width="0dp"
android:layout_weight="1"
android:text="send"/>
</LinearLayout>
</RelativeLayout>

  头像位于左边的消息布局文件list_message_item_left.xml:

 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="@drawable/chat_list_item_background"
android:padding="6dp"> <LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_horizontal"> <TextView
android:id="@+id/tv_sendtime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#8B8B8B"
android:textSize="12sp"
android:text="15:03:15"/>
</LinearLayout> <RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"> <ImageView
android:id="@+id/iv_userhead"
android:layout_width="40dp"
android:layout_height="40dp"
android:background="@drawable/head_portrait_1"
android:focusable="false"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" /> <TextView
android:id="@+id/tv_username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginBottom="5dp"
android:textColor="#8B8B8B"
android:layout_toRightOf="@id/iv_userhead"
android:text="name"/> <TextView
android:id="@+id/tv_chatcontent"
android:layout_toRightOf="@id/iv_userhead"
android:layout_marginLeft="10dp"
android:layout_marginRight="40dp"
android:layout_below="@id/tv_username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:background="@drawable/message_text_background01"/>
</RelativeLayout>
</LinearLayout>

  头像位于右边的消息布局文件list_message_item_right.xml:

 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="@drawable/chat_list_item_background"
android:padding="6dp"> <LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_horizontal"> <TextView
android:id="@+id/tv_sendtime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#8B8B8B"
android:textSize="12sp"
android:text="15:03:15"/>
</LinearLayout>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp" > <ImageView
android:id="@+id/iv_userhead"
android:layout_width="40dp"
android:layout_height="40dp"
android:background="@drawable/head_portrait_2"
android:focusable="false"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true" /> <TextView
android:id="@+id/tv_username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:layout_marginBottom="5dp"
android:textColor="#8B8B8B"
android:layout_toLeftOf="@id/iv_userhead"
android:text="name"/> <TextView
android:id="@+id/tv_chatcontent"
android:layout_toLeftOf="@id/iv_userhead"
android:layout_marginRight="10dp"
android:layout_marginLeft="40dp"
android:layout_below="@id/tv_username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:background="@drawable/message_text_background02"/>
</RelativeLayout> </LinearLayout>

  主界面java代码文件MainActivity.java:

 public class MainActivity extends Activity implements OnClickListener{
EditText et_tony_message;
Button but_tony_send; EditText et_hill_message;
Button but_hill_send; ListView lv_message;
List<Message> list;
MessageAdapter adapter;
Handler handler=new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
} private void init() {
et_tony_message=(EditText) findViewById(R.id.et_tony_message);
but_tony_send=(Button) findViewById(R.id.but_tony_send);
but_tony_send.setOnClickListener(this); et_hill_message=(EditText) findViewById(R.id.et_hill_message);
but_hill_send=(Button) findViewById(R.id.but_hill_send);
but_hill_send.setOnClickListener(this); list=new ArrayList<Message>();
lv_message=(ListView) findViewById(R.id.lv_message);
adapter=new MessageAdapter();
lv_message.setAdapter(adapter);
} @Override
public void onClick(View v) {
/*Tony发送消息*/
if(v==but_tony_send){
/*验证*/
if(et_tony_message.getText()==null||et_tony_message.getText().toString().equals("")){
Toast.makeText(this, "消息不能为空", 0).show();
return ;
}
Message m=new Message();
m.setFrom_username("Tony");
m.setCreate_time(System.currentTimeMillis());
m.setText(et_tony_message.getText().toString());
sendMessage(m);
et_tony_message.setText("");
}
/*Hill发送消息*/
if(v==but_hill_send){
/*验证*/
if(et_hill_message.getText()==null||et_hill_message.getText().toString().equals("")){
Toast.makeText(this, "消息不能为空", 0).show();
return ;
}
Message m=new Message();
m.setFrom_username("Hill");
m.setCreate_time(System.currentTimeMillis());
m.setText(et_hill_message.getText().toString());
sendMessage(m);
et_hill_message.setText("");
}
}
private void sendMessage(Message m) {
list.add(m);
adapter.notifyDataSetChanged();
// lv_message.f
lv_message.setSelection(list.size()+1);
}
class MessageAdapter extends BaseAdapter{ @Override
public int getCount() {
return list.size();
} @Override
public Object getItem(int position) {
return list.get(position);
} @Override
public long getItemId(int position) {
return 0;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
Message message=list.get(position);
ViewHolder viewHolder=null;
// if(convertView==null){
if("Tony".equalsIgnoreCase(message.getFrom_username())){
convertView=parent.inflate(MainActivity.this, R.layout.list_message_item_left, null);
}else{
convertView=parent.inflate(MainActivity.this, R.layout.list_message_item_right, null);
}
viewHolder=new ViewHolder();
viewHolder.iv_userhead=(ImageView) convertView.findViewById(R.id.iv_userhead);
viewHolder.tv_chatcontent=(TextView) convertView.findViewById(R.id.tv_chatcontent);
viewHolder.tv_sendtime=(TextView) convertView.findViewById(R.id.tv_sendtime);
viewHolder.tv_username=(TextView) convertView.findViewById(R.id.tv_username);
// convertView.setTag(viewHolder);
// }else{
// viewHolder=(ViewHolder) convertView.getTag();
// } viewHolder.tv_chatcontent.setText(message.getText());
viewHolder.tv_sendtime.setText(new SimpleDateFormat("HH:mm:ss").format(new Date(message.getCreate_time())));
viewHolder.tv_username.setText(message.getFrom_username());
return convertView;
}
class ViewHolder{
public ImageView iv_userhead;
public TextView tv_username;
public TextView tv_chatcontent;
public TextView tv_sendtime;
}
}
}

  消息封装代码文件Message.java:

 public class Message {
private String from_username;/*发送者*/
private Long create_time;/*发送时间*/
private String text;/*消息内容*/
public String getFrom_username() {
return from_username;
} public Long getCreate_time() {
return create_time;
}
public void setCreate_time(Long create_time) {
this.create_time = create_time;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
} public void setFrom_username(String from_username) {
this.from_username = from_username;
} }

源码下载:http://www.apkbus.com/forum.php?mod=viewthread&tid=173419&extra=

简单模仿QQ聊天界面的更多相关文章

  1. QQ聊天界面的布局和设计(IOS篇)-第二季

    QQChat Layout - 第二季 本来第二季是快写好了, 也花了点功夫, 结果gitbook出了点问题, 给没掉了.有些细节可能会一带而过, 如有疑问, 相互交流进步~. 在第一季中我们完成了Q ...

  2. Qt 之 模仿 QQ登陆界面——样式篇

    一.简述 今天晚上花了半天时间从QQ登录界面抠了些图,顺便加了点样式基本上实现了QQ的登陆界面全部效果.虽不说100%相似,那也有99.99%相似了哈O(∩_∩)O. QQ好像从去年开始,登录界面有了 ...

  3. Objective-c——UI基础开发第八天(QQ聊天界面)

    一.知识点: QQ聊天界面 双模型的使用(dataModel和frameModel) UITextField的使用 通知的使用 拉伸图片的两种方法(slicing/image对象的resizeable ...

  4. QQ聊天界面的布局和设计(IOS篇)-第一季

    我写的源文件整个工程会再第二季中发上来~,存在百度网盘, 感兴趣的童鞋, 可以关注我的博客更新,到时自己去下载~.喵~~~ QQChat Layout - 第一季 一.准备工作 1.将假数据messa ...

  5. 高仿qq聊天界面

    高仿qq聊天界面,给有需要的人,界面效果如下: 真心觉得做界面非常痛苦,给有需要的朋友. chat.xml <?xml version="1.0" encoding=&quo ...

  6. [转]Android:布局实例之模仿QQ登录界面

    Android:布局实例之模仿QQ登录界面 预览图: 准备: 1.找到模仿对象 QQ登陆界面UI下载>>>>> 2.导入工程 3.查看布局结构和使用控件 其对应效果图分布 ...

  7. 在WEB项目中调用QQ通讯组件打开QQ聊天界面

    在很多WEB项目中,需要提供在线服务的功能,加上自己的联系方式,例如:QQ,不用添加QQ好友也可以交谈,那这到底是怎么实现的呢? 对于这个功能,需要提到一个组件,即“QQ通讯组件”.QQ通讯组件是一种 ...

  8. Android—简单的仿QQ聊天界面

    最近仿照QQ聊天做了一个类似界面,先看下界面组成(画面不太美凑合凑合呗,,,,):

  9. JS简单仿QQ聊天工具的制作

    刚接触JS,对其充满了好奇,利用刚学到的一点知识,写了一个简单的仿QQ聊天的东西,其中还有很多的不足之处,有待慢慢提高. 功能:1.在输入框中输入内容,点击发送,即可在上方显示所输入内容. 2.点击‘ ...

随机推荐

  1. Mongodb的常用语句

    模糊查询  regex(".*?\\"+questionContent+".*") String questionContent = "需求" ...

  2. TiDB 压力测试报告

    (转载自公众号DBATech) 一.测试环境 1.tidb 集群架构: 测试使用最基本的TiDB架构.即 3个tidb-server节点+ 3个tikv节点 + 3个pd节点. 2.tidb集群的部署 ...

  3. 解锁云原生 AI 技能 - 开发你的机器学习工作流

    按照上篇文章<解锁云原生 AI 技能 | 在 Kubernetes 上构建机器学习系统>搭建了一套 Kubeflow Pipelines 之后,我们一起小试牛刀,用一个真实的案例,学习如何 ...

  4. Ajax异步后台加载Html绑定不上事件

    因项目需要,需要实时从后台动态加载html,开发过程中,遇到事件绑定不上,后来百度一番,大概意思:ajax是异步加载的,页面一开始绑定事件的时候,后台数据还没有传过来,就绑定事件,这个时候找不到这个d ...

  5. PHP 日历函数手册

    PHP日历函数安装>>> 函数名称 描述 cal_days_in_month 返回某个历法中某年中某月的天数 cal_from_jd 转换Julian Day计数到一个支持的历法. ...

  6. webpack4 plugins 篇

    demo 代码点此,篇幅有限,仅介绍几个常用的. start 什么是 plugins ? While loaders are used to transform certain types of mo ...

  7. android studio学习----自动导包

    介绍一个最有用的设置,我们只有每次引用一些类的时候必须要导包,而Studio可以通过设置自动导包,简直太实用了. 到 Preferences -> Editor -> Auto Impor ...

  8. 简单聊聊实时视频rtmp

    背景: 由于经常接触实时视频, 对实时视频略有了解. 实时视频是将视频流实时上传到服务器端进行解析, 由RTMP服务器处理. RTMP 服务器 自己动手搭建一个rtmp, 本文在 Linux环境中搭建 ...

  9. HeadFirst设计模式--命令模式

    模式定义 命令模式(Command Pattern):将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化:对请求排队或者记录请求日志,以及支持可撤销的操作.命令模式是一种对象行为型模式 ...

  10. vuejs的导航栏固定

    https://blog.csdn.net/wang1006008051/article/details/78003974 博主文章,超级详细,上面传送们 不过博主的导航栏跳动比较明显,我自己做了修复 ...