Fragment实践之聊天窗体
前几天刚学了android的fragment,总是停留在简单的demo,也许永远都学不会。
今天,我要动手向我的聊天软件开刀。今天。用Fragment来实现一个例如以下图效果的聊天界面。
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvTWluaU1pY2FsbA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" width="350" height="600" alt="">
从图中能够看出,这个activity是由三部分组成:1)抬头,包括一个返回button。对话用户的名字和一个对话好友的信息button;2)一个聊天的历史记录;3)底部是输入,包括很多其它丰富的输入button。文本输入以及发送button。
第一步:定义好资源文件
资源文件主要是布局文件。布局文件所用到的其它资源我们在此就不再做介绍了
new_chat_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:id="@+id/chat_title_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
</LinearLayout> <LinearLayout
android:id="@+id/chat_history_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:background="@color/white3"
android:orientation="horizontal">
</LinearLayout>
<LinearLayout
android:id="@+id/chat_bottom_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
</LinearLayout>
<LinearLayout
android:id="@+id/chat_multifunc_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
</LinearLayout> </LinearLayout>
其效果图例如以下:空白的
接下来。我们创建抬头的fagment的layout文件
frag_chat_title_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="60dip"
android:background="@drawable/skinpic_blue"
android:gravity="center_vertical" > <ImageButton
android:id="@+id/title_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/title_btn_l_selector"
android:padding="0.0dip"
android:src="@drawable/title_btn_back" /> <TextView
android:id="@+id/to_chat_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:ellipsize="end"
android:gravity="center"
android:singleLine="true"
android:textColor="#ffffffff"
android:textSize="18.0sp"
android:text="张三"
android:textStyle="bold" /> <ImageButton
android:id="@+id/user_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/title_btn_r_selector"
android:padding="0.0dip"
android:src="@drawable/popbar_icon_info" /> </LinearLayout>
其效果例如以下:
接下来我们定义聊天记录的布局文件
frag_history_list_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:background="@color/white3"
android:orientation="vertical" > <ListView
android:id="@+id/chat_list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:background="@color/white3"
android:divider="@null"
android:listSelector="@android:color/transparent" /> </LinearLayout>
其效果如图:
定义底部的输入布局
frag_chat_bottom_layout.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:background="#FFEEEEEE" >
<Button
android:id="@+id/multi_function_btn"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginLeft="5dip"
android:background="@drawable/plus_btn"
android:text=" " /> <EditText
android:id="@+id/chat_content"
android:textColor="#000000"
android:layout_width="wrap_content"
android:layout_height="45dip"
android:background="@anim/edit_text"
android:layout_weight="1.0"
android:hint="请输入内容"
android:inputType="textWebEditText"
android:text="" /> <Button
android:id="@+id/chat_sendbtn"
android:layout_marginLeft="5dip"
android:background="@drawable/button"
android:layout_width="wrap_content"
android:layout_height="45dip"
android:text=" 发送 " /> </LinearLayout>
其效果如图所看到的
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvTWluaU1pY2FsbA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">
至此,我们的布局文件算是完毕了。接下来。我们须要定义三个Fragment来关联这三个碎片布局
1。抬头
FragChatTitle.java
package com.sanliao.eim.activity.im; import com.sanliao.eim.R;
import com.sanliao.eim.manager.ContacterManager;
import com.sanliao.eim.manager.XmppConnectionManager;
import com.sanliao.eim.model.User;
import com.sanliao.eim.util.StringUtil; import android.app.Activity;
import android.app.Fragment;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView; public class FragChatTitle extends Fragment { private final static String TAG="FragChatTitle";
NewChatActivity activity=null;
private ImageView titleBack;//返回button
private TextView tvChatTitle;//对话username
private ImageButton userInfo;//用户信息button
private User user;// 聊天人
private String to_name; @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.d(TAG, "onCreateView");
return inflater.inflate(R.layout.frag_chat_title_layout, container, false);
} @Override
public void onAttach(Activity activity) {
super.onAttach(activity);
Log.d(TAG, "onAttach");
} @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate");
} @Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.d(TAG, "onActivityCreated");
activity=(NewChatActivity)getActivity();//获得所在activity,并转为newchatactivity
//返回button
titleBack = (ImageView) getActivity().findViewById(R.id.title_back);
titleBack.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
getActivity().finish();
}
});
tvChatTitle = (TextView) getActivity().findViewById(R.id.to_chat_name);
user = ContacterManager.getByUserJid(activity.getTo(), XmppConnectionManager
.getInstance().getConnection());
if (null == user) {
to_name = StringUtil.getUserNameByJid(activity.getTo());
} else {
to_name = user.getName() == null ? user.getJID() : user.getName(); }
tvChatTitle.setText(to_name);//将username设置到title
//用户信息
userInfo = (ImageButton)activity. findViewById(R.id.user_info);
userInfo.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setClass(activity, FriendInfoActivity.class);
startActivity(intent);
}
});
} @Override
public void onStart() {
super.onStart();
Log.d(TAG, "onStart");
} @Override
public void onResume() {
super.onResume();
Log.d(TAG, "onResume");
} @Override
public void onPause() {
super.onPause();
Log.d(TAG, "onPause");
} @Override
public void onStop() {
super.onStop();
Log.d(TAG, "onStop");
} @Override
public void onDestroyView() {
super.onDestroyView();
Log.d(TAG, "onDestroyView");
} @Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy");
} @Override
public void onDetach() {
super.onDetach();
Log.d(TAG, "onDetach");
} }
定义聊天记录的Fragment
FragChatHistory.java
package com.sanliao.eim.activity.im; import java.util.List; import com.sanliao.eim.R; import com.sanliao.eim.manager.MessageManager;
import com.sanliao.eim.model.IMMessage;
import com.sanliao.eim.model.User;
import com.sanliao.eim.util.StringUtil; import android.app.Activity;
import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView; public class FragChatHistory extends Fragment { private final static String TAG="FragChatHistory";
private MessageListAdapter adapter = null;
private ListView listView;
private int recordCount;
private View listHead;
private Button listHeadButton;
private User user;// 聊天人 private NewChatActivity activity=null; @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.d(TAG, "onCreateView");
return inflater.inflate(R.layout.frag_history_list_layout, container, false);
} @Override
public void onAttach(Activity activity) {
super.onAttach(activity);
Log.d(TAG, "onAttach");
} @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate");
} @Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.d(TAG, "onActivityCreated");
activity=(NewChatActivity) getActivity(); listView = (ListView) activity.findViewById(R.id.chat_list);
listView.setCacheColorHint(0);
adapter = new MessageListAdapter(activity, activity.getMessages(),
listView); // 头 LayoutInflater mynflater = LayoutInflater.from(activity);
listHead = mynflater.inflate(R.layout.chatlistheader, null);
listHeadButton = (Button) listHead.findViewById(R.id.buttonChatHistory);
listHeadButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent in = new Intent(activity, ChatHistoryActivity.class);
in.putExtra("to", activity.getTo());
startActivity(in);
}
});
listView.addHeaderView(listHead);
listView.setAdapter(adapter); } @Override
public void onStart() {
super.onStart();
Log.d(TAG, "onStart");
} @Override
public void onResume() {
super.onResume();
Log.d(TAG, "onResume"); recordCount = MessageManager.getInstance((NewChatActivity)getActivity())
.getChatCountWithSb(((NewChatActivity)getActivity()).getTo());
if (recordCount <= 0) {
listHead.setVisibility(View.GONE);
} else {
listHead.setVisibility(View.VISIBLE);
}
adapter.refreshList(((NewChatActivity)getActivity()).getMessages());
} @Override
public void onPause() {
super.onPause();
Log.d(TAG, "onPause");
} @Override
public void onStop() {
super.onStop();
Log.d(TAG, "onStop");
} @Override
public void onDestroyView() {
super.onDestroyView();
Log.d(TAG, "onDestroyView");
} @Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy");
} @Override
public void onDetach() {
super.onDetach();
Log.d(TAG, "onDetach");
} public MessageListAdapter getAdapter()
{
return adapter ;
}
//////////////////////////////////////////////////////////////////
public class MessageListAdapter extends BaseAdapter { private List<IMMessage> items;
private Context context;
private ListView adapterList;
private LayoutInflater inflater; public MessageListAdapter(Context context, List<IMMessage> items,
ListView adapterList) {
this.context = context;
this.items = items;
this.adapterList = adapterList;
} public void refreshList(List<IMMessage> items) {
this.items = items;
this.notifyDataSetChanged();
adapterList.setSelection(items.size() - 1);
} @Override
public int getCount() {
return items == null ? 0 : items.size();
} @Override
public Object getItem(int position) {
return items.get(position);
} @Override
public long getItemId(int position) {
return position;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
IMMessage message = items.get(position);
if (message.getMsgType() == 0) {
convertView = this.inflater.inflate(
R.layout.formclient_chat_in, null);
} else {
convertView = this.inflater.inflate(
R.layout.formclient_chat_out, null);
}
TextView useridView = (TextView) convertView
.findViewById(R.id.formclient_row_userid);
TextView dateView = (TextView) convertView
.findViewById(R.id.formclient_row_date);
TextView msgView = (TextView) convertView
.findViewById(R.id.formclient_row_msg);
if (message.getMsgType() == 0) {
if (null == user) {
useridView.setText(StringUtil.getUserNameByJid(((NewChatActivity)getActivity()).to));
} else {
useridView.setText(user.getName());
} } else {
useridView.setText("我");
}
dateView.setText(message.getTime());
msgView.setText(message.getContent());
return convertView;
} } }
定义底部Fragment
FragChatBottom.java
package com.sanliao.eim.activity.im; import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast; import com.sanliao.eim.R; public class FragChatBottom extends Fragment {
private final static String TAG="FragChatBottom";
private EditText messageInput = null;
private Button messageSendBtn = null; @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.d(TAG, "onCreateView");
return inflater.inflate(R.layout.frag_chat_bottom_layout, container, false);
} @Override
public void onAttach(Activity activity) {
super.onAttach(activity);
Log.d(TAG, "onAttach");
} @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate");
} @Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.d(TAG, "onActivityCreated");
messageInput = (EditText) getActivity().findViewById(R.id.chat_content);
messageSendBtn = (Button) getActivity().findViewById(R.id.chat_sendbtn);
messageSendBtn.setOnClickListener(new View.OnClickListener() { @Override
public void onClick(View v) {
String message = messageInput.getText().toString();
if ("".equals(message)) {
Toast.makeText(getActivity(), "不能为空",
Toast.LENGTH_SHORT).show();
} else { try {
((NewChatActivity)getActivity()).sendMessage(message);
messageInput.setText("");
} catch (Exception e) {
((NewChatActivity)getActivity()).showToast("信息发送失败");
messageInput.setText(message);
}
((NewChatActivity)getActivity()).closeInput();
}
}
});
} @Override
public void onStart() {
super.onStart();
Log.d(TAG, "onStart");
} @Override
public void onResume() {
super.onResume();
Log.d(TAG, "onResume");
} @Override
public void onPause() {
super.onPause();
Log.d(TAG, "onPause");
} @Override
public void onStop() {
super.onStop();
Log.d(TAG, "onStop");
} @Override
public void onDestroyView() {
super.onDestroyView();
Log.d(TAG, "onDestroyView");
} @Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy");
} @Override
public void onDetach() {
super.onDetach();
Log.d(TAG, "onDetach");
} }
最后,我们须要在NewChatActivity中将这三个Fragment组装起来。
NewChat.java
package com.sanliao.eim.activity.im; import java.util.List; import org.jivesoftware.smackx.InitStaticCode; import com.sanliao.eim.R;
import com.sanliao.eim.model.IMMessage; import android.app.Activity;
import android.os.Bundle; public class NewChatActivity extends AChatActivity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.new_chat_layout); init(); } public void init()
{
FragChatTitle fragChatTitle = new FragChatTitle();
getFragmentManager().beginTransaction().replace(R.id.chat_title_layout,fragChatTitle).commit();
FragChatHistory fragChatHistory=new FragChatHistory();
getFragmentManager().beginTransaction().replace(R.id.chat_history_layout,fragChatHistory).commit();
FragChatBottom fragChatBottom=new FragChatBottom();
getFragmentManager().beginTransaction().replace(R.id.chat_bottom_layout,fragChatBottom).commit();
} @Override
protected void receiveNewMessage(IMMessage message) {
// TODO Auto-generated method stub } @Override
protected void refreshMessage(List<IMMessage> messages) {
// TODO Auto-generated method stub
FragChatHistory fragment = (FragChatHistory ) getFragmentManager().findFragmentById(R.id.chat_history_layout);
fragment.getAdapter().refreshList(messages); } }
对于这个类。大家看到了它继承AchatActivity。关于这个类图结构,大家最好翻阅一下之前的一篇文章:《三僚智能家居软件设计》
http://blog.csdn.net/minimicall/article/details/38680087
好,跑起来。
就会得到如图1所看到的的效果。好,打完收工。
Fragment实践之聊天窗体的更多相关文章
- 最佳实践扩展Windows窗体DataGridView控件 .net 4.5 附示例代码
Windows窗体DataGridView控件的性能调优.net 4.5 在处理大量数据时, DataGridView 控制可以消耗大量的内存开销,除非你仔细地使用它. 在客户有限的内存,你可以避 ...
- Knockout : 实现复杂的web聊天窗体
公司以前一个同事写的这个聊天的窗体,由于是采用了html拼接的方式,外加处理的时候没有合理的划分职责,导致页面js代码量非常庞大(1500行左右).现在这哥们离职了,苦的是我们剩下的人,不多说,我先去 ...
- Socket实现仿QQ聊天(可部署于广域网)附源码(4)-加入数据库系统搭建完成
1.前言 这是本系列的第四篇文章,上一篇我们讲到实现了客户端对客户端的抖屏与收发各种类型文件,本篇文章我们加入SQLServer数据库实现登录与好友的添加等功能,并对界面做了美化处理.向往常一样我会把 ...
- 【笔记】Fragment使用
1.静态加载 1.1 首先定义每一个Fragment的布局文件. 1.2 创建每个fragment类,需要继承Fragment.并使用onCreateView()的inflater.inflate() ...
- paip.提升效率--gui 的选择--swing最佳实践swt awt
paip.提升效率--gui 的选择--swing最佳实践swt awt ////////////////弹出消息框. ////////////////myeclipse swing 开发最佳实践.. ...
- MDI窗体 的再度思考
早在敲学生管理系统的时候,青山师哥就跟我说过 MDI 窗体 跟 子窗体的事情,当时只是简单的查询.小小的用了一下,没有太在意. 当再次面对着这个东西更深层的时候才想起师哥那句话.“好好研究一下这个东 ...
- Android仿微信界面--使用Fragment实现(慕课网笔记)
1 效果图 这里我们没有实现滑动切换view的功能 2 具体实现: 2.1 布局文件:top.xml, bottom.xml,tab01.xml,tab02.xml,tab03.xml,tab04. ...
- [Java聊天室server]实战之五 读写循环(服务端)
前言 学习不论什么一个稍有难度的技术,要对其有充分理性的分析,之后果断做出决定---->也就是人们常说的"多谋善断":本系列尽管涉及的是socket相关的知识,但学习之前,更 ...
- 单页WEB应用(三),Chat聊天模块
Chat 聊天模块 这个模块应该就是该书全篇的唯一一个模块吧,后面差点儿全部的篇章都环绕这个模块去实现的,只是就通过这一个模块的实现和上线,也能体现单页应用开发到公布上线的整个过程,毕竟后面的数据.通 ...
随机推荐
- vue 异步请求数据后,用v-if,显示组件,这样初始化的值就在开始的时候传进去了
请求到数据才会有的一个组件,并把数据传进组件中 https://www.cnblogs.com/LuckyWinty/p/6246698.html
- Vue项目结构梳理
Vue项目结构图: 简单介绍目录结构 build目录是一些webpack的文件,配置参数什么的,一般不用动 config是vue项目的基本配置文件 node_modules是项目中安装的依赖模块 sr ...
- iOS 6 的 Smart App Banners 介绍和使用
iOS 6 的 Smart App Banners 介绍和使用 Denis 留言: 10 浏览:4890 文章目录[隐藏] 什么是 Smart App Banners 在你的网站添加 Smart Ap ...
- LCIS 最长上升公共子序列问题
首先点名一个串叫 L1,另一个叫L2. 明显的是一个DP,那么我们来探讨下如何求得答案. 朴素的算法 首先我们定义状态$dp[ i ][ j ]$表示L1中前i个与L2中前j个的最长公共上升子序列. ...
- 整理几个牛人博客以及OJ
Blogs 陈立杰(wjmzbmr):http://wjmzbmr.com/ 飘过的小牛:http://blog.csdn.net/niushuai666 王垠:http://www.yinwang. ...
- python UDP-数据报协议
基于udp协议通信的套接字 服务端 from socket import * server = socket(AF_INET, SOCK_DGRAM) # SOCK_DGRAM=>数据报协议 s ...
- scp免密码拷贝和ssh免密码登录
版权声明:本文为博主原创文章,未经允许不得转载. 在平常的工作中经常在两个服务器之间传输文件,而且经常从本地远程登录服务器,每次都要输入密码显然很没效率,这时候该怎么办呢? 首先假设服务器A和B,要想 ...
- Linux组和提权
目 录 第1章 组命名管理** 1 1.1 group组信息和密码信息 1 1.1.1 /etc/group 组账户信息 1 1.1.2 /etc/gshadow 组密码信息 ...
- 5.12-leepcode 作业详解
leepcode 作业详解 1.给定一个整数数组,判断是否存在重复元素.如果任何值在数组中出现至少两次,函数返回 true.如果数组中每个元素都不相同,则返回 false. 正确解答 class So ...
- 剑指Offer(书):替换空格
题目:请实现一个函数,将一个字符串中的每个空格替换成“%20”.例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy. 分析:通常来说,这样的题有两种方式 ...