CH3-Android常见界面控件
目标
- 掌握简单控件的使用,能够独立搭建一个注册界面
- 掌握ListView控件与RecyclerView控件的使用,能独立搭建列表界面
- 掌握自定义控件的定义方式,能够自定义一个简单的控件
几乎每一个Android应用都是通过界面控件与用户交互的,Android提供了非常丰富的界面控件,借助这些控件,我们可以很方便地进行用户界面开发。接下来,本章将针对Android常见的界面控件进行讲解。
一、简单控件的使用
1.1 TextView控件
控件是界面组成的主要元素,为了显示界面上的输入框、图片、文字等信息,Android系统提供了一些控件来显示这些信息,每个控件都有对应的属性来设置不同的效果。我们以控件使用的复杂程度将Android中的控件分别简单控件和列表控件,简单控件包含以下几种,具体如下图所示。

TextView控件用于显示文本信息,我们可以在XML布局文件中以添加属性的方式来控制TextView控件的样式, TextView控件的属性如下表所示。
| 属性名称 | 功能描述 |
|---|---|
| android:layout_width | 设置TextView控件的宽度 |
| android:layout_height | 设置TextView控件的高度 |
| android:id | 设置TextView控件的唯一标识 |
| android:background | 设置TextView控件的背景 |
| android:layout_margin | 设置当前控件与屏幕边界或周围控件、布局的距离 (外边距) |
| android:padding | 设置TextView控件与该控件中内容的距离 (内边距) |
| android:text | 设置文本内容 |
| android:textColor | 设置文字显示的颜色 |
| android:textSize | 设置文字大小,推荐单位为sp |
| android:gravity | 设置文本内容的位置 |
| android:maxLength | 设置文本最大长度,超出此长度的文本不显示 |
| android:lines | 设置文本的行数,超出此行数的文本不显示 |
| android:maxLines | 设置文本的最大行数,超出此行数的文本不显示。 |
| android:ellipsize | 设置当文本超出TextView规定的范围的显示方式。 |
| android:drawableTop | 在文本的顶部显示图像 |
| android:lineSpacingExtra | 设置文本的行间距 |
| android:textStyle | 设置文本样式,如bold(粗体),italic(斜体),normal(正常) |
接下来,我们通过一个案例讲解如何将TextView控件中的文本信息居中,并且将文本的字体设置为斜体进行显示,显示斜体文本的界面效果如下图所示。

放置界面控件
在res/layout文件夹的activity_main.xml文件中,放置1个TextView控件,用于显示文本信息。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextView控件显示的文本信息"
android:textColor="#FFF79E38"
android:textSize="25sp"
android:gravity="center"
android:textStyle="italic" />
</RelativeLayout>
1.2 EditText控件
EditText表示编辑框,它是TextView的子类,用户可在此控件中输入信息。除了支持TextView控件的属性外,EditText还支持一些其它的常用属性,这些常用属性如下表所示。
| 属性名称 | 功能描述 |
|---|---|
| android:hint | 控件中内容为空时显示的提示文本信息 |
| android:textColorHint | 控件中内容为空时显示的提示文本信息的颜色 |
| android:password | 输入文本框中的内容显示为“.” |
| android:phoneNumber | 设置输入文本框中的内容只能是数字 |
| android:maxLines | 设置文本的最大行数 |
| android:scrollHorizontally | 设置文本信息超出EditText的宽度情况下,是否出现横拉条 |
| android:editable | 设置是否可编辑 |
接下来,我们通过一个案例来讲解如何使用EditText控件编辑文本信息,本案例中显示编辑框的界面效果如下图所示。

创建程序
创建一个名为EditText的应用程序,指定包名为cn.itcast.edittext。
放置界面控件
在activity_main.xml文件中,放置1个TextView控件,用于显示标题,1个EditText控件,供用户输入文本信息。
<?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:padding="10dp"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="姓名:"
android:textSize="28sp"
android:textColor="#000000" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入姓名"
android:maxLines="2"
android:textColor="#000000"
android:textSize="20sp"
android:textStyle="italic" />
</LinearLayout>
1.3 Button控件
Button控件表示按钮,它继承TextView控件,既可以显示文本,又可以显示图片,同时也允许用户通过点击来执行操作,当Button控件被点击时,被按下与弹起的背景会有一个动态的切换效果,这个效果就是点击效果 。
Button控件设置点击事件的方式有三种,具体如下所示。
(1)在布局文件中指定onClick属性的方式设置点击事件
<Button
android:id="@+id/btn_two"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="click"
android:text="按钮2" />
(2)使用匿名内部类的方式设置点击事件
btn_one.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) { //按钮2的点击事件
btn_one.setText("按钮1已被点击");
}
});
(3)Activity实现OnClickListener接口的方式设置点击事件
public void click(View view) {
btn_two.setText("按钮2已被点击");
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_three: //按钮3的点击事件
btn_three.setText("按钮3已被点击");
break;
}
}
注意:实现Button控件的点击事件的三种方式中,前两种方式适合界面上Button控件较少的情况,如果界面上Button控件较多时,建议使用第三种方式实现控件的点击事件。

