03UI
来源:互联网 发布:qq农场蜂箱升级数据 编辑:程序博客网 时间:2024/06/06 03:41
本节内容:常见控件的使用方法、详解四种基本布局、引入布局、创建自定义控件、最常用和最难用的控件——ListView、单位和尺寸、编写界面的最佳实践----聊天界面;
常见控件的使用方法:
android:id:给当前控件定义了一个唯一标识符
android:layout_width、android:layout_height:match_parent、fill_parent 和wrap_content
TextView:
android:text :指定TextView 中显示的文本内容
android:gravity:指定文字的对齐方式,可选值有top、bottom、left、right、center等, 可以用“ | ” 来同时指定多个值, 这里我们指定的"center" , 效果等同于"center_vertical|center_horizontal",表示文字在垂直和水平方向都居中对齐。
android:textSize: 属性可以指定文字的大小(android:textSize="24sp")
android:textColor: 属性可以指定文字的颜色(android:textColor="#00ff00")
Button:
android:text :指定Button中显示的文本内容
主要是为Button 的点击事件注册一个监听器,如果你不喜欢使用匿名类的方式来注册监听器,也可以使用实现接口的方式来进行注册,代码如下所示:
public
class
MainActivity
extends
Activity
implements
OnClickListener {
private
Button button;
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button);
button.setOnClickListener(
this
);
}
@Override
public
void
onClick(View v) {
switch
(v.getId()) {
case
R.id.button:
// 在此处添加逻辑
break
;
default
:
break
;
}
}
}
EditText:
android:hint:属性来指定了一段提示性的文本
android:maxLines :指定了EditText 的最大行数为两行(android:maxLines="2")
使用EditText和Button组合通过点击按钮获取输入内容:(同02Activity节中的计算器用法);
ImageView:
android:src: 属性给ImageView 指定了一张图片(android:src="@drawable/ic_launcher")
也可以在程序中通过代码动态地更改ImageView 中的图片:在按钮的点击事件里,通过调用ImageView 的setImageResource()方法;
ProgressBar:
android:visibility:visible(默认)、invisible 和gone。
还可以通过代码来设置进度条的可见性,使用的是setVisibility()方法,可以传入View.VISIBLE、View.INVISIBLE 和View.GONE 三种值;通过getVisibility()方法来判断ProgressBar 是否可见;
style:指定不同的样式(style="?android:attr/progressBarStyleHorizontal")
指定成水平进度条后,我们还可以通过android:max 属性给进度条设置一个最大值,然后在代码中动态地更改进度条的进度。getProgress()和setProgress()(进度为int型数据);
AlertDialog:
在当前的界面弹出一个对话框,这个对话框是置顶于所有界面元素之上的,能够屏蔽掉其他控件的交互能力,因此一般AlertDialog 都是用于提示一些非常重要的内容或者警告信息。比如为了防止用户误删重要内容,在删除前弹出一个确认对话框。
public
class
MainActivity
extends
Activity
implements
OnClickListener {
……
@Override
public
void
onClick(View v) {
switch
(v.getId()) {
case
R.id.button:
AlertDialog.Builder dialog =
new
AlertDialog.Builder(MainActivity.
this
);
dialog.setTitle(
"This is Dialog"
);
dialog.setMessage(
"Something important."
);
dialog.setCancelable(
false
);
dialog.setPositiveButton(
"OK"
,
new
DialogInterface.OnClickListener() {
@Override
public
void
onClick(DialogInterface dialog,
int
which){}
});
dialog.setNegativeButton(
"Cancel"
,
new
DialogInterface.OnClickListener() {
@Override
public
void
onClick(DialogInterface dialog,
int
which) {}
});
dialog.show();
break
;
default
:
break
;
}
}
}
ProgressDialog:
AlertDialog 有点类似,都可以在界面上弹出一个对话框,都能够屏蔽掉其他控件的交互能力。不同的是,ProgressDialog 会在对话框中显示一个进度条,一般是用于表示当前操作比较耗时,让用户耐心地等待。
public
class
MainActivity
extends
Activity
implements
OnClickListener {
……
@Override
public
void
onClick(View v) {
switch
(v.getId()) {
case
R.id.button:
ProgressDialog progressDialog =
new
ProgressDialog(MainActivity.
this
);
progressDialog.setTitle(
"This is ProgressDialog"
);
progressDialog.setMessage(
"Loading..."
);
progressDialog.setCancelable(
true
);
progressDialog.show();
break
;
default
:
break
;
}
}
}
注意:如果在setCancelable()中传入了false,表示ProgressDialog 是不能通过Back 键取消
掉的,这时你就一定要在代码中做好控制,当数据加载完成后必须要调用ProgressDialog 的
dismiss()方法来关闭对话框,否则ProgressDialog 将会一直存在。
详解四种基本布局:
LinearLayout:
android:orientation:vertical、horizontal(默认);
注意:排列方向是horizontal,内部的控件就绝对不能将宽度指定为match_parent;同样排列方向是vertical,内部的控件就不能将高度指定为match_parent。
android:layout_gravity:指定控件在布局中的对齐方式。android:layout_gravity 的可选值和android:gravity(文字在控件中的对齐方式) 差不多, 但是需要注意, 当LinearLayout 的排列方向是horizontal 时,只有垂直方向上的对齐方式才会生效;当LinearLayout 的排列方向是vertical 时,只有水平方向上的对齐方式才会生效。
android:layout_weight:所有控件按权重比例分配宽度,此时控件的width属性不起作用;两个控件均为1则平分宽度;一个为1一个不指定weight,而width为wrap_content,则一个占满剩余宽度;
RelativeLayout:
相对于父布局进行定位:
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_centerInParent="true"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
相对于控件进行定位:
android:layout_above="@id/button3"
android:layout_toLeftOf="@id/button3"
android:layout_below="@id/button3"
android:layout_toRightOf="@id/button3"
注意:当一个控件去引用另一个控件的id 时,该控件一定要定义在引用控件的后面;
android:layout_alignLeft、android:layout_alignRight、android:layout_alignTop 、android:layout_alignBottom;
FrameLayout(不常用):
没有任何的定位方式,所有的控件都会摆放在布局的左上角;
TableLayout(不常用):
在TableLayout 中每加入一个TableRow 就表示在表格中添加了一行,然后在TableRow中每加入一个控件,就表示在该行中加入了一列,TableRow 中的控件是不能指定宽度的;
用于输入密码的EditText , 我们通过将android:inputType="textPassword",把EditText 变为密码输入框;
使用android:layout_span="2"让登录按钮占据两列的空间;
使用android:stretchColumns=1表示如果表格不能完全占满屏幕宽度,就将第二列进行拉伸;指定成0 就是拉伸第一列;
<
TableLayout
xmlns:android
=
"http://schemas.android.com/apk/res/android"
android:layout_width
=
"match_parent"
android:layout_height
=
"match_parent"
>
android:stretchColumns="1"
<
TableRow
>
<
TextView
android:layout_height
=
"wrap_content"
android:text
=
"Account:"
/>
<
EditText
android:id
=
"@+id/account"
android:layout_height
=
"wrap_content"
android:hint
=
"Input your account"
/>
</
TableRow
>
<
TableRow
>
<
TextView
android:layout_height
=
"wrap_content"
android:text
=
"Password:"
/>
<
EditText
android:id
=
"@+id/password"
android:layout_height
=
"wrap_content"
android:inputType
=
"textPassword"
/>
</
TableRow
>
<
TableRow
>
<
Button
android:id
=
"@+id/login"
android:layout_height
=
"wrap_content"
android:layout_span
=
"2"
android:text
=
"Login"
/>
</
TableRow
>
</
TableLayout
>
引入布局:解决了重复编写布局代码的问题
新建一个布局title.xml
<
LinearLayout
xmlns:android
=
"http://schemas.android.com/apk/res/android"
android:layout_width
=
"match_parent"
android:layout_height
=
"wrap_content"
android:background
=
"@drawable/title_bg"
>
<
Button
android:id
=
"@+id/title_back"
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:layout_gravity
=
"center"
android:layout_margin
=
"5dip"
android:background
=
"@drawable/back_bg"
android:text
=
"Back"
android:textColor
=
"#fff"
/>
<
TextView
android:id
=
"@+id/title_text"
android:layout_width
=
"0dip"
android:layout_height
=
"wrap_content"
android:layout_gravity
=
"center"
android:layout_weight
=
"1"
android:gravity
=
"center"
android:text
=
"Title Text"
android:textColor
=
"#fff"
android:textSize
=
"24sp"
/>
<
Button
android:id
=
"@+id/title_edit"
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:layout_gravity
=
"center"
android:layout_margin
=
"5dip"
android:background
=
"@drawable/edit_bg"
android:text
=
"Edit"
android:textColor
=
"#fff"
/>
</
LinearLayout
>
两个Button 中我们都使用了android:layout_margin 这个属性,它可以指定控件在上下左右方向上偏移的距离,当然也可以使用android:layout_marginLeft或android:layout_marginTop 等属性来单独指定控件在某个方向上偏移的距离。
引入布局:修改activity_main.xml 中的代码,如下所示:
<
LinearLayout
xmlns:android
=
"http://schemas.android.com/apk/res/android"
android:layout_width
=
"match_parent"
android:layout_height
=
"match_parent"
>
<
include
layout
=
"@layout/title"
/>
</
LinearLayout
>
注意:要将系统自带的标题栏隐藏掉;
创建自定义控件:解决了重复编写响应事件代码的问题
新建TitleLayout 继承自LinearLayout,让它成为我们自定义的标题栏控件,代码如下所示:
public
class
TitleLayout
extends
LinearLayout {
public
TitleLayout(Context context, AttributeSet attrs) {
super
(context, attrs);
LayoutInflater.from(context).inflate(R.layout.title,
this
);
}
}
首先我们重写了LinearLayout 中的带有两个参数的构造函数,在布局中引入TitleLayout控件就会调用这个构造函数。然后在构造函数中需要对标题栏布局进行动态加载,这就要借助LayoutInflater 来实现了。通过LayoutInflater 的from()方法可以构建出一个LayoutInflater对象,然后调用inflate()方法就可以动态加载一个布局文件,inflate()方法接收两个参数,第一个参数是要加载的布局文件的id,这里我们传入R.layout.title,第二个参数是给加载好的布局再添加一个父布局,这里我们想要指定为TitleLayout,于是直接传入this。
然后我们需要在布局文件中添加这个自定义控件,修改activity_main.xml 中的代码,如下所示:
<
LinearLayout
xmlns:android
=
"http://schemas.android.com/apk/res/android"
android:layout_width
=
"match_parent"
android:layout_height
=
"match_parent"
>
<
com.example.uicustomviews.TitleLayout
android:layout_width
=
"match_parent"
android:layout_height
=
"wrap_content"
></
com.example.uicustomviews.TitleLayout
>
</
LinearLayout
>
添加自定义控件和添加普通控件的方式基本是一样的,只不过在添加自定义控件的时候我们需要指明控件的完整类名,包名在这里是不可以省略的。
然后我们来尝试为标题栏中的按钮注册点击事件,修改TitleLayout 中的代码,如下所示:
public
class
TitleLayout
extends
LinearLayout {
public
TitleLayout(Context context, AttributeSet attrs) {
super
(context, attrs);
LayoutInflater.from(context).inflate(R.layout.title,
this
);
Button titleBack = (Button) findViewById(R.id.title_back);
Button titleEdit = (Button) findViewById(R.id.title_edit);
titleBack.setOnClickListener(
new
OnClickListener() {
@Override
public
void
onClick(View v) {
((Activity) getContext()).finish();
}
});
titleEdit.setOnClickListener(
new
OnClickListener() {
@Override
public
void
onClick(View v) {
Toast.makeText(getContext(),
"You clicked Edit button"
,Toast.LENGTH_SHORT).show();
}
});
}
}
这样的话,每当我们在一个布局中引入TitleLayout,返回按钮和编辑按钮的点击事件就已经自动实现好了。
最常用和最难用的控件——ListView:
简单用法:
activity_main.xml 中:
<
LinearLayout
xmlns:android
=
"http://schemas.android.com/apk/res/android"
android:layout_width
=
"match_parent"
android:layout_height
=
"match_parent"
>
<
ListView
android:id
=
"@+id/list_view"
android:layout_width
=
"match_parent"
android:layout_height
=
"match_parent"
>
</
ListView
>
</
LinearLayout
>
MainActivity 中:
public
class
MainActivity
extends
Activity {
private
String[] data = {
"Apple"
,
"Banana"
,
"Orange"
,
"Watermelon"
,
"Pear"
,
"Grape"
,
"Pineapple"
,
"Strawberry"
,
"Cherry"
,
"Mango"
};
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ArrayAdapter<String> adapter =
new
ArrayAdapter<String>( MainActivity.
this
, android.R.layout.simple_list_item_1, data);
ListView listView = (ListView) findViewById(R.id.list_view);
listView.setAdapter(adapter);
}
}
我们使用一个data 数组来测试,数组中的数据是无法直接传递给ListView 的,我们还需要借助适配器来完成。Android 中提供了很多适配器的实现类,最好用的就是ArrayAdapter。它可以通过泛型来指定要适配的数据类型,然后在构造函数中把要适配的数据传入即可。ArrayAdapter有多个构造函数的重载,这里由于我们提供的数据都是字符串,因此将ArrayAdapter 的泛型指定为String,然后在ArrayAdapter 的构造函数中依次传入当前上下文、ListView 子项布局的id,以及要适配的数据。注意我们使用了android.R.layout.simple_list_item_1 作为ListView 子项布局的id,这是一个Android 内置的布局文件,里面只有一个TextView,可用于简单地显示一段文本。这样适配器对象就构建好了。最后,还需要调用ListView 的setAdapter()方法,将构建好的适配器对象传递进去,这样ListView 和数据之间的关联就建立完成了。
定制ListView 的界面:
新建类Fruit,作为ListView 适配器的适配类型:
public
class
Fruit {
private
String name;
private
int
imageId;
public
Fruit(String name,
int
imageId) {
this
.name = name;
this
.imageId = imageId;
}
public
String getName() {
return
name;
}
public
int
getImageId() {
return
imageId;
}
}
为ListView 的子项指定一个我们自定义的布局, 在layout 目录下新建fruit_item.xml,代码如下所示:
<
LinearLayout
xmlns:android
=
"http://schemas.android.com/apk/res/android"
android:layout_width
=
"match_parent"
android:layout_height
=
"match_parent"
>
<
ImageView
android:id
=
"@+id/fruit_image"
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
/>
<
TextView
android:id
=
"@+id/fruit_name"
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:layout_gravity
=
"center"
android:layout_marginLeft
=
"10dip"
/>
</
LinearLayout
>
新建类FruitAdapter,代码如下所示:
public
class
FruitAdapter
extends
ArrayAdapter<Fruit> {
private
int
resourceId;
public
FruitAdapter(Context context,
int
textViewResourceId,List<Fruit> objects) {
super
(context, textViewResourceId, objects);
resourceId = textViewResourceId;
}
@Override
public
View getView(
int
position, View convertView, ViewGroup parent) {
Fruit fruit = getItem(position);
// 获取当前项的Fruit实例
View view = LayoutInflater.from(getContext()).inflate(resourceId,
null
);
ImageView fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
TextView fruitName = (TextView) view.findViewById(R.id.fruit_name);
fruitImage.setImageResource(fruit.getImageId());
fruitName.setText(fruit.getName());
return
view;
}
}
FruitAdapter 重写了父类的一组构造函数,用于将上下文、ListView 子项布局的id 和数据都传递进来。另外又重写了getView()方法,这个方法在每个子项被滚动到屏幕内的时候会被调用。在getView 方法中,首先通过getItem()方法得到当前项的Fruit 实例,然后使用LayoutInflater 来为这个子项加载我们传入的布局,接着调用View 的findViewById()方法分别获取到ImageView 和TextView 的实例,并分别调用它们的setImageResource()和setText()方法来设置显示的图片和文字,最后将布局返回。
MainActivity 中:
public
class
MainActivity
extends
Activity {
private
List<Fruit> fruitList =
new
ArrayList<Fruit>();
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initFruits();
// 初始化水果数据
FruitAdapter adapter =
new
FruitAdapter(MainActivity.
this
,R.layout.fruit_item, fruitList);
ListView listView = (ListView) findViewById(R.id.list_view);
listView.setAdapter(adapter);
}
private
void
initFruits() {
Fruit apple =
new
Fruit(
"Apple"
, R.drawable.apple_pic);
fruitList.add(apple);
Fruit banana =
new
Fruit(
"Banana"
, R.drawable.banana_pic);
fruitList.add(banana);
......
}
}
提升ListView 的运行效率:
1.在FruitAdapter 的getView()方法中每次都将布局重新加载了一遍,当ListView 快速滚动的时候这就会成为性能的瓶颈。getView()方法中还有一个convertView 参数,这个参数用于将之前加载好的布局进行缓存,以便之后可以进行重用。
2.每次在getView()方法中还是会调用View 的findViewById()方法来获取一次控件的实例。我们可以新增一个内部类ViewHolder,用于对控件的实例进行缓存。
public
class
FruitAdapter
extends
ArrayAdapter<Fruit> {
……
@Override
public
View getView(
int
position, View convertView, ViewGroup parent) {
Fruit fruit = getItem(position);
View view;
ViewHolder viewHolder;
if
(convertView ==
null
) {
view = LayoutInflater.from(getContext()).inflate(resourceId,
null
);
viewHolder =
new
ViewHolder();
viewHolder.fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
viewHolder.fruitName = (TextView) view.findViewById(R.id.fruit_name);
view.setTag(viewHolder);
// 将ViewHolder存储在View中
}
else
{
view = convertView;
viewHolder = (ViewHolder) view.getTag();
// 重新获取ViewHolder
}
viewHolder.fruitImage.setImageResource(fruit.getImageId());
viewHolder.fruitName.setText(fruit.getName());
return
view;
}
class
ViewHolder {
ImageView fruitImage;
TextView fruitName;
}
}
ListView 的点击事件:
MainActivity 中:
listView.setOnItemClickListener(
new
OnItemClickListener() {
@Override
public
void
onItemClick(AdapterView<?> parent, View view,
int
position,
long
id) {
Fruit fruit = fruitList.get(position);
Toast.makeText(MainActivity.
this
, fruit.getName(),Toast.LENGTH_SHORT).show();
}
});
单位和尺寸:
px:像素;
pt:磅数,1 磅等于1/72 英寸,一般pt 都会作为字体的单位来使用;
dp:密度无关像素,也被称作dip,和px 相比,它在不同密度的屏幕中的显示比例将保持一致;
sp:可伸缩像素;
Android 中的密度就是屏幕每英寸所包含的像素数,通常以dpi 为单位。根据Android 的规定,在160dpi 的屏幕上,1dp 等于1px,而在320dpi 的屏幕上,1dp就等于2px。sp 的原理和dp 是一样的,它主要是用于指定文字的大小。
总结一下,在编写Android 程序的时候,尽量将控件或布局的大小指定成match_parent或wrap_content,如果必须要指定一个固定值,则使用dp 来作为单位,指定文字大小的时候使用sp 作为单位。
编写界面的最佳实践----聊天界面:
制作Nine-Patch 图片:
在Android sdk 目录下有一个tools 文件夹,在这个文件夹中找到draw9patch.bat 文件,
我们就是使用它来制作Nine-Patch 图片的。
2.编写精美的聊天界面:
activity_main.xml中:
<
LinearLayout
xmlns:android
=
"http://schemas.android.com/apk/res/android"
android:layout_width
=
"match_parent"
android:layout_height
=
"match_parent"
android:background
=
"#d8e0e8"
android:orientation
=
"vertical"
>
<
ListView
android:id
=
"@+id/msg_list_view"
android:layout_width
=
"match_parent"
android:layout_height
=
"0dp"
android:layout_weight
=
"1"
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:layout_weight
=
"1"
android:hint
=
"Type somthing here"
android:maxLines
=
"2"
/>
<
Button
android:id
=
"@+id/send"
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:text
=
"Send"
/>
</
LinearLayout
>
</
LinearLayout
>
定义消息的实体类,新建Msg,代码如下所示:
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;
}
}
接着来编写ListView 子项的布局,新建msg_item.xml,代码如下所示:
<
LinearLayout
xmlns:android
=
"http://schemas.android.com/apk/res/android"
android:layout_width
=
"match_parent"
android:layout_height
=
"match_parent"
android:orientation
=
"vertical"
android:padding
=
"10dp"
>
<
LinearLayout
android:id
=
"@+id/left_layout"
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:layout_gravity
=
"left"
android:background
=
"@drawable/message_left"
>
<
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
=
"#fff"
/>
</
LinearLayout
>
<
LinearLayout
android:id
=
"@+id/right_layout"
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:layout_gravity
=
"right"
android:background
=
"@drawable/message_right"
>
<
TextView
android:id
=
"@+id/right_msg"
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:layout_gravity
=
"center"
android:layout_margin
=
"10dp"
/>
</
LinearLayout
>
</
LinearLayout
>
接下来需要创建ListView 的适配器类:
public
class
MsgAdapter
extends
ArrayAdapter<Msg> {
private
int
resourceId;
public
MsgAdapter(Context context,
int
textViewResourceId, List<Msg> objects) {
super
(context, textViewResourceId, objects);
resourceId = textViewResourceId;
}
@Override
public
View getView(
int
position, View convertView, ViewGroup parent) {
Msg msg = getItem(position);
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);
}
else
{
view = convertView;
viewHolder = (ViewHolder) view.getTag();
}
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;
}
class
ViewHolder {
LinearLayout leftLayout;
LinearLayout rightLayout;
TextView leftMsg;
TextView rightMsg;
}
}
最后修改MainActivity 中的代码,来为ListView 初始化一些数据,并给发送按钮加入事件响应,代码如下所示:
public
class
MainActivity
extends
Activity {
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);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
initMsgs();
// 初始化消息数据
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);
send.setOnClickListener(
new
OnClickListener() {
@Override
public
void
onClick(View v) {
String content = inputText.getText().toString();
if
(!
""
.equals(content)) {
Msg msg =
new
Msg(content, Msg.TYPE_SENT);
msgList.add(msg);
adapter.notifyDataSetChanged();
// 当有新消息时,刷新ListView中的显示
msgListView.setSelection(msgList.size());
// 将ListView定位到最后一行
inputText.setText(
""
);
// 清空输入框中的内容
}
}
});
}
private
void
initMsgs() {
Msg msg1 =
new
Msg(
"Hello guy."
, Msg.TYPE_RECEIVED);
msgList.add(msg1);
Msg msg2 =
new
Msg(
"Hello. Who is that?"
, Msg.TYPE_SENT);
msgList.add(msg2);
Msg msg3 =
new
Msg(
"This is Tom. Nice talking to you. "
, Msg.TYPE_RECEIVED);
msgList.add(msg3);
}
}
- 03UI
- 03 常用UI控件
- UI 03 UITextField
- UI基础学习03
- UI进阶03
- UI
- UI
- UI
- UI
- ui
- UI
- UI
- ui
- ui
- ui
- Ui
- UI
- ui
- 微信公众号js接口,实现图片的上传(拍照+本地相册)
- JavaWeb-实现多ip、异地 同时登录踢人下线
- eclipse+java+tomcat+maven 开发环境配置
- 第四部分:MapReduce 编程模型
- boost::bind
- 03UI
- centos 6.9 升级python 2.6.6 至 3.5.0
- BBS论坛项目 I
- 高级语言的编译:链接及装载过程介绍
- Redis的RDB和AOF持久化
- RN 的 fetch 组件网络请求
- JVM调优系列:(一)什么是JVM
- UESTC 1691 这是一道比CCCC简单题经典的中档题
- 04Broadcast Receiver