您的位置:首页 > 移动开发 > Android开发

Android学习-ListView

2016-02-17 16:59 393 查看
今天复习的内容是ListView,来做一个简单的仿微信的聊天界面



这是微信的界面

自定义Layout

先写个自定义Layout来仿标题栏,新建一个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="wrap_content"
android:orientation="horizontal"
android:background="#393a3e">//设置背景颜色

<ImageButton
android:id="@+id/btn_title_back"
android:layout_height="60dp"
android:layout_width="60dp"
android:padding="21dp"//控制返回按钮显示的大小
android:scaleType="centerInside"//图片缩放模式为居中缩放
android:src="@drawable/back"
android:background="#393a3e"/>

<View
android:layout_height="25dp"
android:layout_width="1dp"
android:layout_gravity="center_vertical"
android:background="#000000"/>//设置back与名字中间的分割线

<TextView
android:layout_height="wrap_content"
android:layout_width="0dp"
android:textSize="20sp"
android:paddingLeft="5dp"
android:layout_gravity="center_vertical"
android:textColor="#FFFF"
android:layout_weight="1"
android:text="小冰"/>

<ImageButton
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:scaleType="centerInside"
android:padding="17dp"
android:src="@drawable/people"
android:background="#393a3e"/>

</LinearLayout>


效果图



然后新建class,取名title,继承LinearLayout

public class title extends LinearLayout{

public title(Context context, AttributeSet attrs) {//重写2个参数的构造函数
super(context, attrs);
// TODO Auto-generated constructor stub
LayoutInflater.from(context).inflate(R.layout.title_layout, this);//动态加载布局文件,用LayoutInflater.from()构建LayoutInflater对象,再调用它的inflate()方法来加载布局,它的第一个参数是要加载的布局文件,第二个参数是它的父布局
ImageButton back=(ImageButton)findViewById(R.id.btn_title_back);//这里是ImageButton,之前写成了Button,一直报错,要仔细
back.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
((Activity)getContext()).finish();//给back键动作,关掉这个activity
}
});
}
}


主界面

接下来写聊天界面的布局,总共包含一个自定义的title,一个ListView,一个语音的Button,这里用来接收消息,一个EditText用来输入聊天信息,一个Button加号,就是微信里面的更多,这里用来发送消息,效果如图



因为没准备素材所以有一些偏差,不过大致上是出来了。

定制ListView界面

布局写完了就该写ListView里面的东西了,先建一个类来储存聊天列表里的信息,包括消息的类型(收到的和发出的),头像,以及聊天的内容

public class Message {
public static final int RECEIVE=0;
public static final int SEND=1;//用来代表消息的类型

private String content;
private int type;//消息的类型
private int imageId;
public String getContent() {
return content;
}
public int getType() {
return type;
}
public int getImageId() {
return imageId;
}
public Message(int type,int imageId,String content) {
this.content=content;
this.imageId=imageId;
this.type=type;

4000
}
}


然后为ListView子项即聊天列表新建一个自定义布局,分为左右两种,左边的是收到的信息,右边的是发出的信息,所以对应着建两个LinearLayout

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#ebebeb" >

<LinearLayout//收到的消息
android:id="@+id/receive_layout"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:orientation="horizontal">

<ImageView
android:id="@+id/left_image"
android:layout_width="60dp"
android:layout_height="60dp"
android:padding="10dp"
/>

<TextView
android:id="@+id/left_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="-5dp"
android:singleLine="false"
android:maxEms="12"
android:padding="10dp"
android:textSize="15sp"
android:layout_marginTop="10dp"
android:background="@drawable/receive_bg"
/>

</LinearLayout>
<LinearLayout //发出去的消息
android:id="@+id/send_layout"
android:layout_height="wrap_content"
android:gravity="right"
android:layout_width="match_parent"
android:orientation="horizontal">

<TextView
android:id="@+id/right_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="-5dp"
android:singleLine="false"
android:maxEms="12"
android:padding="10dp"
android:textSize="15sp"
android:layout_marginTop="10dp"
android:background="@drawable/send_bg"
/>

<ImageView
android:id="@+id/right_image"
android:layout_width="60dp"
android:layout_height="60dp"
android:padding="10dp"
/>

</LinearLayout>

</LinearLayout>


自定义适配器MessageAdapter

然后就是写适配器,继承ArrayAdapter,泛型为之前创建的Message