1.4 ImageView控件
ImageView控件表示图片,它继承自View,可以加载各种图片资源。ImageView控件的常用属性如下表所示。
| 属性名称 | 功能描述 |
|---|---|
| android:layout_width | 设置ImageView控件的宽度 |
| android:layout_height | 设置ImageView控件的高度 |
| android:id | 设置ImageView控件的唯一标识 |
| android:background | 设置ImageView控件的背景 |
| android:layout_margin | 设置当前控件与屏幕边界或周围控件的距离 |
| android:src | 设置ImageView控件需要显示的图片资源 |
| android:scaleType | 将图片资源缩放或移动,以适应ImageView控件的宽高 |
| android:tint | 将图片渲染成指定的颜色 |

res\layout\activity_main.xml下放置界面控件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bg" />
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:src="@drawable/icon" />
</RelativeLayout>
1.5 RadioButton控件
RadioButton表示单选按钮,它是Button的子类。每一个单选按钮都有“选中”和“未选中”两种状态,这两种状态是通过android:checked属性指定的。当可选值为true时,表示选中状态,否则,表示未选中状态。
在XML布局文件中,RadioGroup和RadioButton配合使用的语法格式如下:
<RadioGroup
android:属性名称 ="属性值"
......>
<RadioButton
android:属性名称 ="属性值"
...... />
......
<RadioGroup/>
接下来,我们通过一个案例来讲解如何使用RadioGroup和RadioButton实现单选按钮的功能。本案例的界面效果如下图所示。

res\layout\activity_main.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="match_parent"
android:orientation="vertical">
<RadioGroup
android:id="@+id/rdg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RadioButton
android:id="@+id/rbtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="25dp"
android:text="男" />
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="25dp"
android:text="女" />
</RadioGroup>
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30dp" />
</LinearLayout>
radiobutton\MainActivity.java下设置监听事件
package cn.itcast.radiobutton;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.RadioGroup;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private RadioGroup radioGroup;
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
radioGroup = findViewById(R.id.rdg);
textView = findViewById(R.id.tv);
//利用setOnCheckedChangeListener()为RadioGroup设置监听事件
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
//判断被点击的是哪一个RadioButton控件
if (checkedId == R.id.rbtn) {
textView.setText("您的性别是:男");
} else {
textView.setText("您的性别是:女");
}
}
});
}
}
1.6 CheckBox控件
CheckBox表示复选框,它是Button的子类,用于实现多选功能。每一个复选框都有“选中”和“未选中”两种状态,这两种状态是通过android:checked属性指定的,当该属性的值为true时,表示选中状态,否则,表示未选中状态。

res\layout\activity_main.xml下放置界面控件
<?xml version="1.0" encoding="utf-8"?>
<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"
tools:context=".MainActivity"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="请选择兴趣爱好:"
android:textColor="#FF8000"
android:textSize="18sp" />
<CheckBox
android:id="@+id/like_shuttlecock"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="羽毛球"
android:textSize="18sp" />
<CheckBox
android:id="@+id/like_basketball"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="篮球"
android:textSize="18sp" />
<CheckBox
android:id="@+id/like_pingpong"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="乒乓球"
android:textSize="18sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="您选择的兴趣爱好为:"
android:textColor="#FF8000"
android:textSize="22sp" />
<TextView
android:id="@+id/hobby"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp" />
</LinearLayout>
checkbox\MainActivity.java下实现控件的点击事件
package cn.itcast.checkbox;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity implements
CompoundButton.OnCheckedChangeListener {
private TextView hobby;
private String hobbys;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化CheckBox控件
CheckBox shuttlecock = findViewById(R.id.like_shuttlecock);
CheckBox basketball = findViewById(R.id.like_basketball);
CheckBox pingpong = findViewById(R.id.like_pingpong);
shuttlecock.setOnCheckedChangeListener(this);
basketball.setOnCheckedChangeListener(this);
pingpong.setOnCheckedChangeListener(this);
hobby = findViewById(R.id.hobby);
hobbys = new String();//存放选中的CheckBox的文本信息
}
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
String motion = buttonView.getText().toString();
if(isChecked){
if(!hobbys.contains(motion)){
hobbys = hobbys + motion;
hobby.setText(hobbys);
}
}else {
if (hobbys.contains(motion)) {
hobbys = hobbys.replace(motion, "");
hobby.setText(hobbys);
}
}
}
}
1.7 Toast类
Toast是Android系统提供的轻量级信息提醒机制,用于向用户提示即时消息,它显示在应用程序界面的最上层,显示一段时间后自动消失不会打断当前操作,也不获得焦点。
使用Toast显示提示信息的示例代码如下:
Toast.makeText(Context,Text,Time).show();
关于makeText()方法中参数的相关介绍具体如下:
Context:表示应用程序环境的信息,即当前组件的上下文环境。Text:表示提示的字符串信息。Time:表示显示信息的时长,其属性值包括Toast.LENGTH_SHORT和Toast.LENGTH_LONG,分别表示显示较短时间和较长时间。
MainActivity.java使用Toast提示用户“WIFI已断开”的信息,示例代码如下:
package cn.itcast.toast;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toast.makeText(MainActivity.this, "WIFI已断开", Toast.LENGTH_SHORT).show();
}
}
Toast提示用户“WIFI已断开”信息的效果如右图所示。

1.8 实战演练—实现注册界面效果
接下来我们通过实现一个注册界面的功能来演示如何使用Android程序中常用的简单控件,注册界面的效果如下图所示。


