Fragment实践之聊天窗口

前几天刚学了android的fragment,总是停留在简单的demo,或许永远都学不会。

今天,我要动手向我的聊天软件开刀。今天,用Fragment来实现一个如下图效果的聊天界面。

从图中可以看出,这个activity是由三部分组成:1)抬头,包含一个返回按钮,对话用户的名字和一个对话好友的信息按钮;2)一个聊天的历史记录;3)底部是输入,包含更多丰富的输入按钮,文本输入以及发送按钮。

第一步:定义好资源文件

资源文件主要是布局文件,布局文件所用到的其他资源我们在此就不再做介绍了

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>

其效果如图所示


至此,我们的布局文件算是完成了。接下来,我们需要定义三个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;//返回按钮
	private TextView tvChatTitle;//对话用户名
	private ImageButton userInfo;//用户信息按钮
	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
        //返回按钮
    	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);//将用户名设置到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所示的效果。好,打完收工。

时间: 2024-08-26 05:54:42

Fragment实践之聊天窗口的相关文章

最佳实践之Android代码规范

命名规范 包命名规范 采用反域名命名规则,包名全部小写,连续的单词只是简单地连接起来,不使用下划线,一级包名为com,二级包名为xxx(可以是公司域名或者个人命名),三级包名根据应用进行命名,四级包名为模块名或层级名.如: com.isa.crm.activity |com.isa.crm.adapter JAVA类命名规范 采用大驼峰式命名法,尽量避免缩写,除非该缩写是众所周知的,比如HTML,URL,如果类名称包含单词缩写,则单词缩写的每个字母均应大写.如: Product | Produc

安卓简单app开发实践,代码完成后没报错,但功能就是无法使用,学生菜鸟,求指导

问题描述 安卓简单app开发实践,代码完成后没报错,但功能就是无法使用,学生菜鸟,求指导 想把网上一个简单记事本的功能(编辑,保存,修改,删除)添加入一个含三个Fragment的app框架中,但添加并把提示的错误修改后发现功能根本不管用,图标都不能点击,运行结果中console显示[2015-07-14 22:44:42 - ddms] Can't bind to local 8700 for debugger. 解决方案 看下防火墙和杀毒软件设置,提示是端口没法绑定. 解决方案二: 直接使用真

Android基础之Fragment与Activity交互详解

以下小编就为大家介绍一下Fragment跟Activity之间的关系.需要的朋友可以过来参考下   今天继续讲解Fragment组件的特性,主要是跟Activity的交互和生命周期的关系,我们前面已经说过Fragment是依赖于Activity的,而且生命周期也跟Activity绑定一起.下面我们看看Fragment跟Activity的关系. 1.为Activity创建事件回调方法在 一些情况下, 你可能需要一个fragment与activity分享事件. 一个好的方法是在fragment中定义

Android事件总线分发库EventBus3.0的简单讲解与实践

Android事件总线分发库EventBus的简单讲解与实践 导语,EventBus大家应该不陌生,EventBus是一款针对Android优化的发布/订阅事件总线.主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,线程之间传递消息.优点是开销小,代码更优雅.以及将发送者和接收者解耦.反正能帮助我们快速开发,这个确实是个好东西,其实鸿洋大神已经对源码作了一个较全面的剖析了 Android EventBus源码解析 带你深入理解Ev

【Andorid X 项目笔记】嵌套Fragment的使用(5)

前言  之前的文章有介绍ActivityGroup,不少人问嵌套使用的问题,同样的需求在Fragment中也存在,幸好在最新的Android support 包已经支持这一特性!这里就跳过Fragment的介绍,需要注意的是TabActivity已经被标记为弃用(deprecated).   声明 欢迎转载,但请保留文章原始出处:) 博客园:http://www.cnblogs.com 农民伯伯: http://www.cnblogs.com/over140/    正文 一.准备 关于最新的A

React native for Android 初步实践

Facebook 于2015年9月15日推出react native for Android 版本, 加上2014年底已经开源的IOS版本,至此RN (react-native)真正成为跨平台的客户端框架.本篇主要是从分析代码入手,探讨一下RN在安卓平台上是如何构建一套JS的运行框架. 一. 整体架构 RN 这套框架让 JS开发者可以大部分使用JS代码就可以构建一个跨平台APP. Facebook官方说法是learn once, run everywhere, 即在Android . IOS.

HTTP2总结及简单实践总结

本文讲的是HTTP2总结及简单实践总结,在总结http2之前先来回顾下http的发展历史.以下三张图片来自 Jerry Qu HTTP/0.9 (1991) HTTP/1.0 (1996) HTTP/1.1 (1999) HTTP通信过程 众所周知,http是基于tcp之上的应用层协议,即在tcp连接建立之后,在tcp的链路上传送数据. 首先进行TCP连接,三次握手, C --(SYN{k})--> S , S --(ACK{k+1}&SYN{j})--> C , C --ACK{j+

深入实践Spring

深入实践Spring Boot 陈韶健 著 图书在版编目(CIP)数据 深入实践Spring Boot / 陈韶健著. -北京:机械工业出版社,2016.10 ISBN 978-7-111-55088-4 I. 深- II. 陈- III. JAVA语言-程序设计 IV. TP312 中国版本图书馆CIP数据核字(2016)第244089号 深入实践Spring Boot 出版发行:机械工业出版社(北京市西城区百万庄大街22号 邮政编码:100037) 责任编辑:李 艺 责任校对:殷 虹 印 刷

[Android]Fragment生命周期

官方文档中有详细的文字说明,不过最好还是实践下,熟悉过程.http://developer.android.com/guide/components/fragments.html 一.Activity的生命周期图: 二.Fragment生命周期图 三.对比图 四.测试代码:   [java] view plaincopy   package com.goso.testapp;      import android.app.Activity;   import android.app.ListF