刚开始接触到ListView,总是看见别人做出来很多稀奇古怪的界面自己就是不会,随后学习到了自定义View,就想着ListView也可以自定义出想要的样式,然后在网上搜集很多的的方法,要不就是看不懂,代码复制出来还无运行,要么就是不是自己想要的那款。今天在这里使用的不需要自定义ListView控件,e而是利用ListView自带的控件就能完成。
我们熟知的QQ、微信界面,至少会展示两种界面,有双方发送消息的版面,只要大家勤于动脑,我相信如果你看了今天我的方法,可以在ListView上添加两种以上的布局。老师不会告诉你,老师只是将你带入门,让你了解程序,认识程序,编写程序,其他的技能提升需要的是自己不断的提出问题,向别人提出问题,回答别人的问题,这样就会得到很多答案。
一个与我们平时所使用的ListView不同,就是它拥有2个不同的布局——收到的布局和发送的布局,如果需要实现这样的效果,必须要拿Adapter开头,在定义BaseAdapter时,需要重写getView()方法,需要哪种布局,只要判断一下获取哪种布局就可以了,ListView在设计的时候就已经考虑到这样的情况,所以提供的两个方法。
public int getItemView(int position){} 返回第position的item是何种类型
public int getViewTypeCount(){}; 返回不同布局的总数
1. 效果图
2 设计两个布局文件,就是所谓的接收布局和发送布局,由于两个布局文件基本都是一样的,不同的只是控件的位置不同,还有就是现实的图片的方位不同,适配图片请选用九宫图片适配。这里只列出一种布局文件
<?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="horizontal"
android:gravity="center_vertical"
android:padding="10dp">
<ImageView
android:id="@+id/icon_in"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@drawable/ic_launcher_background"/>
<TextView
android:id="@+id/text_in"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="20sp"
android:textColor="#DF0606"
android:gravity="center"
android:background="@drawable/popoleft"
android:text="打开工单各大品牌地方公开董鹏飞水电费控股电饭锅电饭锅"/>
</LinearLayout>
3 聊天内容,便于在Adapter中获取对象,我们需要封装一个javaBean对象,用来保存聊天的记录信息
package com.example.demod6;
import android.graphics.Bitmap;
public class ChatItemListViewBean {
private int type;
private String text;
private Bitmap icon;
public int getType() {
return type;
public void setType(int type) {
this.type = type;
public String getText() {
return text;
public void setText(String text) {
this.text = text;
public Bitmap getIcon() {
return icon;
public void setIcon(Bitmap icon) {
this.icon = icon;
4 最重要的就是BaseAdapter类了,同样使用ViewHolder模式来提高ListView的效率,并在getView()方法中进行布局类型的判断,从而确定使用哪种布局。
package com.example.demod6;
import android.content.Context;
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.util.List;
public class ViewHolderView extends BaseAdapter {
private List<ChatItemListViewBean> mData;
private LayoutInflater inflater;
public ViewHolderView(List<ChatItemListViewBean> mData, Context context) {
this.mData = mData;
inflater = LayoutInflater.from(context);
@Override
public int getCount() {
return mData.size();
@Override
public Object getItem(int i) {
return mData.get(i);
@Override
public long getItemId(int i) {
return i;
@Override
public View getView(int position, View contentView, ViewGroup viewGroup) {
ViewHolder holder = null;
if(contentView == null){
if(getItemViewType(position) == 0){
holder = new ViewHolder();
contentView = inflater.inflate(R.layout.chat_item_in,null);
holder.imageView = (ImageView) contentView.findViewById(R.id.icon_in);
holder.title = (TextView) contentView.findViewById(R.id.text_in);
}else {
holder = new ViewHolder();
contentView = inflater.inflate(R.layout.chat_item_out,null);
holder.imageView = (ImageView) contentView.findViewById(R.id.icon_in);
holder.title = (TextView) contentView.findViewById(R.id.text_in);
contentView.setTag(holder);
}else {
holder = (ViewHolder) contentView.getTag();//通过tag缓存找到对像
holder.imageView.setImageBitmap(mData.get(position).getIcon());
holder.title.setText(mData.get(position).getText());
return contentView;
@Override
public int getViewTypeCount() { //返回地position是何种类型
return 2;
@Override
public int getItemViewType(int position) { //返回不同布局的总数
ChatItemListViewBean bean = mData.get(position);
return bean.getType();
public class ViewHolder{
public ImageView imageView;
public TextView title;
6 实现ListView中多個佈局,就需要添加一些测试代码
package com.example.demod6;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.animation.ObjectAnimator;
import android.app.ActionBar;
import android.app.Activity;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.AbsListView;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private List<ChatItemListViewBean> mData = new ArrayList<ChatItemListViewBean>();
private int mTouchSlop;
private TextView header;
private TextView toolBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolBar = (TextView) findViewById(R.id.img);
MyListView myListView = (MyListView) findViewById(R.id.listView);
initListView();
ViewHolderView adapter = new ViewHolderView(mData,this);
myListView.setAdapter(adapter);
// header = new View(this);
header = new TextView(this);
header.setText("恭喜今天你和程辽辽成为好朋友");
header.setTextColor(Color.GREEN);
header.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
header.setLayoutParams(new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, (int) getResources().getDimension(R.dimen.height)));
myListView.addHeaderView(header); //标题头
mTouchSlop = ViewConfiguration.get(this).getScaledTouchSlop(); //最低滑动距离
//toolBar = getActionBar();
myListView.setOnTouchListener(myTouchListenner);
private void initListView() {
ChatItemListViewBean bean1 = new ChatItemListViewBean();
bean1.setIcon(BitmapFactory.decodeResource(getResources(),R.drawable.m1));
bean1.setType(0);
bean1.setText("嗨,你好,我在XXXX网站上看见你发的帖子,请问是单身吗?");
ChatItemListViewBean bean2 = new ChatItemListViewBean();
bean2.setIcon(BitmapFactory.decodeResource(getResources(),R.drawable.m2));
bean2.setType(1);
bean2.setText("是呀?这个与你有何干系。");
ChatItemListViewBean bean3 = new ChatItemListViewBean();
bean3.setIcon(BitmapFactory.decodeResource(getResources(),R.drawable.m1));
bean3.setType(0);
bean3.setText("是这样的,刚好我也单着,我看你各项条件都不错,对米有意。");
ChatItemListViewBean bean4 = new ChatItemListViewBean();
bean4.setIcon(BitmapFactory.decodeResource(getResources(),R.drawable.m2));
bean4.setType(1);
bean4.setText("我的各项条件真的正如你所说,很不错的。");
ChatItemListViewBean bean5 = new ChatItemListViewBean();
bean5.setIcon(BitmapFactory.decodeResource(getResources(),R.drawable.m1));
bean5.setType(0);
bean5.setText("我是一名打工族,最近家里老是催婚,家里介绍的那个是我一点都不喜欢,在深圳这边打工,很无奈。");
ChatItemListViewBean bean6 = new ChatItemListViewBean();
bean6.setIcon(BitmapFactory.decodeResource(getResources(),R.drawable.m2));
bean6.setType(1);
bean6.setText("那你做什么工作的?");
ChatItemListViewBean bean7 = new ChatItemListViewBean();
bean7.setIcon(BitmapFactory.decodeResource(getResources(),R.drawable.m1));
bean7.setType(0);
bean7.setText("前天被老板给开除,还不是因为家里那点事,惹的挺烦的,结果工作也弄丢了,还被罚了钱");
ChatItemListViewBean bean8 = new ChatItemListViewBean();
bean8.setIcon(BitmapFactory.decodeResource(getResources(),R.drawable.m2));
bean8.setType(1);
bean8.setText("看来挺糟糕的,那你准备回去吗?还是继续找新的工作?");
ChatItemListViewBean bean9 = new ChatItemListViewBean();
bean9.setIcon(BitmapFactory.decodeResource(getResources(),R.drawable.m1));
bean9.setType(0);
bean9.setText("哎!怎么说呢?前天去人才市场找工作,结果把钱弄丢了,现在钱只顾吃饭,在挺挺吧,等找到工作,就好了。");
ChatItemListViewBean bean10 = new ChatItemListViewBean();
bean10.setIcon(BitmapFactory.decodeResource(getResources(),R.drawable.m2));
bean10.setType(1);
bean10.setText("那你家在哪里?要不先回家后,在过一端事件再出来");
ChatItemListViewBean bean11 = new ChatItemListViewBean();
bean11.setIcon(BitmapFactory.decodeResource(getResources(),R.drawable.m1));
bean11.setType(0);
bean11.setText("我没钱回家,是钱不够,但是这边还是可以维持一段时间,下午我要去一个工厂面试。可能会在上班的。");
mData.add(bean1);
mData.add(bean2);
mData.add(bean3);
mData.add(bean4);
mData.add(bean5);
mData.add(bean6);
mData.add(bean7);
mData.add(bean8);
mData.add(bean9);
mData.add(bean10);
mData.add(bean11);
private int mFirstY = 0;
private int currentY = 0;
private int direction = 0;
private boolean mShow = true;
private ObjectAnimator mAnimator;
View.OnTouchListener myTouchListenner = new View.OnTouchListener() {
@Override
public boolean onTouch(View v, @NonNull MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
mFirstY = (int) event.getY();
break;
case MotionEvent.ACTION_MOVE:
currentY = (int) event.getY();
if(currentY - mFirstY > mTouchSlop){
direction = 0; //向下
}else if(mFirstY - currentY > mTouchSlop ){
direction = 1; //向上
if(direction == 1){
if(mShow){
//header.setVisibility(View.GONE);
toolBarAnima(0);
mShow = !mShow;
}else if(direction == 0){
if(!mShow){
//header.setVisibility(View.VISIBLE);
toolBarAnima(1);
mShow = !mShow;
break;
return false;
* @param flag
private void toolBarAnima(int flag){
if(mAnimator != null && mAnimator.isRunning()){
mAnimator.cancel();
if(flag == 0){
mAnimator = ObjectAnimator.ofFloat(toolBar,"translationY",toolBar.getTranslationY(),0);
}else {
mAnimator = ObjectAnimator.ofFloat(toolBar,"translationY",toolBar.getTranslationY(),-toolBar.getHeight());
mAnimator.start();
轻轻松松完成模拟对话情景效果,赶快来试一试吧。
我们这么来分析:
整个聊天记录是一个listview,分为两种布局:发送的消息和收到的消息。
这里就是与平时使用的ListView有一个最大的不同:拥有两个不同的布局,在Adapter上下功夫!
BaseAdapter中提供了两个方法:
@Override
public int getItemViewType(int position)
通常我们用惯的ListView每一项的布局都是相同的,只是控件所绑定的数据不同。但单单只是如此并不能满足我们某些特殊需求,比如我们常见的QQ、微信的聊天列表,除了有左右之分外,内容更是有很大区别,有文字、语音、图片、视频等等,他们真的是ListView可以实现的吗?答案是肯定的,只要我们做一下类型区别即可。实现效果如下所示:大家不要在意布局,这里为了方便就随意了。大家可以看到,这里有两种布局,一种...
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
把生活的优质寄托于别人,一昧的祈求别人同情和怜悯,短时间可能会有所收获,但随着时间,同情和怜悯最终只会变成反感和厌恶。而真正能够改变自己命运的,只有自己努力。你若精彩,蝴蝶自来。 ——出自青坏坏语录大家还记得我们之前用BaseAdapter去实现Spinner的使用吗,其实适配器可以完成的工作不仅仅是Spinner的适配,还有很多控件都可以,比如我们今天要学习的ListVi...
最近搞一个项目,需要用到类似于新浪微博的消息流,即每一项有文字、有九宫格图片,因此这就涉及到ListView或者ScrollView嵌套GridView的问题。其中GridView的高度问题在网上都很容易找到答案,即覆写onMeasure方法,然后设置高度的MeasureSpec。但是宽度问题确实没有什么资料,这里所说的宽度问题是比如GridView的列数为3,那么即使只有一张图片,gridvie...
我正在Android上编写一个聊天客户端,但是在我的客户端中有一个聊天泡泡问题.我的聊天屏幕包括一个包含文本框的ListView和底部的发送按钮.对于外发消息,文本在ListView行中保持对齐.对于传入消息,文本在ListView行中对齐.但是,聊天泡泡不会调整到传入消息文本的长度.左对齐的传出消息不会发生此问题.这里的屏幕截图如下.聊天消息文本存储在数据库中,并通过光标适配器显示在ListVi...
WPF仿微信界面发送消息简易版
参考别的博主的例子用WPF MVVM框架来仿了一个微信聊天界面,做了个发送消息简易功能,下面一起来看看吧!
以下为View视图布局代码,消息对话框的样式直接在这里定义了,主要定义的是用户头像、对话框和发送时间的样式,其中设置了文字消息自动换行。
<Window x:Class="DEMO.View.ChatWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
说说怎么实现的吧。打磨一个聊天气泡的想法由来已久。
WinForm
最开始用的WInForm,想重绘ListBox或者RichTextBox来做,可是借助万能的度娘也没找到思路,不熟...
2、Name: 程序里调用的名称,Text:表格里显示的信息,其它可以设置大小等信息。3、显示网格线 属性 GridLines --- True。1、点击表格右上角的三角形,添加表头信息。这样,一个listView就画出来了。4、往表格里填写数据,跟着来就可以了。5、改变背景颜色,和字体颜色。