res\layout\activity_main.xml下放置界面控件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/register_bg">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#01ceff"
android:gravity="center"
android:text="注册"
android:textColor="@android:color/white"
android:textSize="20sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="130dp"
android:orientation="horizontal">
<TextView
style="@style/tvOne"
android:drawableTop="@drawable/qq_icon"
android:text="用QQ注册" />
<View style="@style/vLine" />
<TextView
style="@style/tvOne"
android:drawableTop="@drawable/weixin_icon"
android:text="用微信注册" />
</LinearLayout>
<View style="@style/hLine" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal"
android:padding="15dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:src="@drawable/email_icon" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:text="使用电子邮箱注册"
android:textColor="@android:color/white"
android:textSize="15sp" />
</LinearLayout>
<View style="@style/hLine" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="15dp">
<TextView
style="@style/tvTwo"
android:text="名字" />
<EditText
android:id="@+id/et_name"
style="@style/etOne" />
</LinearLayout>
<View style="@style/hLine" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="15dp">
<TextView
style="@style/tvTwo"
android:text="邮箱" />
<EditText
android:id="@+id/et_email"
style="@style/etOne" />
</LinearLayout>
<View style="@style/hLine" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="15dp">
<TextView
style="@style/tvTwo"
android:text="密码" />
<EditText
android:id="@+id/et_pwd"
style="@style/etOne"
android:inputType="textPassword" />
</LinearLayout>
<View style="@style/hLine" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="15dp">
<TextView
style="@style/tvTwo"
android:text="性别" />
<RadioGroup
android:id="@+id/rg_sex"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="50dp"
android:orientation="horizontal">
<RadioButton
android:id="@+id/rb_boy"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="男"
android:textColor="@android:color/white"
android:textSize="15sp" />
<RadioButton
android:id="@+id/rb_girl"
style="@style/tvTwo"
android:text="女"/>
</RadioGroup>
</LinearLayout>
<View style="@style/hLine" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="15dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="请选择兴趣爱好:"
android:textColor="@android:color/white"
android:textSize="15sp" />
<CheckBox
android:id="@+id/cb_sing"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="唱歌"
android:textColor="@android:color/white"
android:textSize="15sp" />
<CheckBox
android:id="@+id/cb_dance"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="跳舞"
android:textColor="@android:color/white"
android:textSize="15sp" />
<CheckBox
android:id="@+id/cb_read"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="读书"
android:textColor="@android:color/white"
android:textSize="15sp" />
</LinearLayout>
<View style="@style/hLine" />
</LinearLayout>
<View
android:id="@+id/v_line"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_above="@id/btn_submit"
android:background="@android:color/darker_gray" />
<Button
android:id="@+id/btn_submit"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:gravity="center"
android:text="提交"
android:textColor="@android:color/white"
android:background="@null"
android:textSize="18sp" />
</RelativeLayout>
res\values\styles.xml下创建样式
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="hLine">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">1dp</item>
<item name="android:background">@android:color/white</item>
</style>
<style name="vLine">
<item name="android:layout_width">1dp</item>
<item name="android:layout_height">match_parent</item>
<item name="android:background">@android:color/white</item>
</style>
<style name="tvOne">
<item name="android:layout_width">0dp</item>
<item name="android:layout_height">match_parent</item>
<item name="android:layout_weight">1</item>
<item name="android:drawablePadding">8dp</item>
<item name="android:gravity">center_horizontal</item>
<item name="android:paddingTop">40dp</item>
<item name="android:textColor">@android:color/white</item>
<item name="android:textSize">15dp</item>
</style>
<style name="tvTwo">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_marginLeft">20dp</item>
<item name="android:textColor">@android:color/white</item>
<item name="android:textSize">15dp</item>
</style>
<style name="etOne">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_marginLeft">30dp</item>
<item name="android:background">@null</item>
<item name="android:textColor">@android:color/white</item>
</style>
</resources>
src\main\AndroidManifest.xml下去掉默认标题栏
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.itcast.register">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.AppCompat.Light.NoActionBar">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
checkbox\MainActivity.java下实现注册功能
package cn.itcast.register;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.RadioGroup;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity implements View.OnClickListener, CompoundButton.OnCheckedChangeListener {
private EditText et_name, et_email, et_pwd;
private Button btn_submit;
private String name, email, pwd, sex, hobbys;
private RadioGroup rg_sex;
private CheckBox cb_sing,cb_dance,cb_read;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
private void init() {
//获取界面控件
et_name = findViewById(R.id.et_name);
et_email = findViewById(R.id.et_email);
et_pwd = findViewById(R.id.et_pwd);
rg_sex = findViewById(R.id.rg_sex);
cb_sing = findViewById(R.id.cb_sing);
cb_dance = findViewById(R.id.cb_dance);
cb_read = findViewById(R.id.cb_read);
btn_submit = findViewById(R.id.btn_submit);
btn_submit.setOnClickListener(this);//设置提交按钮的点击事件的监听器
//设置复选框控件的点击事件的监听器
cb_sing.setOnCheckedChangeListener(this);
cb_dance.setOnCheckedChangeListener(this);
cb_read.setOnCheckedChangeListener(this);
hobbys=new String();
//设置单选按钮的点击事件
rg_sex.setOnCheckedChangeListener(new RadioGroup.
OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
switch (checkedId){ //判断被点击的RadioButton
case R.id.rb_boy:
sex = "男";
break;
case R.id.rb_girl:
sex = "女";
break;
}
}
});
}
/**
* 获取界面输入的信息
*/
private void getData() {
name = et_name.getText().toString().trim();
email = et_email.getText().toString().trim();
pwd = et_pwd.getText().toString().trim();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_submit: //提交按钮的点击事件
getData();
if (TextUtils.isEmpty(name)) {
Toast.makeText(MainActivity.this, "请输入名字",
Toast.LENGTH_SHORT).show();
} else if (TextUtils.isEmpty(email)) {
Toast.makeText(MainActivity.this, "请输入邮箱",
Toast.LENGTH_SHORT).show();
} else if (TextUtils.isEmpty(pwd)) {
Toast.makeText(MainActivity.this, "请输入密码",
Toast.LENGTH_SHORT).show();
} else if (TextUtils.isEmpty(sex)) {
Toast.makeText(MainActivity.this, "请选择性别",
Toast.LENGTH_SHORT).show();
} else if (TextUtils.isEmpty(hobbys)) {
Toast.makeText(MainActivity.this, "请选择兴趣爱好",
Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this, "注册成功",
Toast.LENGTH_SHORT).show();
Log.i("MainActivity","注册的用户信息:"+"名字:"+name+", 邮箱:"
+email+", 性别:"+sex+", 兴趣爱好:"+hobbys);
}
break;
}
}
/**
* 复选框的点击事件
*/
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
String motion = buttonView.getText().toString();//获取复选框中的内容
if (isChecked) {
if (!hobbys.contains(motion)) { //判断之前选择的内容是否与此次选择的不一样
hobbys = hobbys + motion;
}
} else {
if (hobbys.contains(motion)) {
hobbys = hobbys.replace(motion, "");
}
}
}
}
二、列表控件的使用
目标
- 掌握ListView控件的使用,能够独立搭建购物商城界面
- 掌握RecyclerView控件的使用,能够独立搭建仿今日头条推荐列表界面
2.1 ListView控件
在Android开发中,ListView是一个比较常用的控件,它以列表的形式展示数据内容,并且能够根据列表的高度自适应屏幕显示。ListView的样式是由属性决定的,它的常用属性如下表所示。
| 属性名称 | 功能描述 |
|---|---|
| android:listSelector | 当条目被点击后,改变条目的背景颜色 |
| android:divider | 设置分割线的颜色 |
| android:dividerHeight | 设置分割线的高度 |
| android:scrollbars | 是否显示滚动条 |
| android:fadingEdge | 去掉上边和下边的黑色阴影 |
在XML文件的RelativeLayout布局中添加ListView控件的示例代码如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
......>
<ListView
android:id="@+id/lv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:listSelector="#fefefefe"
android:scrollbars="none">
</ListView>
</RelativeLayout>
2.2 常用数据适配器(Adapter)
数据适配器是数据与视图之间的桥梁,它类似于一个转换器,将复杂的数据转换成用户可以接受的方式进行呈现。
常用的数据适配器:
-
BaseAdapter:基本的适配器
-
SimpleAdapter:继承自BaseAdapter
-
ArrayAdapter:也是BaseAdapter的子类
BaseAdapter
BaseAdapter顾名思义是基本的适配器。它实际上是一个抽象类,通常在自定义适配器时会继承BaseAdapter,该类拥有四个抽象方法,根据这几个抽象方法对ListView控件进行数据适配。BaseAdapter中的4个抽象方法如下表所示。
| 方法名称 | 功能描述 |
|---|---|
| public int getCount() | 获取列表条目的总数 |
| public Object getItem(int position) | 根据position(位置)获取某个条目的对象 |
| public long getItemId(int position) | 根据position(位置)获取某个条目的id |
| public View getView(int position, View convertView, ViewGroup parent) | 获取相应position对应的条目视图,position是当前条目的位置,convertView用于复用旧视图,parent用于加载XML布局。 |
SimpleAdapter
SimpleAdapter继承BaseAdapter,实现了BaseAdapter的四个抽象方法并进行封装。SimpleAdapter的构造方法的具体信息如下:
public SimpleAdapter(
Context context, List<? extends Map<String, ?>> data,
int resource, String[] from, int[] to
)
在SimpleAdapter()构造方法中的5个参数的含义如下:
- context:表示
上下文对象。 - data:数据集合,data中的每一项
对应ListView控件中的条目的数据。 - resource:条目布局的
资源id。 - from:Map集合中的
key值。 - to:条目布局中
对应的控件。
ArrayAdapter
ArrayAdapter也是BaseAdapter的子类,用法与SimpleAdapter类似,开发者只需要在构造方法里面传入相应参数即可。ArrayAdapter通常用于适配TextView控件,ArrayAdapter有多个构造方法,构造方法的具体信息如下所示。
public ArrayAdapter(Context context,int resource);
public ArrayAdapter(Context context,int resource, int textViewResourceId);
public ArrayAdapter(Context context,int resource,T[] objects);
public ArrayAdapter(Context context,int resource,int textViewResourceId,T[] objects);
public ArrayAdapter(Context context,int resource,List<T> objects);
public ArrayAdapter(Context context,int resource,int textViewResourceId, List<T> objects)
在ArrayAdapter()构造方法中的4个参数的含义如下:
- context:表示
上下文对象。 - resource:条目布局的
资源id。 - textViewResourceId: 条目布局中对应的
TextView控件的id - List
objects: 需要适配的 List类型的数据
2.3 实战演练—购物商城
接下来我们通过一个购物商城的案例来演示如何通过ListView控件与数据适配器显示一个商品信息的列表。本案例的界面效果如下图所示。

