控件ListView样式.

  1. 首先在 xml 中定义个ListView;
  2. 在 Activity 中写如代码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class MainActivity extends AppCompatActivity {

private String[] data = {"Apple", "Banana", "Orange", "Cherry"};


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

//数据无法直接传递给ListView,所以需要借助适配器来完成 这里范型指定为String(因为我们传递数组是字符串) 依次传入上下文、ListView子项布局id,以及需要适配的数据
ArrayAdapter<String> adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_expandable_list_item_1, data);


ListView listView = (ListView) findViewById((R.id.list_view));
listView.setAdapter(adapter);

}
}

ListView点击事件

1
2
3
4
5
6
7
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id
}
});
//get(position)就行

定制ListView界面(例:对话界面)

  1. 准备主布局文件、组件布局文件;
  2. 获取并整理数据;
  3. 绑定数据。

对话框demo(包含对话和输入框、发送按钮)

  1. 首先写主布局文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<ListView
android:id="@+id/msg_list_view"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="0dp"
android:divider="#0000">
</ListView>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">

<EditText
android:id="@+id/input_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="输入内容"
android:maxLines="2"
android:layout_weight="1"/>

<Button
android:id="@+id/send"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="发送"/>

</LinearLayout>

2.新建一个class, 定义实体类。content表示消息内容;type表示消息的类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Msg {

public static final int TYPE_RECEIVED = 0; //收到的消息
public static final int TYPE_SENT = 1; //发送的消息
private String content;
private int type;


public Msg(String content, int type) {
this.content = content;
this.type = type;
}
public String getContent(){
return content;
}
public int getType(){
return type;
}
}

3.新建xml,写ListView子项的布局。定义一个居右,一个居左的TextView,用来显示对话框content。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<LinearLayout
android:id="@+id/left_layout"
android:layout_gravity="left"
android:layout_width="wrap_content"
android:layout_height="wrap_content">


<TextView
android:id="@+id/left_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="10dp"
android:textColor="#0000ff"/>

</LinearLayout>




<LinearLayout
android:id="@+id/right_layout"
android:layout_gravity="right"
android:layout_width="wrap_content"
android:layout_height="wrap_content">


<TextView
android:id="@+id/right_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="10dp"
android:textColor="#00ff00"/>

</LinearLayout>

3.创建ListView的适配器类,继承ArrayAdapter(这里baseAdapter也可以),也就是创建一个关于消息显示的样式布局。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package com.example.xxhuang.demo;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.List;


public class MsgAdapter extends ArrayAdapter<Msg> {

private int resourceId;

//重写父类构造函数。用于将上下文、ListView子项布局的id和数据都传递进来
public MsgAdapter(Context context, int textViewResourceId, List<Msg> objects) {
super(context, textViewResourceId, objects);
resourceId = textViewResourceId;
}

//重写get方法,
@Override
public View getView(int position, View convertView, ViewGroup parent) {

//获得当前项的实例
Msg msg = getItem(position);

//对getView()方法进行判断,如果convertView为空,则使用LayoutInflater加载布局,如果不为空则直接对cnvertView进行重用(提高运行效率)
View view;
ViewHolder viewHolder;

if(convertView == null){


view = LayoutInflater.from(getContext()).inflate(resourceId , null);

viewHolder = new ViewHolder();
viewHolder.leftLayout = (LinearLayout) view.findViewById(R.id.left_layout);
viewHolder.rightLayout = (LinearLayout) view.findViewById(R.id.right_layout);
viewHolder.leftMsg = (TextView)view.findViewById(R.id.left_msg);
viewHolder.rightMsg = (TextView)view.findViewById(R.id.right_msg);
view.setTag(viewHolder); //将viewHolder存储在view中

}
else{
view = convertView;
viewHolder = (ViewHolder)view.getTag();//重新获取viewHolder



}
if(msg.getType() == Msg.TYPE_RECEIVED){

//如果是收到的消息,则显示左边的消息布局,将右边的消息布局隐藏
viewHolder.leftLayout.setVisibility(View.VISIBLE);
viewHolder.rightLayout.setVisibility(View.GONE);
viewHolder.leftMsg.setText(msg.getContent()); //拿到消息内容


}else if(msg.getType() == Msg.TYPE_SENT){

//如果是发出的消息,则显示右边的消息布局,将左边的消息布局隐藏
viewHolder.rightLayout.setVisibility(View.VISIBLE);
viewHolder.leftLayout.setVisibility(View.GONE);
viewHolder.rightMsg.setText(msg.getContent());

}

return view;

}


/**新增内部类ViewHolder,用于对控件实例进行缓存 当convertView为空时,创建一个ViewHolder对象,
并将控件的都存在ViewHolder里。然后调用setTag()方法,将将ViewHolder存储在View中,当convertView不为空时,
则调用View的get()方法,把ViewHolder重新取出。这样把空间的实例都缓存在ViewHolder里,就没有必要每次通过findViewById()方法来获取控件实例
*/

class ViewHolder{
LinearLayout leftLayout;
LinearLayout rightLayout;
TextView leftMsg;
TextView rightMsg;

}
}

4.修改 MainActivity 代码,为 ListView 初始化数据;给按钮加入监听事件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
public class MainActivity extends AppCompatActivity {
private ListView msgListView;
private EditText inputText;
private Button send;
private MsgAdapter adapter;
private List<Msg> msgList = new ArrayList<Msg>();


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);


initMsg(); //初始化消息数据

//适配器 上下文,子项布局id,需要传入的数据
adapter = new MsgAdapter(MainActivity.this , R.layout.msg_item , msgList);

inputText = (EditText)findViewById(R.id.input_text);
send = (Button)findViewById(R.id.send);
msgListView = (ListView)findViewById(R.id.msg_list_view);

msgListView.setAdapter(adapter);

//点击事件,点击获取EditText中的内容
send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String content = inputText.getText().toString();
if(! "".equals(content)){

//如果内容不为空,则创建一个新的msg对象
Msg msg = new Msg(content, Msg.TYPE_SENT);

//将对象添加到msgList列表中去
msgList.add(msg);
adapter.notifyDataSetChanged(); //当有消息时,刷新ListView中的显示
msgListView.setSelection(msgList.size()); //将ListView定位到最后一行
inputText.setText(""); //清空输入框中的内容

}else {
Toast.makeText(MainActivity.this, "请输入内容" , 2).show(); //没内容则toast提示
}
}
});

}

//初始化几条数据在ListView
private void initMsg(){
Msg msg1 = new Msg("hello" ,Msg.TYPE_RECEIVED );
msgList.add(msg1);

Msg msg2 = new Msg("hello" ,Msg.TYPE_SENT );
msgList.add(msg2);

}