(3)Android常见界面控件

3.1 简单控件的使用

Android界面上有很多的输入框,文字,图片,按钮等,这些都是Android提供的一些简单的控件来显示这些信息

3.1.1 TextView控件

用于显示文字信息,可在XML文件中设置其样式,相关属性如图

image-20220323184647478

image-20220323184717910

<TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="hello"
        android:textSize="20dp"
        android:id="@+id/tv_1"/>

3.1.2 EditText控件

表示编辑框,是TextView控件类的子类,下图是除TextView外其他的属性

image-20220323185357792

<TextView
    android:id="@+id/tv_1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="姓名"
    android:textSize="50dp"
    android:layout_margin="20dp"/>
<EditText
    android:layout_below="@id/tv_1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="请输入姓名:"
    android:layout_margin="20dp"/>

image-20220323185842545

3.1.3 Button控件

Button控件表示按钮,继承自TextView控件类,既可以显示文本,也可以显示图片,可以执行点击操作(理论上所有控件都可以设置点击事件)

通过以下属性来设置Button的点击事件,这句代码在XML中,需要在对应的Activity中设置一个方法名为click的点击事件方法,也就是与属性值同名

一下为三种方法实现点击事件

方法一:布局文件中指定点击事件(不常用)
android:onClick = "click"
   //Activity中的代码
   public void click(View view)
    {
        Log.w("MainActivity","yes");
    }
方法二:使用内部匿名类实现点击事件

在Activity中使用内部匿名类实现点击操作

mbtn1.setOnClickListener(new View.OnClickListener() {//按钮1点击事件,使用方法二匿名内部类
            @Override
            public void onClick(View view) {
                mbtn1.setText("按钮1被点击");
            }
        });
方法三:使用Activity实现OnClickListener接口

使用当前Activity实现View.OnClickListener接口,可以实现点击事件,实现代码在下面

全部实现代码举例

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="20dp">
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/btn1"
        android:text="按钮1"/>
    <Button
        android:layout_below="@id/btn1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/btn2"
        android:onClick="click"
        android:text="按钮2"/>

    <Button
        android:id="@+id/btn3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/btn2"
        android:text="按钮3" />

</RelativeLayout>

MainActivity

package cn.itcast.animalconnection;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

import java.nio.BufferUnderflowException;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    private Button mbtn1,mbtn2,mbtn3;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mbtn1 = findViewById(R.id.btn1);//找到xml中的Button控件与Button变量一一对应
        mbtn2 = findViewById(R.id.btn2);
        mbtn3 = findViewById(R.id.btn3);
        mbtn3.setOnClickListener(this);//设置按钮3的监听按钮事件

        mbtn1.setOnClickListener(new View.OnClickListener() {//按钮1点击事件,使用方法二匿名内部类
            @Override
            public void onClick(View view) {
                mbtn1.setText("按钮1被点击");
            }
        });
    }

    public void click(View view)//按钮2点击事件,使用方法一,在xml中指定了onClick属性
    {
        mbtn2.setText("按钮2被点击");
    }

    @Override
    public void onClick(View v)//按钮3点击事件,使用方法三,实现OnClickListener接口
    {
        switch (v.getId())
        {
            case R.id.btn3:
                mbtn3.setText("按钮3被点击");
        }
    }
}

image-20220323213834517

3.1.4 ImageView控件

ImageView控件表示图片,继承自View,可以加载各种图片资源,常用属性如下

image-20220323214202197

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="20dp"
    android:orientation="vertical">
    <ImageView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="@drawable/s"/>
    <ImageView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="@drawable/w"/>
    <ImageView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="@drawable/q"/>
</LinearLayout>

image-20220323214902220

注意点:

android:background="@drawable/w"设置的背景,默认拉伸显示

android:src="@drawable/w"设置的是前景,默认原图显示

3.1.5 RadioButton控件

RadioButton表示单选按钮,是Button的一个子类,每一个单选按钮都有选中和未选中两种状态,都是通过android:checked属性指定的