res\layout\activity_main.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="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="45dp"
android:text="购物商城"
android:textSize="18sp"
android:textColor="#FFFFFF"
android:background="#FF8F03"
android:gravity="center"/>
<ListView
android:id="@+id/lv"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
res\layout\list_item.xml创建列表条目
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<ImageView
android:id="@+id/iv"
android:layout_width="120dp"
android:layout_height="90dp"
android:layout_centerVertical="true"/>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_toRightOf="@+id/iv"
android:layout_centerVertical="true">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="桌子"
android:textSize="20sp"
android:textColor="#000000" />
<TextView
android:id="@+id/tv_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="价格:"
android:textSize="20sp"
android:layout_marginTop="10dp"
android:layout_below="@+id/title"
android:textColor="#FF8F03" />
<TextView
android:id="@+id/price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1000"
android:textSize="20sp"
android:layout_below="@+id/title"
android:layout_toRightOf="@+id/tv_price"
android:textColor="#FF8F03"
android:layout_marginTop="10dp"/>
</RelativeLayout>
</RelativeLayout>
ListView\MainActivity.java下实现界面显示功能
package cn.itcast.listview;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
public class MainActivity extends Activity {
private ListView mListView;
//商品名称与价格数据集合
private String[] titles = {"桌子", "苹果", "蛋糕", "线衣", "猕猴桃", "围巾"};
private String[] prices = {"1800元", "10元/kg", "300元", "350元", "10元/kg",
"280元"};
//图片数据集合
private int[] icons = {R.drawable.table, R.drawable.apple, R.drawable.cake,
R.drawable.wireclothes, R.drawable.kiwifruit, R.drawable.scarf};
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mListView = findViewById(R.id.lv); //初始化ListView控件
MyBaseAdapter mAdapter = new MyBaseAdapter(); //创建一个Adapter的实例
mListView.setAdapter(mAdapter); //设置Adapter
}
class MyBaseAdapter extends BaseAdapter {
@Override
public int getCount() { //获取条目的总数
return titles.length; //返回条目的总数
}
@Override
public Object getItem(int position) {
return titles[position]; //返回条目的数据对象
}
@Override
public long getItemId(int position) {
return position; //返回条目的Id
}
//获取条目的视图
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
//将list_item.xml文件找出来并转换成View对象
convertView = View.inflate(MainActivity.this, R.layout.list_item, null);
//找到list_item.xml中创建的TextView
holder = new ViewHolder();
holder.title = convertView.findViewById(R.id.title);
holder.price = convertView.findViewById(R.id.price);
holder.iv = convertView.findViewById(R.id.iv);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.title.setText(titles[position]);
holder.price.setText(prices[position]);
holder.iv.setBackgroundResource(icons[position]);
return convertView;
}
class ViewHolder {
TextView title, price;
ImageView iv;
}
}
}
优化ListView加载数据逻辑
运行前面的购物商城程序后,当ListView控件上加载的条目过多,并快速滑动该列表控件时,界面会出现卡顿的现象,出现这个现象的原因如下:
(1)当滑动屏幕时,不断地创建条目对象
(2)不断执行findViewById()方法初始化界面控件
由于上述两点原因,我们需要对ListView控件进行优化,优化目的是使ListView控件在快速滑动时不再重复创建条目对象,减少内存的消耗和屏幕渲染的处理。优化方式有以下两种:
(1)使用ViewHolder类
(2)复用convertView
为了防止数据量过大造成内存溢出,在使用ListView时通常会进行优化,优化方式中的其中一种是复用convertView。