public class MessageAdapter extends ArrayAdapter<Message>{

private int resId;

public MessageAdapter(Context context, int resource, List<Message> objects) {
super(context, resource, objects);
// TODO Auto-generated constructor stub
resId=resource;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {//使listview的子项一出现在屏幕上就会调用这个方法来显示
// TODO Auto-generated method stub
Message message=getItem(position);
View view;
ViewHolder viewHolder;
if (convertView==null) {//判断上一个子项加载后的缓存是否为空,若不为空,就可以直接调用之前的,节省内存
view=LayoutInflater.from(getContext()).inflate(resId, null);//加载传入的布局
viewHolder=new ViewHolder();
viewHolder.left_layou=(LinearLayout)view.findViewById(R.id.receive_layout);
viewHolder.right_layout=(LinearLayout)view.findViewById(R.id.send_layout);
viewHolder.left_content=(TextView)view.findViewById(R.id.left_content);
viewHolder.right_content=(TextView)view.findViewById(R.id.right_content);
viewHolder.left_image=(ImageView)view.findViewById(R.id.left_image);
viewHolder.right_image=(ImageView)view.findViewById(R.id.right_image);
view.setTag(viewHolder);//将设置好的viewHolder放入缓存,以便下次使用
}else {
view=convertView;
viewHolder=(ViewHolder)view.getTag();
}if (message.getType()==Message.RECEIVE) {//判断显示哪一个LinearLayout
viewHolder.left_layou.setVisibility(View.VISIBLE);
viewHolder.right_layout.setVisibility(View.GONE);
viewHolder.left_content.setText(message.getContent());
viewHolder.left_image.setImageResource(message.getImageId());
}else {
viewHolder.right_layout.setVisibility(View.VISIBLE);
viewHolder.left_layou.setVisibility(View.GONE);
viewHolder.right_content.setText(message.getContent());
viewHolder.right_image.setImageResource(message.getImageId());
}
return view;
}

@Override
public boolean isEnabled(int position) {//设置子项不可点击
// TODO Auto-generated method stub
return false;
}

class ViewHolder{//用来管理需要加载的控件以及布局
LinearLayout left_layou;
LinearLayout right_layout;
TextView left_content;
TextView right_content;
ImageView left_image;
ImageView right_image;
}
}


在Activity中调用、更新逻辑

接下来就是在activity中去调用了

public class fuxi extends Activity implements OnClickListener{

private ImageButton btn_receive;
private ImageButton btn_send;
private ListView chat_list;
private EditText et_content;
private List<Message> messages=new ArrayList<Message>();//新建Message的list,待会儿用来传入adapter
private MessageAdapter adapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.chat);
initView();//初始化控件
initMessage();//初始化聊天内容,这里一边放入一个你好
adapter=new MessageAdapter(this, R.layout.chat_list, messages);
chat_list.setAdapter(adapter);
}

private void initView() {
btn_receive=(ImageButton)findViewById(R.id.btn_receive);
btn_send=(ImageButton)findViewById(R.id.btn_send);
chat_list=(ListView)findViewById(R.id.chat_list);
et_content=(EditText)findViewById(R.id.chat_content);
btn_receive.setOnClickListener(this);
btn_send.setOnClickListener(this);
}

private void initMessage() {
Message message1=new Message(Message.RECEIVE, R.drawable.receive, "你好");
messages.add(message1);
Message message2=new Message(Message.SEND, R.drawable.send, "你好");
messages.add(message2);
}

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
String content=et_content.getText().toString();
switch (v.getId()) {
case R.id.btn_receive://之前语音图标的Button用来接收消息,模拟别人发过来消息
if (!TextUtils.isEmpty(content)) {
Message message=new Message(Message.RECEIVE, R.drawable.receive, content);
messages.add(message);
adapter.notifyDataSetChanged();
chat_list.setSelection(messages.size());//刷新列表
et_content.setText("");//清空输入框
}
break;
case R.id.btn_send://之前加号图标的Button,这里用作发送
if (!TextUtils.isEmpty(content)) {
Message message=new Message(Message.SEND, R.drawable.send, content);
messages.add(message);
adapter.notifyDataSetChanged();
chat_list.setSelection(messages.size());
et_content.setText("");
}
break;

default:
break;
}
}
}


这里每次输入消息后,ListView中都会有新的子项,先调用adapter.notifyDataSetChanged()来刷新ListView,因为新加的消息是在ListView的最后一项,如果超出屏幕范围了,就不能显示出来,需要用户手动划到ListView的最后一项才能看到,所以需要再调用chat_list.setSelection(messages.size())将ListView定位到最后一行,保证新消息能显示出来。

最后效果图



TextView的字的位置有点问题,需要微调一下,不过主要的还是对ListView的练习。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android listview