在Android程序中,该控件经常与RadioGroup配合使用,实现单选按钮的功能,RadioGroup是单选组合框,RadioGroup继承自LinearLayout,可以使用android:orientation属性控制RadioButton的排列方向

    <RadioGroup
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <RadioButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text=""/>
        <RadioButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text=""/>
    </RadioGroup>

image-20220323220434984

设置监听事件

参考代码

//MainActivity
public class MainActivity extends AppCompatActivity{
    private RadioGroup mrg1;
    private TextView mtv1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mrg1 = findViewById(R.id.rg_1);
        mtv1 = findViewById(R.id.tv_1);
        //设置监听事件
        mrg1.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup radioGroup, int i) {//i就是状态为选中的那个单选按钮的id
                if(i == R.id.rb_1)
                {
                    mtv1.setText("你的性别是:男");
                }
                else
                {
                    mtv1.setText("你的性别是:女");
                }
            }
        });
    }
}

3.1.6 CheckBox控件

CheckBox表示复选框,是Button的子类,选中的属性和单选按钮是一样的

与单选框类似,但不需要包含在RadioGroup中

代码举例

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="20dp"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="选择你的性别:"
        android:textSize="15sp"/>
    <CheckBox
        android:id="@+id/cb_1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="羽毛球"/>
    <CheckBox
        android:id="@+id/cb_2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="篮球"/>
    <CheckBox
        android:id="@+id/cb_3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="乒乓球"/>
    <TextView
        android:id="@+id/tv_1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="你的兴趣爱好是"
        android:textSize="20sp"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/tv_2"
        android:textSize="20sp"/>
</LinearLayout>

MainActivity

package cn.itcast.animalconnection;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.RadioGroup;
import android.widget.TextView;

import java.nio.BufferUnderflowException;

public class MainActivity extends AppCompatActivity implements CompoundButton.OnCheckedChangeListener{
    private TextView hobby;//输出TextView控件
    private String hobbys;//存放输出内容
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        CheckBox mcb1 = findViewById(R.id.cb_1);
        CheckBox mcb2 = findViewById(R.id.cb_2);
        CheckBox mcb3 = findViewById(R.id.cb_3);
        mcb1.setOnCheckedChangeListener((CompoundButton.OnCheckedChangeListener) this);//找到对应控件,需要转换一下类型
        mcb2.setOnCheckedChangeListener((CompoundButton.OnCheckedChangeListener) this);
        mcb3.setOnCheckedChangeListener((CompoundButton.OnCheckedChangeListener) this);
        hobby = findViewById(R.id.tv_2);
        hobbys = new String();
    }
    @Override
    public void onCheckedChanged(CompoundButton buttonview,boolean ischecked)//监听事件,两个参数表示被点击的控件和控件的状态,实现对应接口
    {
        String motion = buttonview.getText().toString();//被点击控件的文字
        if(ischecked)
        {
            if(!hobbys.contains(motion))//字符串中没有这个文字就加入,下面else没有就删除
            {
                hobbys = hobbys + motion;
                hobby.setText(hobbys);
            }
        }
        else
        {
            if (hobbys.contains(motion))
            {
                hobbys = hobbys.replace(motion,"");//替换字符串
                hobby.setText(hobbys);
            }
        }
    }
}

image-20220323224311620

3.1.7 Toast类

Toast类是android提供的轻量级信息提醒机制,用于向用户提示即时消息,显示在应用程序的最上层,显示一段时间后自动消失不会打断当前操作,也不会获得焦点