2.4 RecyclerView控件
RecyclerView与ListView控件相似,同样是以列表的形式展示数据,并且数据都是通过适配器加载的。RecyclerView的功能更加强大,接下来我们从以下几个方面来分析:

2.5 实战演练—动物列表
接下来,我们通过一个案例来讲解如何通过RecyclerView控件显示一个动物列表界面。本案例的界面效果如下图所示。


res\layout\activity_main.xml下放置界面控件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/id_recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</RelativeLayout>
res\layout\recycler_item.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:padding="16dp"
android:gravity="center"
android:orientation="horizontal">
<ImageView
android:id="@+id/iv"
android:layout_width="120dp"
android:layout_height="90dp"
android:src="@drawable/siberianhusky"/>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginTop="5dp">
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:textColor="#FF8F03"
android:text="哈士奇"/>
<TextView
android:id="@+id/introduce"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:layout_marginTop="10dp"
android:layout_below="@+id/name"
android:textColor="#FF716C6D"
android:maxLines="2"
android:ellipsize="end"
android:text="西伯利亚雪橇犬,常见别名哈士奇,昵称为二哈。"/>
</RelativeLayout>
</LinearLayout>
Recyclerview\MainActivity.java下实现界面显示功能
package cn.itcast.recyclerview;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private HomeAdapter mAdapter;
private String[] names = {"小猫", "哈士奇", "小黄鸭", "小鹿", "老虎"};
private int[] icons = {R.drawable.cat, R.drawable.siberianhusky,
R.drawable.yellowduck, R.drawable.fawn, R.drawable.tiger};
private String[] introduces = {
"猫,属于猫科动物,分家猫、野猫,是全世界家庭中较为广泛的宠物。",
"西伯利亚雪橇犬,常见别名哈士奇,昵称为二哈。",
"鸭的体型相对较小,颈短,一些属的嘴要大些。腿位于身体后方,因而步态蹒跚。",
"鹿科是哺乳纲偶蹄目下的一科动物。体型大小不等,为有角的反刍类。",
"虎,大型猫科动物;毛色浅黄或棕黄色,满有黑色横纹;头圆、耳短,耳背面黑色,中央有一白斑甚显著;四肢健壮有力;尾粗长,具黑色环纹,尾端黑色。"
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecyclerView = findViewById(R.id.id_recyclerview);
//设置RecyclerView控件的显示方式为线性垂直
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mAdapter = new HomeAdapter();
//将HomeAdapter对象设置到RecyclerView控件上
mRecyclerView.setAdapter(mAdapter);
}
class HomeAdapter extends RecyclerView.Adapter<HomeAdapter.MyViewHolder> {
@Override
//加载item界面的布局文件,并将MyViewHolder类的对象返回
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
MyViewHolder holder = new MyViewHolder(LayoutInflater.from(MainActivity.this).inflate(
R.layout.recycler_item, parent, false));
return holder;
}
@Override
//将获取的数据设置到对应的控件上
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.name.setText(names[position]);
holder.iv.setImageResource(icons[position]);
holder.introduce.setText(introduces[position]);
}
@Override
//获取列表条目的总数
public int getItemCount() {
return names.length;
}
class MyViewHolder extends RecyclerView.ViewHolder {
TextView name;
ImageView iv;
TextView introduce;
//获取item界面上的控件
public MyViewHolder(View view) {
super(view);
name = view.findViewById(R.id.name);
iv = view.findViewById(R.id.iv);
introduce = view.findViewById(R.id.introduce);
}
}
}
}
2.5 实战演练—仿今日头条
接下来以仿今日头条推荐列表为例,来演示如何使用RecyclerView控件,仿今日头条推荐列表界面的效果如下图所示。


