目标
- 掌握简单控件的使用,能够独立搭建一个注册界面
- 掌握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中通过重写指定的方法来添加额外的样式和功能。
3.1 实战演练—显示一个圆形
接下来,我们通过一个案例讲解如何使用自定义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对话框
四、编程题
1.整数加法
开发一个整数加法的程序,实现将计算结果显示到界面上的功能
src\main\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">
<EditText
android:id="@+id/addend"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:phoneNumber="true"
android:hint="加数"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="+"/>
<EditText
android:id="@+id/augend"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:phoneNumber="true"
android:hint="被加数"/>
<Button
android:id="@+id/equal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="="/>
<TextView
android:id="@+id/result"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
/>
</LinearLayout>
answer_addition\MainActivity.java
package cn.itcast.answer_addition;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private EditText ed_addend;
private EditText ed_augend;
private TextView tv_result;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ed_addend = findViewById(R.id.addend);
ed_augend = findViewById(R.id.augend);
tv_result = findViewById(R.id.result);
findViewById(R.id.equal).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String addend = ed_addend.getText().toString().trim();
String augend = ed_augend.getText().toString().trim();
if(addend ==null && addend.isEmpty()){
Toast.makeText(MainActivity.this,"请输入加数",Toast.LENGTH_SHORT).show();
return;
}else if (augend ==null && augend.isEmpty()){
Toast.makeText(MainActivity.this,"请输入被加数",Toast.LENGTH_SHORT).show();
return;
}
try {
int result = Integer.parseInt(addend)+Integer.parseInt(augend);
tv_result.setText(""+result);
}catch (Exception e){
Toast.makeText(MainActivity.this,"请输入整数",Toast.LENGTH_SHORT).show();
}
}
});
}
}
2.自定义的对话框
开发一个自定义的对话框,其界面中显示标题、提示内容、确定和取消按钮。当点击返回键时,用于提示用户是否退出程序。
src\main\res\layout\activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
src\main\java\answer_customdialog\MainActivity.java
package cn.itcast.answer_customdialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
final CommonDialog dialog = new CommonDialog(MainActivity.this);
dialog.setTitle("提示");
dialog.setMessage("您确定要退出本应用吗?");
dialog.setNegtive("取消");
dialog.setPositive("确定");
dialog.setOnClickBottomListener(new CommonDialog.
OnClickBottomListener() {
@Override
public void onPositiveClick() { //确定按钮的点击事件
dialog.dismiss();
MainActivity.this.finish();
}
@Override
public void onNegtiveClick() { //取消按钮的点击事件
dialog.dismiss();
}
});
dialog.show();
return true;
}
}
src\main\res\layout\custom_dialog.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">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp"
android:orientation="vertical">
<TextView android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:visibility="visible"
android:textColor="#333333"
android:textSize="18sp"
android:layout_marginBottom="16dp"/>
<TextView android:id="@+id/message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:textSize="14sp"
android:textColor="#999999" />
<View android:layout_width="match_parent"
android:layout_height="2px"
android:layout_marginTop="16dp"
android:background="#E8E8E8" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button android:id="@+id/negtive"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:layout_weight="1"
android:background="@null"
android:gravity="center"
android:singleLine="true"
android:textColor="#999999"
android:textSize="16sp" />
<View android:id="@+id/column_line"
android:layout_width="2px"
android:layout_height="match_parent"
android:background="#E8E8E8" />
<Button
android:id="@+id/positive"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginRight="10dp"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:background="@null"
android:gravity="center"
android:textColor="#38ADFF"
android:textSize="16sp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
src\main\java\answer_customdialog\CommonDialog.java
package cn.itcast.answer_customdialog;
import android.app.AlertDialog;
import android.content.Context;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class CommonDialog extends AlertDialog {
private TextView titleTv ; //显示的标题
private TextView messageTv ; //显示的消息
private Button negtiveBn ,positiveBn; //确认和取消按钮
public CommonDialog(Context context) {
super(context);
}
private String message;
private String title;
private String positive,negtive;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.custom_dialog);
initView(); //初始化界面控件
initEvent(); //初始化界面控件的点击事件
}
//初始化界面控件
private void initView() {
negtiveBn = (Button) findViewById(R.id.negtive);
positiveBn = (Button) findViewById(R.id.positive);
titleTv = (TextView) findViewById(R.id.title);
messageTv = (TextView) findViewById(R.id.message);
}
//初始化界面控件的显示数据
private void refreshView() {
//如果自定义了title和message会 显示自定义的信息,否则不显示title和message的信息
if (!TextUtils.isEmpty(title)) {
titleTv.setText(title); //设置标题控件的文本为自定义的title
titleTv.setVisibility(View.VISIBLE); //标题控件设置为显示状态
}else {
titleTv.setVisibility(View.GONE); //标题控件设置为隐藏状态
}
if (!TextUtils.isEmpty(message)) {
messageTv.setText(message); //设置消息控件的文本为自定义的message信息
}
//如果自定义了按钮的文本,则按钮显示自定义的文本,否则,按钮显示“确定”或“取消”文本
if (!TextUtils.isEmpty(positive)) {
positiveBn.setText(positive); //设置按钮的文本为自定义的文本信息
}else {
positiveBn.setText("确定"); //设置按钮文本为“确定”
}
if (!TextUtils.isEmpty(negtive)) {
negtiveBn.setText(negtive);
}else {
negtiveBn.setText("取消");
}
}
//初始化界面的确定和取消监听器
private void initEvent() {
//设置确定按钮的点击事件的监听器
positiveBn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (onClickBottomListener!= null) {
onClickBottomListener.onPositiveClick();
}
}
});
//设置取消按钮的点击事件的监听器
negtiveBn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if ( onClickBottomListener!= null) {
onClickBottomListener.onNegtiveClick();
}
}
});
}
@Override
public void show() {
super.show();
refreshView();
}
public interface OnClickBottomListener{
void onPositiveClick();//实现确定按钮点击事件的方法
void onNegtiveClick(); //实现取消按钮点击事件的方法
}
//设置确定取消按钮的回调
public OnClickBottomListener onClickBottomListener;
public CommonDialog setOnClickBottomListener(OnClickBottomListener
onClickBottomListener){
this.onClickBottomListener = onClickBottomListener;
return this;
}
public CommonDialog setMessage(String message) {
this.message = message;
return this ;
}
public CommonDialog setTitle(String title) {
this.title = title;
return this ;
}
public CommonDialog setPositive(String positive) {
this.positive = positive;
return this ;
}
public CommonDialog setNegtive(String negtive) {
this.negtive = negtive;
return this ;
}
}