UI界面编写(仿QQ聊天界面)
UI界面编写实战
这里我们模拟QQ聊天的主界面,编写一个简单的聊天界面。
项目描述
首先搭建我们的主界面,在最上边放一个标题栏,然后是一个ListView,用于展示发送的消息,最下边是选择要发送的表情,内容类型,一个发送框和一个发送按钮。
先写一个颜色的资源
<?xml version="1.0" encoding="utf-8"?>
<resources><color name="light_blue">#18B4ED</color><color name="gray">#EBECEE</color><color name="white">#ffffff</color>
</resources>
然后就是主界面
<LinearLayout 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:orientation="vertical"tools:context=".MainActivity"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"android:background="@color/light_blue"android:padding="15dp"><ImageViewandroid:layout_width="30dp"android:layout_height="30dp"android:src="@mipmap/jzw"/><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:textSize="20sp"android:textColor="@color/white"android:text="消息"/><TextViewandroid:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:textSize="25sp"android:textColor="@color/white"android:gravity="center"android:text="模拟聊天"/><ImageViewandroid:layout_width="30dp"android:layout_height="30dp"android:src="@mipmap/login_icon01"/><ImageViewandroid:layout_width="30dp"android:layout_height="30dp"android:src="@mipmap/personal_normal"android:layout_marginLeft="10dp"/></LinearLayout><ListViewandroid:id="@+id/listview"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:background="@drawable/chat_background"android:divider="#0000"></ListView><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"android:background="@color/gray"android:layout_margin="10dp"android:gravity="center"><ImageViewandroid:id="@+id/biaoqing"android:layout_width="30dp"android:layout_height="30dp"android:src="@mipmap/eol"/><ImageViewandroid:id="@+id/choose"android:layout_width="30dp"android:layout_height="30dp"android:src="@mipmap/addcommodity"android:layout_marginLeft="10dp"/><EditTextandroid:id="@+id/edittext"android:layout_width="0dp"android:layout_height="30dp"android:layout_weight="1"android:background="@color/white"android:layout_marginLeft="10dp"/><Buttonandroid:id="@+id/send"android:layout_width="wrap_content"android:layout_height="30dp"android:text="发送"android:background="@drawable/button"android:layout_marginLeft="10dp"/></LinearLayout>
</LinearLayout>
然后是我们的drawable文件的内容:
为发送按钮写了一个shape:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"><corners android:radius="5dp"/><solid android:color="@color/light_blue"/>
</shape>
为展示消息的ListVeiw设置一个背景,也是用一个渐变色。
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"><gradientandroid:startColor="#ACE7EF"android:centerColor="#CAE0D9"android:endColor="#E7D9C5"android:angle="270"></gradient>
</shape>
为昵称前边的标签设置一个背景
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"><corners android:radius="15dp"/><solid android:color="#86D070"/><padding android:left="20dp" android:right="20dp"/>
</shape>
接着,因为我们要发送和接收消息,让接收的消息呈现在左边,发送的消息呈现在右边,所以要为两边各写一个消息的布局。
左边的布局:
<?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"><TextViewandroid:id="@+id/time"android:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center"android:padding="10dp"android:text="星期五 14:29" /><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><ImageViewandroid:id="@+id/touxiang"android:layout_width="60dp"android:layout_height="60dp"android:src="@mipmap/weheartit" /><LinearLayoutandroid:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:orientation="vertical"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><TextViewandroid:id="@+id/title"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/textbackground"android:text="营长"android:textColor="@color/white"android:textSize="15sp" /><TextViewandroid:id="@+id/name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textSize="16sp"android:text="美女"android:layout_marginLeft="10dp"/></LinearLayout><TextViewandroid:id="@+id/message"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginRight="60sp"android:layout_marginTop="10sp"android:background="@mipmap/eng"/></LinearLayout></LinearLayout>
</LinearLayout>
右边的布局:
<?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"><TextViewandroid:id="@+id/time"android:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center"android:padding="10dp"android:text="星期五 14:29" /><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><LinearLayoutandroid:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:gravity="right"android:orientation="vertical"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="right"android:orientation="horizontal"><TextViewandroid:id="@+id/name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textSize="16sp"android:text="美女"android:layout_marginLeft="10dp"/><TextViewandroid:id="@+id/title"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/textbackground"android:text="营长"android:textColor="@color/white"android:textSize="15sp" /></LinearLayout><TextViewandroid:id="@+id/message"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="60sp"android:layout_marginTop="10sp"android:background="@mipmap/qqright"/></LinearLayout><ImageViewandroid:id="@+id/touxiang"android:layout_width="60dp"android:layout_height="60dp"android:src="@mipmap/weheartit" /></LinearLayout>
</LinearLayout>
接着定义我们消息内容的实体类ChatMessage.java
/*** Created by Administrator on 2015/8/31.*/
public class ChatMessage {private int touxiang;//头像private String title;//标签private String name;//昵称private String message;//消息内容private long time;//发送时间private int type;//消息类型,即左边或者右边public ChatMessage(int touxiang, String title, String name, String message, long time) {this.touxiang = touxiang;this.title = title;this.name = name;this.message = message;this.time = time;}public int getType() {return type;}public void setType(int type) {this.type = type;}public int getTouxiang() {return touxiang;}public void setTouxiang(int touxiang) {this.touxiang = touxiang;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public long getTime() {return time;}public void setTime(long time) {this.time = time;}
}
定义我们消息内容的适配器MessageAdapter
import android.text.Html;
import android.text.Spanned;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;/*** Created by Administrator on 2015/8/31.*/
public class MessageAdapter extends BaseAdapter{private LayoutInflater inflater;private ArrayList<ChatMessage> data;private Html.ImageGetter getter;private static final int TYPE=2;public static final int MESSAGE_LEFT=0;public static final int MESSAGE_RIGHT=1;public MessageAdapter(LayoutInflater inflater, ArrayList<ChatMessage> data,Html.ImageGetter getter) {this.inflater = inflater;this.data = data;this.getter=getter;}@Overridepublic int getViewTypeCount() {//得到当前缓存布局类型的数量return TYPE;//因为有左右两种布局,返回常量2}@Overridepublic int getItemViewType(int position) {return data.get(position).getType();//返回当前布局的类型}@Overridepublic int getCount() {return data.size();}@Overridepublic Object getItem(int position) {return position;}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ChatMessage chatMessage=data.get(position);View view=null;ViewHolder viewHolder;int type=getItemViewType(position);if(convertView==null){switch (type){case MESSAGE_LEFT:view=inflater.inflate(R.layout.message,null);break;case MESSAGE_RIGHT:view=inflater.inflate(R.layout.message_right,null);break;default:break;}viewHolder=new ViewHolder();viewHolder.touxiang= (ImageView) view.findViewById(R.id.touxiang);viewHolder.title= (TextView) view.findViewById(R.id.title);viewHolder.name= (TextView) view.findViewById(R.id.name);viewHolder.message= (TextView) view.findViewById(R.id.message);viewHolder.time= (TextView) view.findViewById(R.id.time);view.setTag(viewHolder);}else {view=convertView;viewHolder= (ViewHolder) view.getTag();}viewHolder.touxiang.setImageResource(chatMessage.getTouxiang());viewHolder.title.setText(chatMessage.getTitle());viewHolder.name.setText(chatMessage.getName());Spanned spanned=Html.fromHtml(chatMessage.getMessage(),getter,null);viewHolder.message.setText(spanned);//因为内容可能添加表情,所以传入富文本SimpleDateFormat format= new SimpleDateFormat("EEE HH:mm");String time=format.format(new Date(chatMessage.getTime()));viewHolder.time.setText(time);//设置显示时间的格式return view;}class ViewHolder{ImageView touxiang;TextView title;TextView name;TextView message;TextView time;}
}
下面就要设置表情了,我们点击表情图片时,弹出一个PopupWindow,然后在里边设置一个GridView来显示我们的全部表情。
新建一个Gridview布局
<?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"><GridViewandroid:id="@+id/expression"android:layout_width="match_parent"android:layout_height="match_parent"android:numColumns="4"></GridView>
</LinearLayout>
然后是表情的布局,就是一个ImageView:
<?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:gravity="center"android:orientation="vertical"><ImageViewandroid:id="@+id/image_expression"android:layout_width="wrap_content"android:layout_height="wrap_content" />
</LinearLayout>
然后我们定义表情的实体类Expression
/*** Created by Administrator on 2015/8/31.*/
public class Expression {private int image;//设置一张表情的图片public int getImage() {return image;}public void setImage(int image) {this.image = image;}
}
接着我们写一个表情的适配器ExpressionAdapter
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import java.util.ArrayList;/*** Created by Administrator on 2015/8/31.*/
public class ExpressionAdapter extends BaseAdapter {private LayoutInflater inflater;private ArrayList<Expression> expressions;public ExpressionAdapter(LayoutInflater inflater, ArrayList<Expression> expressions) {this.inflater = inflater;this.expressions = expressions;}@Overridepublic int getCount() {return expressions.size();}@Overridepublic Object getItem(int position) {return position;}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {Expression expression=expressions.get(position);View view =inflater.inflate(R.layout.biaoqing,null);ImageView image= (ImageView) view.findViewById(R.id.image_expression);image.setImageResource(expression.getImage());return view;}
}
接下来呢,为了美观,当我们点击加号图片时,弹出一个PopupWindow,里边放置两个RadioButton,让我们选择发送信息的类型。
定义这个布局:
<?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:gravity="center"android:orientation="horizontal"><RadioGroupandroid:id="@+id/radiogroup"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><RadioButtonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="receive"/><RadioButtonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="send"/></RadioGroup>
</LinearLayout>
最后就是我们主活动的代码了!
import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.text.Html;
import android.text.Spanned;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.PopupWindow;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import java.util.ArrayList;public class MainActivity extends Activity {private EditText editText;private ArrayList<ChatMessage> data;private MessageAdapter adapter;private Html.ImageGetter getter;private ListView listView;private LayoutInflater inflater;private GridView gridView;private ArrayList<Expression> expressions;private ExpressionAdapter expressionAdapter;private View view;private View chooseView;private ImageView imageView;private ImageView choose;private String name;private ChatMessage chatMessage;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);editText = (EditText) findViewById(R.id.edittext);imageView = (ImageView) findViewById(R.id.biaoqing);choose = (ImageView) findViewById(R.id.choose);Button send = (Button) findViewById(R.id.send);listView = (ListView) findViewById(R.id.listview);inflater = getLayoutInflater();view = inflater.inflate(R.layout.expression, null);chooseView = inflater.inflate(R.layout.sendreceive, null);data = new ArrayList<>();imageView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {PopupWindow popupWindow = new PopupWindow(MainActivity.this);popupWindow.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);popupWindow.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);popupWindow.setContentView(view);popupWindow.setFocusable(true);popupWindow.setOutsideTouchable(true);popupWindow.update();popupWindow.showAtLocation(view, Gravity.CENTER, 0, 400);}});gridView = (GridView) view.findViewById(R.id.expression);expressions = new ArrayList<>();initExpression();expressionAdapter = new ExpressionAdapter(inflater, expressions);getter = new Html.ImageGetter() {@Overridepublic Drawable getDrawable(String source) {Drawable drawable = getResources().getDrawable(Integer.parseInt(source));drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());return drawable;}};gridView.setAdapter(expressionAdapter);gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {Spanned spanned = Html.fromHtml("<img src='" + expressions.get(position).getImage() + "'/>", getter, null);//将表情插入到光标所在位置editText.getText().insert(editText.getSelectionStart(), spanned);}});choose.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {PopupWindow popupWindow = new PopupWindow(MainActivity.this);popupWindow.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);popupWindow.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);popupWindow.setContentView(chooseView);popupWindow.setFocusable(true);popupWindow.setOutsideTouchable(true);popupWindow.update();popupWindow.showAtLocation(view, Gravity.CENTER, 0, 450);}});RadioGroup radioGroup = (RadioGroup) chooseView.findViewById(R.id.radiogroup);radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(RadioGroup group, int checkedId) {RadioButton radioButton = (RadioButton) chooseView.findViewById(checkedId);name = (String) radioButton.getText();}});send.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {if (name.equals("send")) {String message = filterHtml(Html.toHtml(editText.getText()));chatMessage = new ChatMessage(R.mipmap.weheartit, "老大", "巴黎铁塔前的黎明", message, System.currentTimeMillis());chatMessage.setType(MessageAdapter.MESSAGE_RIGHT);} else if (name.equals("receive")) {String message = filterHtml(Html.toHtml(editText.getText()));chatMessage = new ChatMessage(R.mipmap.weheartit, "老二", "东京樱花后的黄昏", message, System.currentTimeMillis());chatMessage.setType(MessageAdapter.MESSAGE_LEFT);}data.add(chatMessage);adapter.notifyDataSetChanged();listView.setSelection(data.size());//将ListView定位到最后一行editText.setText("");//清空输入框的内容}});adapter = new MessageAdapter(inflater, data, getter);listView.setAdapter(adapter);}/*** 将文本转化为HTML格式后,发送的时候去掉除富文本以外的内容** @param str 转化为HTML格式的字符串* @return 富文本*/public String filterHtml(String str) {str = str.replaceAll("<(?!br|img)[^>]+>", "").trim();return str;}/***初始化表情*/private void initExpression() {Expression expression1 = new Expression();expression1.setImage(R.mipmap.ebg);expressions.add(expression1);Expression expression2 = new Expression();expression2.setImage(R.mipmap.ebh);expressions.add(expression2);Expression expression3 = new Expression();expression3.setImage(R.mipmap.ebl);expressions.add(expression3);Expression expression4 = new Expression();expression4.setImage(R.mipmap.ebo);expressions.add(expression4);Expression expression5 = new Expression();expression5.setImage(R.mipmap.ebw);expressions.add(expression5);Expression expression6 = new Expression();expression6.setImage(R.mipmap.eca);expressions.add(expression6);Expression expression7 = new Expression();expression7.setImage(R.mipmap.ecb);expressions.add(expression7);Expression expression8 = new Expression();expression8.setImage(R.mipmap.ecc);expressions.add(expression8);Expression expression9 = new Expression();expression9.setImage(R.mipmap.eew);expressions.add(expression9);}
}
好了,至此大功告成!让我们测试一下结果吧!
##运行结果:
首先是我们的界面
然后点击加号,选择我们要发送的类型,选择send
输入发送内容,点击表情,选择要发送的表情
点击发送
最后的效果:
UI界面编写(仿QQ聊天界面)相关推荐
- Android 仿qq聊天界面之一
一.登录界面 本来是只想仿一个qq的聊天界面的,顺便做了一个登录界面,熟悉下SharedPreferences(解释一下:SharedPreferences由于非常适合记录一些零散的简单的数据,因此登 ...
- Android—简单的仿QQ聊天界面
最近仿照QQ聊天做了一个类似界面,先看下界面组成(画面不太美凑合凑合呗,,,,): 其中聊天背景可以是一个LinearLayout或者RelativeLayout里面存放的是ListView(将Lis ...
- php仿qq聊天界面,jquery仿微信聊天界面
首先看一下我们的效果图. 这个颜色可能搭配的有些不合适,但基本功能大都实现了.就是你和你同桌对话,你发的消息在你的左侧,而在他设备的右侧. 首先先写好整体的框架,在一个大容器中放两个盒子,分别是左侧和 ...
- 仿QQ聊天软件(登录界面、好友界面、聊天界面)-Java(Swing、Socket)
文章目录 一.项目结构 二.项目功能 三.制作界面 (一).登录界面的制作 (二).好友列表界面 (三).聊天界面 四.制作服务器 五.设计通信协议 六.项目缺点 学习了socket通信后,就想来制作 ...
- 高仿微信聊天界面长按弹框样式
效果图 背景 在公司做的项目里面,刚好有需要用到微信聊天界面长按弹框样式这种UI的. 网上找了一下,没找到. Android现成的 ListPopupWindow又不能满足需求. 因此在非上班时间撸一 ...
- android 仿微信聊天界面 以及语音录制功能,Android仿微信录制语音功能
本文实例为大家分享了Android仿微信录制语音的具体代码,供大家参考,具体内容如下 前言 我把录音分成了两部分 1.UI界面,弹窗读秒 2.一个类(包含开始.停止.创建文件名功能) 第一部分 由于6 ...
- android自定义设置界面,Android开发之精仿QQ设置界面(自定义PreferenceActivity)
Android开发之精仿QQ设置界面(自定义PreferenceActivity) 时间:2011-12-05 10:25:06 来源:Android开发者门户 作者: 今天,再给大家分享一下QQ设置 ...
- 使用js实现的带输入状态的简单的仿微信聊天界面
使用js实现的简单的仿微信聊天界面,实现固定的聊天回复功能,只能是固定的5句,但是回复的内容可以在代码的判断中进行修改. 实现的效果有:1.实现仿微信的聊天界面 2.实现仿微信的正在输入功能. 原理: ...
- C语言实现类似QQ聊天界面抖动功能
该博文为原创文章,未经博主同意不得转载,如同意转载请注明博文出处 本文章博客地址:https://cplusplus.blog.csdn.net/article/details/104991863 实 ...
最新文章
- python爬虫项目-23个Python爬虫开源项目代码
- python以下是变量合法命名的是_Python超级详细的变量命名规则
- 如何在SAP Business by design的UI上扩展新的按钮
- iOS: How To Make AutoLayout Work On A ScrollView
- Codeforces Round #674 (Div. 3)
- vue点击切换类名_vue 新用户引导(vue-dirver)
- java+cache使用方法_java相关:springboot使用GuavaCache做简单缓存处理的方法
- iphone字体大小设置_Win10电脑桌面上使用的记事本便签软件字体大小怎么调整?...
- SpaceBase – 基于 Sass 的响应式 CSS 框架
- Spring自动注解装配、自动检测装配Bean配合过滤组件使用
- oracle在cmd中启动数据库实例
- java基础——李兴华视频
- HighNewTech:19.04.22今天GitHub后无来者大事件之【B站后端代码不小心被开源】
- Lua:小数精度计算,几位数判断,四舍五入,最靠近5倍数取整
- Android Studio调用百度地图(二):实现地图显示后台定位和步行导航
- uniapp实现音视频通讯
- 【Java】抽象类继承的综合案例
- python爬虫淘宝实例-python 淘宝爬虫示例源码(抓取天猫数据)
- C语言知识点总结:指针
- wrong ELF class: ELFCLASS32
热门文章
- 天津理工计算机专业中外合作,天津理工大学中外合作办学硕士国外合作院校及专业...
- win10下php + apache客户端上传文件
- c语言多变量输入,技多不压身——C语言(五)变量,常量和输入输出
- 元宇宙产业委与南京信息工程大学举办“元宇宙与智能技术创新论坛”
- 2023上半年软考各省份报名时间已公布!
- LongAdder原理分析和性能测试
- MOS管常用驱动电路
- SpringBoot图文教程9—SpringBoot 导入导出 Excel 「Apache Poi」
- Unreal Engine 4 使用HLSL自定义着色器(Custom Shaders)教程(下)
- App地推活动需要做哪些准备 - Xinstall