res\values\styles.xml创建样式
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="tvStyle" >
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">match_parent</item>
<item name="android:padding">10dp</item>
<item name="android:gravity">center</item>
<item name="android:textSize">15sp</item>
</style>
<style name="tvInfo" >
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_marginLeft">8dp</item>
<item name="android:layout_gravity">center_vertical</item>
<item name="android:textSize">14sp</item>
<item name="android:textColor">@color/gray_color</item>
</style>
<style name="ivImg" >
<item name="android:layout_width">0dp</item>
<item name="android:layout_height">90dp</item>
<item name="android:layout_weight">1</item>
<!--ll_info为布局文件list_item_one.xml中的id -->
<item name="android:layout_toRightOf">@id/ll_info</item>
</style>
</resources>
res\values\colors.xml添加颜色值
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#008577</color>
<color name="colorPrimaryDark">#00574B</color>
<color name="colorAccent">#D81B60</color>
<color name="light_gray_color">#eeeeee</color>
<color name="gray_color">#828282</color>
</resources>
res\layout\title_bar.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="50dp"
android:background="#d33d3c"
android:orientation="horizontal"
android:paddingLeft="10dp"
android:paddingRight="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="仿今日头条"
android:textColor="@android:color/white"
android:textSize="22sp" />
<EditText
android:layout_width="match_parent"
android:layout_height="35dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="15dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="15dp"
android:background="@drawable/search_bg"
android:gravity="center_vertical"
android:textColor="@android:color/black"
android:hint="搜你想搜的"
android:textColorHint="@color/gray_color"
android:textSize="14sp"
android:paddingLeft="30dp" />
</LinearLayout>
res\layout\activity_main.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="match_parent"
android:background="@color/light_gray_color"
android:orientation="vertical">
<include layout="@layout/title_bar" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="@android:color/white"
android:orientation="horizontal">
<TextView
style="@style/tvStyle"
android:text="推荐"
android:textColor="@android:color/holo_red_dark" />
<TextView
style="@style/tvStyle"
android:text="抗疫"
android:textColor="@color/gray_color" />
<TextView
style="@style/tvStyle"
android:text="小视频"
android:textColor="@color/gray_color" />
<TextView
style="@style/tvStyle"
android:text="北京"
android:textColor="@color/gray_color" />
<TextView
style="@style/tvStyle"
android:text="视频"
android:textColor="@color/gray_color" />
<TextView
style="@style/tvStyle"
android:text="热点"
android:textColor="@color/gray_color" />
<TextView
style="@style/tvStyle"
android:text="娱乐"
android:textColor="@color/gray_color" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#eeeeee" />
<android.support.v7.widget.RecyclerView
android:id="@+id/rv_list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
res\layout\list_item_one/two.xml搭建列表条目界面
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="90dp"
android:layout_marginBottom="8dp"
android:background="@android:color/white"
android:padding="8dp">
<LinearLayout
android:id="@+id/ll_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/tv_title"
android:layout_width="280dp"
android:layout_height="wrap_content"
android:maxLines="2"
android:textColor="#3c3c3c"
android:textSize="16sp" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/iv_top"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignParentBottom="true"
android:src="@drawable/top" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_toRightOf="@id/iv_top"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_name"
style="@style/tvInfo" />
<TextView
android:id="@+id/tv_comment"
style="@style/tvInfo" />
<TextView
android:id="@+id/tv_time"
style="@style/tvInfo" />
</LinearLayout>
</RelativeLayout>
</LinearLayout>
<ImageView
android:id="@+id/iv_img"
android:layout_width="match_parent"
android:layout_height="90dp"
android:layout_toRightOf="@id/ll_info"
android:padding="3dp" />
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:background="@android:color/white">
<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="2"
android:padding="8dp"
android:textColor="#3c3c3c"
android:textSize="16sp" />
<LinearLayout
android:id="@+id/ll_img"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/tv_title"
android:orientation="horizontal">
<ImageView
android:id="@+id/iv_img1"
style="@style/ivImg"/>
<ImageView
android:id="@+id/iv_img2"
style="@style/ivImg"/>
<ImageView
android:id="@+id/iv_img3"
style="@style/ivImg"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/ll_img"
android:orientation="vertical"
android:padding="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_name"
style="@style/tvInfo" />
<TextView
android:id="@+id/tv_comment"
style="@style/tvInfo" />
<TextView
android:id="@+id/tv_time"
style="@style/tvInfo" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
headline\MainActivity.java 显示推荐列表的数据
package cn.itcast.headline;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private String[] titles = {"各地餐企齐行动,杜绝餐饮浪费",
"花菜有人焯水,有人直接炒,都错了,看饭店大厨如何做",
"睡觉时,双脚突然蹬一下,有踩空感,像从高楼坠落,是咋回事?",
"实拍外卖小哥砸开小吃店的卷帘门救火,灭火后淡定继续送外卖",
"还没成熟就被迫提前采摘,8毛一斤却没人要,果农无奈:不摘不行",
"大会、大展、大赛一起来,北京电竞“好嗨哟”"};
private String[] names = {"央视新闻客户端", "味美食记", "民富康健康", "生活小记",
"禾木报告", "燕鸣"};
private String[] comments = {"9884评", "18评", "78评", "678评", "189评",
"304评"};
private String[] times = {"6小时前", "刚刚", "1小时前", "2小时前", "3小时前",
"4个小时前"};
private int[] icons1 = {R.drawable.food, R.drawable.takeout,
R.drawable.e_sports};
private int[] icons2 = {R.drawable.sleep1, R.drawable.sleep2, R.drawable.sleep3,
R.drawable.fruit1,R.drawable.fruit2, R.drawable.fruit3};
//新闻类型,1表示置顶新闻或只有1张图片的新闻,2表示包含3张图片的新闻
private int[] types = {1, 1, 2, 1, 2, 1};
private RecyclerView mRecyclerView;
private NewsAdapter mAdapter;
private List<NewsBean> NewsList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setData();
mRecyclerView = findViewById(R.id.rv_list);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mAdapter = new NewsAdapter(MainActivity.this, NewsList);
mRecyclerView.setAdapter(mAdapter);
}
// 将定义的数组中的数据添加到新闻数据集合NewList中
private void setData() {
NewsList = new ArrayList<NewsBean>();
NewsBean bean;
for (int i = 0; i < titles.length; i++) {
bean = new NewsBean();
bean.setId(i + 1);
bean.setTitle(titles[i]);
bean.setName(names[i]);
bean.setComment(comments[i]);
bean.setTime(times[i]);
bean.setType(types[i]);
switch (i) {
case 0: //置顶新闻的图片设置
List<Integer> imgList0 = new ArrayList<>();
bean.setImgList(imgList0);
break;
case 1://设置第2个条目的图片数据
List<Integer> imgList1 = new ArrayList<>();
imgList1.add(icons1[i - 1]);
bean.setImgList(imgList1);
break;
case 2://设置第3个条目的图片数据
List<Integer> imgList2 = new ArrayList<>();
imgList2.add(icons2[i - 2]);
imgList2.add(icons2[i - 1]);
imgList2.add(icons2[i]);
bean.setImgList(imgList2);
break;
case 3://设置第4个条目的图片数据
List<Integer> imgList3 = new ArrayList<>();
imgList3.add(icons1[i - 2]);
bean.setImgList(imgList3);
break;
case 4://设置第5个条目的图片数据
List<Integer> imgList4 = new ArrayList<>();
imgList4.add(icons2[i - 1]);
imgList4.add(icons2[i]);
imgList4.add(icons2[i + 1]);
bean.setImgList(imgList4);
break;
case 5://设置第6个条目的图片数据
List<Integer> imgList5 = new ArrayList<>();
imgList5.add(icons1[i - 3]);
bean.setImgList(imgList5);
break;
}
NewsList.add(bean);
}
}
}
headline\NewsAdapter.java 创建适配器NewsAdapter
package cn.itcast.headline;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.List;
public class NewsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context mContext;
private List<NewsBean> NewsList;
public NewsAdapter(Context context,List<NewsBean> NewsList) {
this.mContext = context;
this.NewsList=NewsList;
}
//加载条目视图
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent,
int viewType) {
View itemView=null;
RecyclerView.ViewHolder holder=null;
if (viewType == 1){
itemView = LayoutInflater.from(mContext).inflate(R.layout.
list_item_one, parent, false);
holder= new MyViewHolder1(itemView);
}else if (viewType == 2){
itemView = LayoutInflater.from(mContext).inflate(R.layout.
list_item_two, parent, false);
holder= new MyViewHolder2(itemView);
}
return holder;
}
// 获取条目类型
@Override
public int getItemViewType(int position) {
return NewsList.get(position).getType();
}
// 绑定界面数据
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder,
int position) {
NewsBean bean=NewsList.get(position);
if (holder instanceof MyViewHolder1){
if (position==0) {
((MyViewHolder1) holder).iv_top.setVisibility(View.VISIBLE);
((MyViewHolder1) holder).iv_img.setVisibility(View.GONE);
} else {
((MyViewHolder1) holder).iv_top.setVisibility(View.GONE);
((MyViewHolder1) holder).iv_img.setVisibility(View.VISIBLE);
}
((MyViewHolder1) holder).title.setText(bean.getTitle());
((MyViewHolder1) holder).name.setText(bean.getName());
((MyViewHolder1) holder).comment.setText(bean.getComment());
((MyViewHolder1) holder).time.setText(bean.getTime());
if (bean.getImgList().size()==0)return;
((MyViewHolder1) holder).iv_img.setImageResource(bean.getImgList()
.get(0));
}else if (holder instanceof MyViewHolder2){
((MyViewHolder2) holder).title.setText(bean.getTitle());
((MyViewHolder2) holder).name.setText(bean.getName());
((MyViewHolder2) holder).comment.setText(bean.getComment());
((MyViewHolder2) holder).time.setText(bean.getTime());
((MyViewHolder2) holder).iv_img1.setImageResource(bean.getImgList()
.get(0));
((MyViewHolder2) holder).iv_img2.setImageResource(bean.getImgList()
.get(1));
((MyViewHolder2) holder).iv_img3.setImageResource(bean.getImgList()
.get(2));
}
}
// 获取条目总数
@Override
public int getItemCount() {
return NewsList.size();
}
class MyViewHolder1 extends RecyclerView.ViewHolder {
ImageView iv_top,iv_img;
TextView title,name,comment,time;
public MyViewHolder1(View view) {
super(view);
iv_top = view.findViewById(R.id.iv_top);
iv_img = view.findViewById(R.id.iv_img);
title = view.findViewById(R.id.tv_title);
name = view.findViewById(R.id.tv_name);
comment = view.findViewById(R.id.tv_comment);
time = view.findViewById(R.id.tv_time);
}
}
class MyViewHolder2 extends RecyclerView.ViewHolder {
ImageView iv_img1,iv_img2,iv_img3;
TextView title,name,comment,time;
public MyViewHolder2(View view) {
super(view);
iv_img1 = view.findViewById(R.id.iv_img1);
iv_img2 = view.findViewById(R.id.iv_img2);
iv_img3 = view.findViewById(R.id.iv_img3);
title = view.findViewById(R.id.tv_title);
name = view.findViewById(R.id.tv_name);
comment = view.findViewById(R.id.tv_comment);
time = view.findViewById(R.id.tv_time);
}
}
}
headline\NewsBean.java 封装新闻信息实体类,在该类中创建新闻信息属性对应的字段
package cn.itcast.headline;
import java.util.List;
public class NewsBean {
private int id; //新闻id
private String title; //新闻标题
private List<Integer> imgList; //新闻图片
private String name; //用户名
private String comment; //用户评论
private String time; //新闻发布时间
private int type; //新闻类型
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
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 getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public List<Integer> getImgList() {
return imgList;
}
public void setImgList(List<Integer> imgList) {
this.imgList = imgList;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
}
三、自定义控件
目标
- 掌握自定义View中的3个方法,能够在界面中绘制一个圆形图案
通常开发Android应用的界面时,使用的控件都不直接使用View,而是使用View的子类。虽然Android系统中提供了很多继承View类的控件,但是在实际开发中,还会出现不满足需求的情况。此时我们可以通过自定义View的方式进行实现。
当使用系统控件不满足需求时,需要自定义控件。最简单的自定义View就是创建一个类继承自View类或者其子类,并重写该类的构造方法。示例代码如下:
public class Customview extends View{
//在Java代码中创建对象时,使用该构造函数
public Customview(Context context) {
super(context);
}
//在XML布局中引入自定义控件时,使用该构造函数
public Customview(Context context, AttributeSet attrs) {
super(context, attrs);
}
}
由于系统自带的控件不能满足需求中的某种样式或功能,所以我们需要在自定义View中通过重写指定的方法来添加额外的样式和功能。

接下来,我们通过一个案例讲解如何使用自定义View在界面中显示一个圆形,显示圆形界面的效果如下图所示。

customview\CircleView.java自定义CircleView类
package cn.itcast.customview;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
public class CircleView extends View {
public CircleView(Context context) {
super(context);
}
public CircleView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int r = getMeasuredWidth() / 2;
int centerX = getLeft() + r;
int centerY = getTop()+ r;
Paint paint = new2 Paint();
paint.setColor(Color.RED);
//开始绘制
canvas.drawCircle(centerX, centerY, r, paint);
}
}
res\layout\activity_main.xml引用自定义控件CustomView
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp">
<cn.itcast.customview.CircleView
android:layout_width="100dp"
android:layout_height="100dp"/>
</RelativeLayout>
AlertDialog对话框
浙公网安备 33010602011771号