Toast.makeText(Context,Text,time).show();//需要调用show()方法才会显示
  • Context:表示应用程序环境信息,即当前组件的上下文环境,Context是一个抽象类,若在Activity中使用,可以将参数设置为``Activity.this`
  • Text:提示的字符串信息
  • Time:表示显示时间的长短,属性值包括两个固定的参数

3.1.8 实战演练—实现注册界面效果

目标:实现一个注册演示界面,通过日志返回注册信息

创建样式

下面是示例创建的样式,我实际没有使用这些样式,都是一个一个打上去的,这个样式不知道为什么覆盖了其他的默认属性值

themes.xml

<resources xmlns:tools="http://schemas.android.com/tools">
    <!-- Base application theme. -->
    <style name="Theme.仿连连看" parent="Theme.MaterialComponents.DayNight.Bridge">
        <!-- Primary brand color. -->
        <item name="titleTextColor">@android:color/white</item>
        <item name="colorPrimary">@color/purple_500</item>
        <item name="colorPrimaryVariant">@color/purple_700</item>
        <item name="colorOnPrimary">@color/white</item>
        <!-- Secondary brand color. -->
        <item name="colorSecondary">@color/teal_200</item>
        <item name="colorSecondaryVariant">@color/teal_700</item>
        <item name="colorOnSecondary">@color/white</item>
        <!-- Status bar color. -->
        <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
        <!-- Customize your theme here. -->
    </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>
<!--    文本样式1-->
    <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">15sp</item>
    </style>
<!--    文本样式2-->
    <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">15sp</item>
    </style>
<!--    输入框样式-->
    <style name="teOne">
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_marginTop">30dp</item>
        <item name="android:background">@null</item>
        <item name="android:textColor">@android:color/black</item>
    </style>
</resources>
放置界面控件

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="20dp"
    android:orientation="vertical">

    <TextView
        android:layout_marginTop="20dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="注册"
        android:textSize="35sp"
        android:layout_gravity="center_horizontal"/>
    <LinearLayout
        android:layout_marginTop="30dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <EditText
            android:id="@+id/name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:hint="输入账号名:"/>
        <EditText
            android:id="@+id/email"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:hint="输入邮箱:"/>
        <EditText
            android:id="@+id/pwd"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:hint="输入密码"
            android:password="true"/>
    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_marginTop="20dp">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="性别:"
            android:textSize="20sp"
            android:layout_marginRight="20dp"
            android:layout_marginLeft="10dp"/>
        <RadioGroup
            android:id="@+id/sex"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            >
            <RadioButton
                android:id="@+id/man"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text=""
                android:layout_marginRight="20dp"/>
            <RadioButton
                android:id="@+id/woman"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text=""/>
        </RadioGroup>

    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="请选择兴趣爱好:"
            android:textSize="20sp"/>
        <CheckBox
            android:id="@+id/sing"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="唱歌"/>
        <CheckBox
            android:id="@+id/dance"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="跳舞"/>
        <CheckBox
            android:id="@+id/read"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="读书"/>
    </LinearLayout>
    <CheckBox
        android:id="@+id/fage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="我已确认信息无误"
        android:textColor="#00BCD4"
        android:layout_marginTop="20dp"/>
    <Button
        android:id="@+id/login"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="注册"
        android:layout_margin="30dp"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:text="--其他登陆方式--"/>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:layout_marginTop="20dp"
            android:layout_marginLeft="40dp"
            android:layout_marginRight="40dp">


        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:orientation="vertical">
            <ImageView
                android:layout_width="30dp"
                android:layout_height="30dp"
                android:src="@drawable/w"
                android:layout_gravity="center_horizontal"/>
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="QQ"
                android:layout_gravity="center_horizontal"/>
        </LinearLayout>
        <LinearLayout
            android:layout_weight="1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical">
            <ImageView
                android:layout_width="30dp"
                android:layout_height="30dp"
                android:src="@drawable/s"
                android:layout_gravity="center_horizontal"/>
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="微信"
                android:layout_gravity="center_horizontal"/>
        </LinearLayout>
        <LinearLayout
            android:layout_weight="1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical">
            <ImageView
                android:layout_width="30dp"
                android:layout_height="30dp"
                android:src="@drawable/q"
                android:layout_gravity="center_horizontal"/>
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="游客"
                android:layout_gravity="center_horizontal"/>
        </LinearLayout>
        </LinearLayout>
    </LinearLayout>
</LinearLayout>

实现注册功能
package cn.itcast.animalconnection;
import androidx.appcompat.app.AppCompatActivity;
import android.graphics.Color;
import android.os.Bundle;
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.TextView;
import android.widget.Toast;
import java.nio.BufferUnderflowException;
public class MainActivity extends AppCompatActivity implements View.OnClickListener,CompoundButton.OnCheckedChangeListener{

    private EditText ed_name,ed_pwd,ed_email;
    private Button btn_submit;
    private String name,email,pwd,sex,hobbys;
    private RadioGroup rg_sex;
    private CheckBox cb_sing,cb_dance,cb_read,flge;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
    }
    private void init()
    {
        ed_name = findViewById(R.id.name);
        ed_email = findViewById(R.id.email);
        ed_pwd = findViewById(R.id.pwd);
        btn_submit = findViewById(R.id.login);
        rg_sex = findViewById(R.id.sex);
        cb_sing = findViewById(R.id.sing);
        cb_dance = findViewById(R.id.dance);
        cb_read = findViewById(R.id.read);
        flge = findViewById(R.id.fage);
        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 radioGroup, int i) {
                switch (i)
                {
                    case R.id.man:
                        sex = "男";
                        break;
                    case R.id.woman:
                        sex = "女";
                        break;
                }
            }
        });
    }
    private void getDate()//获取界面信息
    {
        name = ed_name.getText().toString();
        email = ed_email.getText().toString();
        pwd = ed_pwd.getText().toString();
    }

    @Override
    public void onClick(View view) //提交按钮
    {
        switch (view.getId()) {
            case R.id.login:
                getDate();
                if (TextUtils.isEmpty(name))
                    Toast.makeText(MainActivity.this, "请输入名字", Toast.LENGTH_LONG).show();
                else if (TextUtils.isEmpty(email))
                    Toast.makeText(MainActivity.this, "请输入邮箱", Toast.LENGTH_LONG).show();
                else if (TextUtils.isEmpty(pwd))
                    Toast.makeText(MainActivity.this, "请输入密码", Toast.LENGTH_LONG).show();
                else if (TextUtils.isEmpty(sex))
                    Toast.makeText(MainActivity.this, "请选择性别", Toast.LENGTH_LONG).show();
                else if (TextUtils.isEmpty(hobbys))
                    Toast.makeText(MainActivity.this, "请选择兴趣爱好", Toast.LENGTH_LONG).show();
                else if (!flge.isChecked())//确认复选框
                {
                    Toast.makeText(MainActivity.this, "请选择确认无误", Toast.LENGTH_LONG).show();
                    flge.setTextColor(Color.parseColor("#FF3030"));
                }
                else
                {
                    Toast.makeText(MainActivity.this, "注册成功", Toast.LENGTH_LONG).show();
                    Log.i("MainActiity","注册的用户信息:"+" 名字:"+name+"邮箱:"+email+"密码:"+pwd+"性别:"+sex+"兴趣爱好:"+hobbys);
                }
                break;
        }
    }

    @Override
    public void onCheckedChanged(CompoundButton compoundButton, boolean b)//复选框设置监听事件
    {
        String motion = compoundButton.getText().toString();
        if(b)
        {
            if(!hobbys.contains(motion))
                hobbys = hobbys + motion;
        }
        else
        {
            if(!hobbys.contains(motion))
                hobbys = hobbys + motion;
        }
    }
}
示例图

image-20220324175732867

3.2 列表控件的使用

日常生活中,淘宝,微信等应用程序,通常会在页面中展示很多的条目,并且每一个条目的风格一致,这种数据方式就是通过ListView或RecyclerView控件实现的

3.2.1 ListView控件的使用

ListView是一个比较常用的控件,以列表的形式展示数据内容,能够根据列表的高度自适应屏幕显示,ListView的属性如下图

image-20220324190912574

<ListView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:listSelector="#fefefe" >
</ListView>

###3.2.2 常用数据适配器

为ListView添加数据的时候会用到数据适配器,数据适配器是数据与视图之间沟通的桥梁,类似一个转换器,将复杂的数据转换成用户可以接受的方式进行呈现,下面是几个常用的数据适配器

BaseAdapter

BaseAdapter是一个基本适配器,实际上是一个抽象类,通常在自定义数据适配器的时候会继承自这个类,该类的抽象方法如下

image-20220324191928227

SimpleAdapter

SimpleAdapter继承自BaseAdapter,实现了四个抽象方法,并进行封装,使用SimpleAdapter进行数据适配的时候只需要在构造函数传入对应的参数即可

public SimpleAdapter(Context context,List<? extends Map<String,?>>data,int resource,String[] from,int[] to);
  • context :上下文对象
  • data :数据集合,data中的每一项对应ListView条目中的数据
  • resource :Item布局的资源id
  • from :Map集合中的key值
  • to :Item布局中对应的控件
ArrayAdapter

ArrayAdapter是BaseAdapter的子类,ArrayAdapter控件通常用于适配TextView控件,例如Android中的设置菜单

构造方法如下

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,List<T>objects);
public ArrayAdapter(Context context,int resource,int textViewResourceId,List<T> objects);
  • context:上下文对象
  • resource:Item布局的资源id
  • textViewResourceId:Item布局中相应TextView控件的id
  • T[] objects:需要适配数组类型的数据
  • Listobjects:需要适配List类型的数据

设置数据适配器到ListView控件举例

ListView mListView = (ListView)findViewById(R.id.lv);
BaseAdapter madapter = new BaseAdapter();
mListView.setAdapter(madapter);

3.2.3 实战演练-购物商城

####activity_main.xml----创建ListView控件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:padding="20dp"
    android:orientation="vertical">
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="购物商城"
        android:gravity="center_horizontal"
        android:background="#DA8282"/>
    <ListView
        android:id="@+id/lv_1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    </ListView>
</LinearLayout>
list_item.xml----用于定义ListView单个条目的布局
<?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>

MainActivity.java
package cn.itcast.test2;
import androidx.appcompat.app.AppCompatActivity;
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 AppCompatActivity {
    private ListView mlistview;
    private String[] titles = {"桌子","苹果","蛋糕","线衣","猕猴桃","围巾"};
    private String[] prices = {"1800元","10元","300元","350元","500元","10元","280元"};
    private int[] icons ={R.drawable.a,R.drawable.b,R.drawable.c,R.drawable.a,R.drawable.b,R.drawable.c};//图片集合
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mlistview = findViewById(R.id.lv_1);
        MyBaseAdapter madapter = new MyBaseAdapter();
        mlistview.setAdapter(madapter);
    }
    class MyBaseAdapter extends BaseAdapter//实现抽象类,不然不能使用
    {
        @Override
        public int getCount() {//获取条目的总数
            return titles.length;
        }
        @Override
        public Object getItem(int i) {//返回条目的数据对象
            return titles[i];
        }
        @Override
        public long getItemId(int i) {//返回条目的id
            return i;
        }
        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {//获取条目的视图
            View v = View.inflate(MainActivity.this,R.layout.list_item,null);//创建视图对象
            TextView title = v.findViewById(R.id.title);//引入控件对象
            TextView price = v.findViewById(R.id.price);
            ImageView iv = v.findViewById(R.id.iv);
            title.setText(titles[i]);
            price.setText(prices[i]);
            iv.setBackgroundResource(icons[i]);
            return v;
        }
    }
}

image-20220326212033368
优化ListView控件

当运行上述程序的时候,当ListView控件上加载的item过多,并且快速滑动屏幕的时候就会产生卡顿,出现的原因如下

  • 滑出屏幕区域的item会被销毁,滑入的会创建,当滑动屏幕的时候就会不断销毁创建
  • 不断执行findViewById()方法初始化控件,每创建一个对象都需要执行这个方法

优化:

在item出屏幕的时候,item会先以缓存的形式暂时保存,getView()方法中的第二个参数就是旧的对象,就可以修改getView()方法利用原来的旧对象来刷新新的信息,就可以有效减少频繁的创建销毁对象,具体修改的代码如下

MyBaseAdapter类下的getView()方法

public View getView(int i, View view, ViewGroup viewGroup) {//获取条目的视图,第二个参数代表滑出的item
            ViewHolder holder = null;
            if(view == null)
            {
                view = View.inflate(MainActivity.this,R.layout.list_item,null);//获取item样式
                holder = new ViewHolder();
                holder.title = view.findViewById(R.id.title);
                holder.price = view.findViewById(R.id.price);
                holder.iv = view.findViewById(R.id.iv);
                view.setTag(holder);
            }
            else//如果有旧对象
            {
                holder = (ViewHolder) view.getTag();//获得缓存中的ViewHolder类的对象
            }
            holder.title.setText(titles[i]);
            holder.price.setText(prices[i]);
            holder.iv.setBackgroundResource(icons[i]);
            return view;
        }

3.2.4 RecyclerView控件的使用

此控件用于在有限的空间内显示大量数据,与ListView类似,该控件以列表的形式展示数据,数据通过数据适配器加载,但是这个控件比ListView更加强大

优越性:
  • RecyclerView控件可以通过LayoutManner类实现横向和竖向的列表效果,瀑布流效果和GridView效果,而ListView只能实现竖直的列表效果
  • RecyclerView控件使用RecyclerView.Adapter,该数据适配器将BaseAdapter中的getView()方法拆分成onCreateViewHoulder()方法和OnBindViewHoulder()方法,强制使用ViewHoulder类,使得代码编写更加规范化
  • RecyclerView控件复用Item对象的工作由自己实现
  • RecyclerView控件可以通过setItemAnimator()方法设置动画效果

3.3自定义控件

通常在Android开发过程中,都不直接使用View控件,而是使用它的子类,最简单的自定义控件就是创建一个继承View类或其他子类的类,并重写该类的构造方法,示例代码如下

class Customview extends View{
    public Customview(Context context)
    {
        super(context);
    }
    public Customview(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }
}

如果想要创建一个该类的对象,则需要使用到第一个构造函数,如果需要在布局文件中引用该自定义类,则需要使用到该类的第二个构造方法

我们可以在自定义控件中通过重写指定方法来添加额外的样式和功能,自定义控件常用的三个方法具体介绍如下

onMeasure()方法

该方法用于测量尺寸,在该方法中可以设置控件本身或者是其子控件的宽高

onMeasure(int widthMeasureSpec,int heightMeasureSpec);

第一个参数表示获取父容器指定该控件的宽度,第二个则是高度

这两个参数不仅包含属性值,还包括父容器的测量模式,测量模式分为三种

  • EXACTLY:当自定义控件的宽高值设置为具体值的时候使用,如100dp,match_parent
  • AT_MOST:当自定义控件的宽高值为wrap_content时使用
  • UNSPECIFIED:当父容器没有指定自定义控件的宽高值时使用

注意点:虽然这两个参数是父容器为该控件指定的宽高,但是该控件还需要通过设置setMeasureDimension(int,int)来设置宽高

onDraw()方法

该方法用于绘制图像

onDraw(Canvas canvas);

canans表示画布,经常与Paint类配合使用,通过Paint类可以在Canans中绘制图像

onLayout()方法

onLayout()方法,用于指定布局中子控件的位置,该方法通常在ViewGroup容器中重写

onLayout(boolean changed,int left,int top,int right,int bottom);

第一个参数表示自定义控件的大小和位置是否发生改变,剩下的四个控件代表与父容器的左边,顶部,右边,底部的距离

举例

使用自定义控件在界面中画一个图形

CircleView.java

package cn.itcast.myapplication;
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 = new Paint();
        paint.setColor(Color.RED);//设置颜色为红色
        canvas.drawCircle(centerX, centerY, r, paint);//调用画笔绘制
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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">

    <cn.itcast.myapplication.CircleView
        android:layout_width="100dp"
        android:layout_height="100dp" />

</RelativeLayout>

注意点:一个java源文件只能设置一个public类,这里的CircleView自定义控件类必须单独放在一个源文件中,如果不加public属性放在主函数类对应的java源文件中也是不行的,当在布局文件中创建一个子对象控件的时候是检测不到的

  • 7
    点赞
  • 84
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值