09.常用控件

Android给我们提供了大量的UI控件,下面我们就挑选几种常用的控件,详细介绍一下它们的使用方法。首先新建一个UIWidgetTest项目。

1、TextView

TextView可以说是Android中最简单的一个控件了,我们在前面其实也已经和它打过了一些打交道。

它主要用于在界面上显示一段文本信息,比如我们在之前看到的Hello world!

下面我们就来看一看关于TextView的更多用法。

将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:id="@+id/tvMessage" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="这是一个文本控件" /> </LinearLayout>

外面的LinearLayout先忽略不看,在TextView中我们使用android:id给当前控件定义了一个唯一标识符。

然后使用android:layout_width指定了控件的宽度,使用android:layout_height指定了控件的高度。

Android中所有的控件都具有这两个属性,可选值有三种match_parent、fill_parent和wrap_content,其中match_parent和fill_parent的意义相同,现在官方更加推荐使用match_parent。

  • match_parent(填充父窗口)表示让当前控件的大小和父布局的大小一样,也就是由父布局来决定当前控件的大小。
  • wrap_content(内容包裹)表示让当前控件的大小能够刚好包含住里面的内容,也就是由控件内容决定当前控件的大小。

所以上面的代码就表示让TextView的宽度和父布局一样宽,也就是手机屏幕的宽度,让TextView的高度足够包含住里面的内容就行。当然除了使用上述值,你也可以对控件的宽和高指定一个固定的值,但是这样做有时会在不同手机屏幕的适配方面出现问题。接下来我们通过android:text指定了TextView中显示的文本内容,现在运行程序,效果如图所示。

 

虽然指定的文本内容是正常显示了,不过我们好像没看出来TextView的宽度是和屏幕一样宽的。其实这是由于TextView中的文字默认是居左上角对齐的,虽然TextView的宽度充满了整个屏幕,可是从效果上完全看不出来。现在我们修改TextView的文字对齐方式,如下所示:

<?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:id="@+id/tvMessage"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="这是一个文本控件" />
</LinearLayout>

我们使用android:gravity来指定文字的对齐方式(文字在控件中的对齐方式),可选值有top、bottom、left、right、center等,可以用“|”来同时指定多个值(中间不要有空格),这里我们指定的“center”,效果等同于“center_vertical|center_horizontal”,表示文字在垂直和水平方向都居中对齐。现在重新运行程序,效果如图所示。

 

这也说明了,TextView的宽度确实是和屏幕宽度一样的。

那么有的同学会问,指定的“center”,为什么垂直方向上没有居中呢?

因为我们指定的这个TextView控件的高度是“wrap_content”(内容包裹),这个控件的高度并没有占满整个屏幕,我们把高度修改为“match_parent,再看看效果。

 

另外,我们还可以对TextView中文字的大小和颜色进行修改,如下所示:

<?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:id="@+id/tvMessage"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="这是一个文本控件"
        android:textColor="#00ff00"
        android:textSize="24sp" />
</LinearLayout>

通过android:textSize属性可以指定文字的大小,通过android:textColor属性可以指定文字的颜色。重新运行程序,效果如图所示。

 其他属性介绍:

属性

说明

android:textStyle

设置字形。属性值:bold、italic,多个时用“|”隔开

android:singleLine

设置单行显示。属性值:true、false,显示不全时后面用“...”来表示。

android:maxLength

限制显示字符数。如设置为8,那么仅可以输入8个汉字/数字/英文字母。

android:lines

设置文本的行数,设置两行就显示两行,即使第二行没有数据。类似android:minLines属性。

android:maxLines

设置文本的最大显示行数,与width或者layout_width结合使用,超出部分自动换行,超出行数将不显示。

android:lineSpacingExtra

设置行间距。例如,"25dp"

android:lineSpacingMultiplier

设置行间距的倍数。例如,"1.2"

2、Button

Button是程序用于和用户进行交互的一个重要控件,相信你对这个控件已经是非常熟悉了,因为我们之前用了太多次Button。

它可配置的属性和TextView是差不多的,我们可以在activity_main.xml中这样加入Button:

<?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:id="@+id/tvMessage"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="这是一个文本控件"
        android:textColor="#00ff00"
        android:textSize="24sp" />

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="按钮" />
</LinearLayout>

加入Button之后的界面如图所示。

 

属性

说明

android:background

背景图,background即可以是颜色,也可以是图片。例如,"#ff0000" ,"@drawable/orange_pic"

android:drawableTop

android:drawableBottom

android:drawableLeft

android:drawableRight

上下左右的图片。例如,"@drawable/oranger_pic"

 

Button既然要交互,我们就要为Button添加点击事件:

(1)匿名内部类的方式

public class MainActivity extends AppCompatActivity {    
    private Button button;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() { //匿名类
            @Override
            public void onClick(View v) {
                // 在此处添加逻辑
            }
        });
    }
}

(2)实现接口的方式

public class MainActivity extends AppCompatActivity implements View.OnClickListener { //实现接口
    private Button button;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button = (Button) findViewById(R.id.button);
        button.setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.button:
            // 在此处添加逻辑
            break;
        }
    }
}

(3)在布局文件中显式指定按钮的onClick属性(不推荐使用)

<?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:id="@+id/tvMessage"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="这是一个文本控件"
        android:textColor="#00ff00"
        android:textSize="24sp" />

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="btnClick"
        android:text="按钮" />
</LinearLayout>

然后在MainActivity中添加btnClick()方法:

public void btnClick(View v) {
    // 在此处添加逻辑
}

这样按钮点击时会利用反射的方式调用对应Activity中的btnClick()方法。这里注意,自定义的btnClick()方法一定要有View类型的形式参数。

这三种写法都可以实现对按钮点击事件的监听,至于使用哪一种就全凭你喜好了。

3、EditText

EditText是程序用于和用户进行交互的另一个重要控件,它允许用户在控件里输入和编辑内容,并可以在程序中对这些内容进行处理。

EditText的应用场景应该算是非常普遍了,发短信、发微博、聊QQ等等,在进行这些操作时,你不得不使用到EditText。

那我们来看一看如何在界面上加入EditText吧,修改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:id="@+id/tvMessage"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="这是一个文本控件"
        android:textColor="#00ff00"
        android:textSize="24sp" />

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="按钮" />

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

Android控件的基本上用法都很相似,给控件定义一个id,再指定下控件的宽度和高度,然后再适当加入些控件特有的属性就差不多了。

所以使用XML来编写界面其实一点都不难,完全可以不用借助任何可视化工具来实现。

现在重新运行一下程序,EditText就已经在界面上显示出来了,并且我们是可以在里面输入内容的,如图所示。

细心的你平时应该会留意到,一些做得比较人性化的软件会在输入框里显示一些提示性的文字,然后一旦用户输入了任何内容,这些提示性的文字就会消失。

这种提示功能在Android里是非常容易实现的,我们甚至不需要做任何的逻辑控制,因为系统已经帮我们都处理好了。修改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:id="@+id/tvMessage"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="这是一个文本控件"
        android:textColor="#00ff00"
        android:textSize="24sp" />

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="按钮" />

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="输入文字信息" />
</LinearLayout>

使用android:hint属性来指定了一段提示性的文本,然后重新运行程序,如图所示。

可以看到,EditText中显示了一段提示性文本,然后当我们输入任何内容时,这段文本就会自动消失。

不过随着输入的内容不断增多,EditText会被不断地拉长。

这时由于EditText的高度指定的是wrap_content,因此它总能包含住里面的内容,但是当输入的内容过多时,界面就会变得非常难看。

我们可以使用android:maxLines属性来解决这个问题,修改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:id="@+id/tvMessage"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="这是一个文本控件"
        android:textColor="#00ff00"
        android:textSize="24sp" />

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="按钮" />

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="输入文字信息"
        android:maxLines="2" />
</LinearLayout>

这里通过android:maxLines指定了EditText的最大行数为两行,这样当输入的内容超过两行时,文本就会向上滚动,而EditText则不会再继续拉伸,如图所示。

 另外,EditText还可以通过给android:inputType属性设置"number""textPassword""datetime""date""time"等值,设置文本输入的格式。

我们还可以结合使用EditText与Button来完成一些功能,比如通过点击按钮来获取EditText中输入的内容。修改MainActivity中的代码,如下所示:

package com.sdbi.uiwidgettest;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements View.OnClickListener { // 实现接口
    private Button button;
private EditText editText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button = (Button) findViewById(R.id.button);
        editText = (EditText) findViewById(R.id.editText);
        button.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button:
                String inputText = editText.getText().toString();
                Toast.makeText(MainActivity.this, inputText, Toast.LENGTH_SHORT).show();
                break;
        }
    }
}

首先通过findViewById()方法得到EditText的实例,然后在按钮的点击事件里调用EditText的getText()方法获取到输入的内容,再调用toString()方法转换成字符串,最后仍然还是老方法,使用Toast将输入的内容显示出来。

重新运行程序,在EditText中输入一段内容,然后点击按钮,效果如图所示。

4、ImageView

ImageView是用于在界面上展示图片的一个控件,通过它可以让我们的程序界面变得更加丰富多彩。

使用这个控件需要提前准备好一些图片,由于目前mipmap文件夹下已经有一张ic_launcher.png图片了,那我们就先在界面上展示这张图吧,修改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:id="@+id/tvMessage"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="这是一个文本控件"
        android:textColor="#00ff00"
        android:textSize="24sp" />

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="按钮" />

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="输入文字信息"
        android:inputType=""
        android:maxLines="2" />

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/ic_launcher" />
</LinearLayout>

注意:资源文件的文件名只能包含小写a-z0-9,或者下划线。否则,会报错!

可以看到,这里使用android:src属性给ImageView指定了一张图片,并且由于图片的宽和高都是未知的,所以将ImageView的宽和高都设定为wrap_content,这样保证了不管图片的尺寸是多少都可以完整地展示出来。重新运行程序,效果如图所示。

我们还可以在程序中通过代码动态地更改ImageView中的图片。

这里我准备了另外一张图片,orange_pic.png(桔子),将它复制到res/drawable目录下,然后修改MainActivity的代码,如下所示:

package com.sdbi.uiwidgettest;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements View.OnClickListener { // 实现接口
    private Button button;
    private EditText editText;
    private ImageView imageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button = (Button) findViewById(R.id.button);
        editText = (EditText) findViewById(R.id.editText);
        imageView = (ImageView) findViewById(R.id.imageView);
        button.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button:
                imageView.setImageResource(R.drawable.orange_pic);
                break;
        }
    }
}

在按钮的点击事件里,通过调用ImageView的setImageResource()方法将显示的图片改成R.drawable.orange_pic,现在重新运行程序,然后点击一下按钮,就可以看到ImageView中显示的图片改变了,如图所示。

注意:在JAVA文件中使用资源ID,用R.drawable.

在XML文件中使用资源ID,用@drawable/。

5、ProgressBar

ProgressBar用于在界面上显示一个进度条,表示我们的程序正在加载一些数据。它的用法也非常简单,修改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:id="@+id/tvMessage"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="这是一个文本控件"
        android:textColor="#00ff00"
        android:textSize="24sp" />

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="按钮" />

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="输入文字信息"
        android:inputType=""
        android:maxLines="2" />

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/ic_launcher" />

    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

重新运行程序,会看到屏幕中有一个圆形进度条正在旋转,如图所示。

旋转的进度条表明我们的程序正在加载数据,如何才能让进度条在数据加载完成时消失呢?这里我们就需要用到Android控件的可见属性。

所有的Android控件都具有这个属性,可以通过android:visibility进行指定,另外我们还可以在逻辑代码中通过setVisibility()方法设置控件的可见性,通过getVisibility()方法获取控件的可见性。

android:visibility属性值

含义

setVisibility()方法参数值

visible

可见,表示控件是可见的,这个值是默认值,不指定android:visibility时,控件都是可见的。

View.VISIBLE

invisible

透明,表示控件不可见,但是它仍然占据着原来的位置和大小,可以理解成控件变成透明状态了。

View.INVISIBLE

gone

消失,表示控件不仅不可见,而且不再占用任何屏幕空间。

View.GONE

在逻辑代码中,我们还是通过findViewById(R.id.progressBar)方法获得progressBar对象,然后按钮对象增加控制代码,来控制控件的可见、透明、消失,代码如下:

if (progressBar.getVisibility() == View.VISIBLE) {
    progressBar.setVisibility(View.GONE);
} else {
    progressBar.setVisibility(View.VISIBLE);
}

如果我们要使用水平进度条,我们可以通过在布局文件中,给<ProgressBar>控件指定style属性来设置。style属性的值可以是:

  • ?android:attr/progressBarStyleHorizontal
  • ?android:progressBarStyleHorizontal
  • @style/Widget.AppCompat.ProgressBar.Horizontal
  • @style/Base.Widget.AppCompat.ProgressBar.Horizontal
  • @android:style/Widget.ProgressBar.Horizontal

这些都可以设置样式为水平进度条,效果会有一些差别。

(1)手动控制进度条

对于水平进度条,我们还可以在逻辑代码中控制进度条的增长和减少,我们先在布局文件中增加两个按钮,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:id="@+id/tvMessage"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="这是一个文本控件"
        android:textColor="#00ff00"
        android:textSize="24sp" />

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="按钮" />

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="输入文字信息"
        android:inputType=""
        android:maxLines="2" />

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/ic_launcher" />

    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/btnAdd"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="增加" />

    <Button
        android:id="@+id/btnReduce"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="减少" />
</LinearLayout>

然后修改MainActivity中的代码,如下所示:

package com.sdbi.uiwidgettest;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements View.OnClickListener { // 实现接口
    private TextView tvMessage;
    private Button button;
    private EditText editText;
    private ImageView imageView;
    private Button btnAdd, btnReduce;
    private ProgressBar progressBar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tvMessage = (TextView) findViewById(R.id.tvMessage);
        button = (Button) findViewById(R.id.button);
        editText = (EditText) findViewById(R.id.editText);
        imageView = (ImageView) findViewById(R.id.imageView);
        button.setOnClickListener(this);
        progressBar = (ProgressBar) findViewById(R.id.progressBar);
        btnAdd = (Button) findViewById(R.id.btnAdd);
        btnReduce = (Button) findViewById(R.id.btnReduce);
        btnAdd.setOnClickListener(this);
        btnReduce.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button:
                imageView.setImageResource(R.drawable.orange_pic);
                break;
            case R.id.btnAdd:
                progressBar.incrementProgressBy(10);
                progressBar.setSecondaryProgress(progressBar.getProgress() + 30);
                break;
            case R.id.btnReduce:
                progressBar.incrementProgressBy(-10);
                progressBar.setSecondaryProgress(progressBar.getProgress() + 30);
                break;
        }
        tvMessage.setText("第一进度:" + progressBar.getProgress() * 100.0 / progressBar.getMax() + "%;第二进度:" + progressBar.getSecondaryProgress() * 100.0 / progressBar.getMax() + "%");
    }
}

我们看到上述代码中用到进度条的一些方法,我们在这里说明一下:

  • incrementProgressBy():增加第一进度的进度值,参数可以是负数,表示减少;
  • setProgress():设置第一进度的进度值;
  • getProgress():获取第一进度的进度值;
  • incrementSecondaryProgressBy():增加第二进度的进度值,参数可以是负数,表示减少;
  • setSecondaryProgress():设置第二进度的进度值;
  • getSecondaryProgress():获取第二进度的进度值。

(2)自动控制进度条

首先,建立子线程,在子线程中让进度条每次增加10%,超过100%后重新归0。

子线程中操作主线程UI,使用runOnUiThread在UI主线程空闲的时候设置progressBar进度条tvMessage文本控件,Thread.sleep延时200ms,别忘了使用线程的start()方法启动线程。

package com.sdbi.uiwidgettest;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements View.OnClickListener { // 实现接口
    private TextView tvMessage;
    private Button button;
    private EditText editText;
    private ImageView imageView;
    private Button btnAdd, btnReduce;
    private ProgressBar progressBar;
    private int iProgress = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tvMessage = (TextView) findViewById(R.id.tvMessage);
        button = (Button) findViewById(R.id.button);
        editText = (EditText) findViewById(R.id.editText);
        imageView = (ImageView) findViewById(R.id.imageView);
        button.setOnClickListener(this);
        progressBar = (ProgressBar) findViewById(R.id.progressBar);
        btnAdd = (Button) findViewById(R.id.btnAdd);
        btnReduce = (Button) findViewById(R.id.btnReduce);
        btnAdd.setOnClickListener(this);
        btnReduce.setOnClickListener(this);

        new Thread(new Runnable() {
            @Override
            public void run() {
                while (iProgress <= 100) {
                    iProgress += 10;
                    if (iProgress > 100) {
                        iProgress = 0;
                    }
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            progressBar.setProgress(iProgress);
                            tvMessage.setText("进度:" + iProgress + "%");
                        }
                    });
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button:
                imageView.setImageResource(R.drawable.orange_pic);
                break;
            case R.id.btnAdd:
                progressBar.incrementProgressBy(10);
                progressBar.setSecondaryProgress(progressBar.getProgress() + 30);
                break;
            case R.id.btnReduce:
                progressBar.incrementProgressBy(-10);
                progressBar.setSecondaryProgress(progressBar.getProgress() + 30);
                break;
        }
        tvMessage.setText("第一进度:" + progressBar.getProgress() * 100.0 / progressBar.getMax() + "%;第二进度:" + progressBar.getSecondaryProgress() * 100.0 / progressBar.getMax() + "%");
    }
}

另外,我们在使用水平进度条,但是又不确定进度时,我们就可以将属性android:indeterminate设置为true,这时的水平进度条就可以不断的循环往复。

6、AlertDialog

AlertDialog可以在当前的界面弹出一个对话框,这个对话框是置顶于所有界面元素之上的,能够屏蔽掉其他控件的交互能力,因此一般AlertDialog都是用于提示一些非常重要的内容或者警告信息。比如为了防止用户误删重要内容,在删除前弹出一个确认对话框。

下面我们先来了解一下AlertDialog的大体创建顺序。与TextView、Button这些控件不同,AlertDialog并不是初始化(findViewById)之后就直接调用各种方法了。我们试想一下AlertDialog的使用场景,它并不像TextView和Button控件似的一般都是固定在界面上,而是在某个时机才会触发出来(比如用户点击了某个按钮或者断网了)。所以AlertDialog并不需要到布局文件中创建,而是在逻辑代码中通过构造器(AlertDialog.Builder)来构造,然后为其设置标题、图标和按钮等内容的。步骤如下:

(1)创建构造器AlertDialog.Builder的对象;

(2)通过构造器的对象调用setTitle、setMessage等方法设置对话框的标题、信息和图标等内容;

(3)根据需要,设置正面按钮、负面按钮和中立按钮;

(4)调用create()方法创建AlertDialog的对象;

(5)AlertDialog的对象调用show()方法,让对话框在界面上显示。

注意:AlertDialog.Builder自己也有一个show()方法,可以显示对话框,所以上面的第(4)、(5)步可以简化为一步。

修改MainActivity中的代码,如下所示:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    ……
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.button:
            AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);
            dialog.setTitle("提示");
            dialog.setMessage("确定退出吗?");
            dialog.setCancelable(false);
            //给对话框添加"确定"按钮
            dialog.setPositiveButton("确定", new DialogInterface. OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    // 确定按钮逻辑代码
                }
            });
            //对话框添加"取消"按钮
            dialog.setNegativeButton("取消", new DialogInterface. OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    // 取消按钮逻辑代码
                }
            });
            dialog.show(); // 显示对话框
            break;
        }
    }
}

首先通过AlertDialog.Builder创建出一个AlertDialog的实例,然后可以为这个对话框设置标题、内容、可否取消等属性,接下来调用setPositiveButton()方法为对话框设置确定按钮的点击事件,调用setNegativeButton()方法设置取消按钮的点击事件,最后调用show()方法将对话框显示出来。重新运行程序,点击按钮后,效果如图所示。

(1)如果要三个按钮呢?

我们来试一下,并且还要通过代码改变了对话框的图标。

@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.button:
            AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);
            dialog.setIcon(android.R.drawable.btn_star); // 系统自带图标
            dialog.setTitle("Android系统欢迎度调查");
            dialog.setMessage("你喜欢使用Android系统吗??");
            dialog.setCancelable(false);
            // 对话框添加"喜欢"按钮
            dialog.setPositiveButton("喜欢", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                }
            });
            // 对话框添加"不喜欢"按钮
            dialog.setNegativeButton("不喜欢", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                }
            });
            // 给对话框添加普通按钮
            dialog.setNeutralButton("一般", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                }
            });
            dialog.show();
            break;
    }
}

(2)类似ListView的AlertDialog

用setItems(CharSequence[] items, final OnClickListener listener)方法来实现类似ListView的AlertDialog。

第一个参数是要显示的数据的数组,第二个参数是点击某个item的触发事件。

@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.button:
            final String[] arrayFruit = new String[]{"苹果","橘子","草莓","香蕉"};
            AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);
            dialog.setIcon(android.R.drawable.btn_star);
            dialog.setTitle("你喜欢吃哪种水果?");
            dialog.setCancelable(false);
            dialog.setItems(arrayFruit, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    Toast.makeText(MainActivity.this, arrayFruit[which], Toast.LENGTH_SHORT).show();
                }
            });
            // 对话框添加"取消"按钮
            dialog.setNegativeButton("取消", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                }
            });
            dialog.show();
            break;
        default:
            break;
    }
}

(3)类似RadioButton的AlertDialog

用setSingleChoiceItems(CharSequence[] items, int checkedItem, final OnClickListener listener)方法来实现类似RadioButton的AlertDialog。

第一个参数是要显示的数据的数组,第二个参数是初始值(初始被选中的item),第三个参数是点击某个item的触发事件,在这个例子里面我们设了一个selectedFruitIndex用来记住选中的item的index。

private int selectedFruitIndex = 0;
@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.button:
            final String[] arrayFruit = new String[] { "苹果", "橘子", "草莓", "香蕉" };
            AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);
            dialog.setIcon(android.R.drawable.btn_star);
            dialog.setTitle("你喜欢吃哪种水果?");
            dialog.setCancelable(false);
            dialog.setSingleChoiceItems(arrayFruit, selectedFruitIndex, new DialogInterface.OnClickListener(){ @Override public void onClick(DialogInterface dialog, int which) { selectedFruitIndex = which; } }); // 对话框添加"确认"按钮 dialog.setPositiveButton("确认", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(MainActivity.this, arrayFruit[selectedFruitIndex], Toast.LENGTH_SHORT).show(); } }); // 对话框添加"取消"按钮 dialog.setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }); dialog.show(); break; default: break; } }

 

(4)类似CheckBox的AlertDialog

用setMultiChoiceItems(CharSequence[] items, boolean[] checkedItems, final OnMultiChoiceClickListener listener)方法来实现类似CheckBox的AlertDialog。

第一个参数是要显示的数据的数组,第二个参数是选中状态的数组,第三个参数是点击某个item的触发事件。

@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.button:
            final String[] arrayFruit = new String[] { "苹果", "橘子", "草莓", "香蕉" };
   final boolean[] arrayFruitSelected = new boolean[] { true, true, false, false };
            AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);
            dialog.setIcon(android.R.drawable.btn_star);
            dialog.setTitle("你喜欢吃哪种水果?");
            dialog.setCancelable(false);
            dialog.setMultiChoiceItems(arrayFruit, arrayFruitSelected, new DialogInterface.OnMultiChoiceClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which, boolean isChecked) {
                    arrayFruitSelected[which] = isChecked;
                }
            });
            // 对话框添加"确认"按钮
            dialog.setPositiveButton("确认", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    StringBuilder stringBuilder = new StringBuilder();
                    for (int i = 0; i < arrayFruitSelected.length; i++) {
                        if (arrayFruitSelected[i] == true) {
                            stringBuilder.append(arrayFruit[i] + "、");
                        }
                    }
                    Toast.makeText(MainActivity.this, stringBuilder.toString(), Toast.LENGTH_SHORT).show();
                }
            });
            // 对话框添加"取消"按钮
            dialog.setNegativeButton("取消", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                }
            });
            dialog.show();
            break;
    }
}

 

(5)自定义View的AlertDialog

有时候我们不能满足系统自带的AlertDialog风格,就比如说我们要实现一个Login画面,有用户名和密码,这时我们就要用到自定义View的AlertDialog。

先创建登录画面的布局文件login.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:gravity="center"
        android:orientation="horizontal">

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="right"
            android:text="用户名:" />

        <EditText
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="3"
            android:hint="请输入用户名"
            android:singleLine="true" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="horizontal">

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="right"
            android:text="密码:" />

        <EditText
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="3"
            android:hint="请输入密码"
            android:inputType="textPassword" />
    </LinearLayout>
</LinearLayout>

然后在Activity里面把login.xml的布局文件添加到AlertDialog上

@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.button:
            // 取得自定义View
            LayoutInflater layoutInflater = LayoutInflater.from(this);
            View myLoginView = layoutInflater.inflate(R.layout.login, null);
            AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);
            dialog.setIcon(android.R.drawable.btn_star);
            dialog.setTitle("用户登录");
            dialog.setCancelable(false);
            dialog.setView(myLoginView);
            // 对话框添加"登录"按钮
            dialog.setPositiveButton("登录", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                }
            });
            // 对话框添加"取消"按钮
            dialog.setNegativeButton("取消", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                }
            });
            dialog.show();
            break;
    }
}

7、ProgressDialog

ProgressDialog和AlertDialog有点类似,都可以在界面上弹出一个对话框,都能够屏蔽掉其他控件的交互能力。

不同的是,ProgressDialog会在对话框中显示一个进度条,一般是用于表示当前操作比较耗时,让用户耐心地等待。

ProgressDialog的创建方式有两种,一种是new ProgressDialog(),一种是调用ProgressDialog的静态方法ProgressDialog.show()。

(1)new ProgressDialog()方式

它的用法和AlertDialog也比较相似,修改MainActivity中的代码,如下所示:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    ……
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.button:
            ProgressDialog progressDialog = new ProgressDialog(MainActivity.this);
            progressDialog.setTitle("进度对话框");
            progressDialog.setMessage("正在加载...");
            progressDialog.setCancelable(true);
            progressDialog.show();
            break;
        }
    }
}

可以看到,这里也是先构建出一个ProgressDialog对象,然后同样可以设置标题、内容、可否取消等属性,最后也是通过调用show()方法将ProgressDialog显示出来。重新运行程序,点击按钮后,效果如图所示。

注意:如果在setCancelable()中传入了false,表示ProgressDialog是不能通过Back键取消掉的,这时你就一定要在代码中做好控制,当数据加载完成后必须要调用ProgressDialog的dismiss()方法来关闭对话框,否则ProgressDialog将会一直存在。

ProgressDialog的样式也有两种,一种是圆形不明确状态,一种是水平进度条状态,类似于ProgressBar。

我们来看一下水平进度条的用法,水平进度条也分为两种进度。

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    ……
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button:
                final ProgressDialog progressDialog=new ProgressDialog(MainActivity.this);
                progressDialog.setTitle("进度对话框");
                progressDialog.setMessage("正在加载...");
                progressDialog.setCancelable(false);
                // 设置水平进度条
                progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
                progressDialog.setMax(100);
                progressDialog.show();
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        int i = 0;
                        while (i < 100) {
                            try {
                                Thread.sleep(200);
                                // 更新进度条的进度,可以在子线程中更新进度条进度
                                progressDialog.incrementProgressBy(1);
                                progressDialog.incrementSecondaryProgressBy(progressDialog.getProgress() + 5);//二级进度条更新方式
                                i++;
                            } catch (Exception e) {
                            }
                        }
                        if (i == 100) { // 进度完成
                            // 在进度条走完时删除Dialog
                            progressDialog.dismiss();
                        }
                    }
                }).start();
                break;
        }
    }
}

(2)调用ProgressDialog的静态方法ProgressDialog.show()方式

@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.button:
            ProgressDialog progressDialog = ProgressDialog.show(MainActivity.this, "进度对话框", "正在加载...");
            break;
    }
}

ProgressDialog.show()方法有多种重载形式,通过查看你会发现,其实show()方法也是把new ProgressDialog()和其他的一些set属性方法做了封装。

 8、CheckBox复选框组件

CheckBox复选框,可以同时选中多个值。

CheckBox继承自CompoundButton(Compound,复合),CompoundButton继承自Button。

CompoundButton提供了两种状态:已选中、未选中。

CompoundButton是抽象类,因此在实际开发中不能直接使用,要使用它的几个子类,主要有CheckBox、Switch、RadioButton等。

CompoundButton相比Button多了一个监听事件接口CompoundButton.OnCheckedChangeListener。

当复合按钮的检查状态发生变化时调用。需要实现的方法是:

@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {

}

第一个参数compoundButton是控件对象,第二个参数b是复合按钮的新状态。

CompoundButton提供了下面的方法对复合按钮进行属性的使用:

  • setChecked(boolean checked):设置按钮的状态
  • isChecked():获取按钮的状态

我们先在布局文件中添加3个CheckBox。

<?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:orientation="horizontal">
        <CheckBox
            android:id="@+id/cbApple"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="苹果" />

        <CheckBox
            android:id="@+id/cbOrange"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="橘子" />

        <CheckBox
            android:id="@+id/cbBanana"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="香蕉" />
    </LinearLayout>
</LinearLayout>

给这3个CheckBox绑定事件。

import androidx.appcompat.app.AppCompatActivity;

import android.app.ProgressDialog;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity implements View.OnClickListener, CompoundButton.OnCheckedChangeListener { // 实现接口
    private TextView tvMessage;
    private Button button;
    private EditText editText;
    private ImageView imageView;
    private Button btnAdd, btnReduce;
    private ProgressBar progressBar;
    private CheckBox cbApple, cbOrange, cbBanana;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tvMessage = (TextView) findViewById(R.id.tvMessage);
        ......

        cbApple = (CheckBox) findViewById(R.id.cbApple);
        cbOrange = (CheckBox) findViewById(R.id.cbOrange);
        cbBanana = (CheckBox) findViewById(R.id.cbBanana);
        cbApple.setOnCheckedChangeListener(this);
        cbOrange.setOnCheckedChangeListener(this);
        cbBanana.setOnCheckedChangeListener(this);
    }

    @Override
    public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
        String strMsg = "";
        if (b) {
            strMsg = "复选框" + compoundButton.getText() + "[" + compoundButton.getId() + "]被选中";
        } else {
            strMsg = "复选框" + compoundButton.getText() + "[" + compoundButton.getId() + "]被取消";
        }
        tvMessage.setText(strMsg);
    }

    @Override
    public void onClick(View v) {
        ......
    }
}

9、Switch开关组件

Switch开关控件,也是经常使用的一个比较重要的控件,也是可以有选中和未选中的两种状态。

Switch也是要绑定CompoundButton.OnCheckedChangeListener监听器。

在布局文件中添加Switch开关控件。

<?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">

    ......

    <Switch
        android:id="@+id/swConnect"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="接通" />
</LinearLayout>

绑定事件。

import androidx.appcompat.app.AppCompatActivity;

import android.app.ProgressDialog;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.Switch;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity implements View.OnClickListener, CompoundButton.OnCheckedChangeListener { // 实现接口
    private TextView tvMessage;
    private Button button;
    private EditText editText;
    private ImageView imageView;
    private Button btnAdd, btnReduce;
    private ProgressBar progressBar;
    private CheckBox cbApple, cbOrange, cbBanana;
    private Switch swConnect;

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

        cbApple = (CheckBox) findViewById(R.id.cbApple);
        cbOrange = (CheckBox) findViewById(R.id.cbOrange);
        cbBanana = (CheckBox) findViewById(R.id.cbBanana);
        cbApple.setOnCheckedChangeListener(this);
        cbOrange.setOnCheckedChangeListener(this);
        cbBanana.setOnCheckedChangeListener(this);
        swConnect = (Switch) findViewById(R.id.swConnect);
        swConnect.setOnCheckedChangeListener(this);
    }

    @Override
    public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
        String strMsg = "";
        if (b) {
            strMsg = "复选框" + compoundButton.getText() + "[" + compoundButton.getId() + "]被选中";
        } else {
            strMsg = "复选框" + compoundButton.getText() + "[" + compoundButton.getId() + "]被取消";
        }
        tvMessage.setText(strMsg);
    }

    @Override
    public void onClick(View v) {
        ......
    }
}

10、RadioButton圆形单选框组件

RadioButton是单选按钮,允许用户在一个组中选择一个选项。同一组中的单选按钮有互斥效果。

RadioButton的特点:

  • RadioButton是圆形单选框;
  • RadioGroup是个可以容纳多个RadioButton的容器;
  • 在RadioGroup中的RadioButton控件可以有多个,但同时有且仅有一个可以被选中。

使用RadioButton必须和单选框RadioGroup一起使用,在RadioGroup中放置RadioButton,也是通过setOnCheckedChangeListener( )来响应按钮的事件。

<?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/rgSex"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <RadioButton
            android:id="@+id/rbMale"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="男" />

        <RadioButton
            android:id="@+id/rbFeMale"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="女" />

        <RadioButton
            android:id="@+id/rbPrivary"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="保密" />
    </RadioGroup>
</LinearLayout>

可以通过给每个RadioButton绑定CompoundButton.OnCheckedChangeListener监听器来监听选项动作。

package com.sdbi.uiwidgettest;

import androidx.appcompat.app.AppCompatActivity;

import android.app.ProgressDialog;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Switch;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity implements View.OnClickListener, CompoundButton.OnCheckedChangeListener { // 实现接口
    ......
    private RadioGroup rgSex;
    private RadioButton rbMale, rbFemale, rbPrivary;

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

        rgSex = (RadioGroup) findViewById(R.id.rgSex);
        rbMale = (RadioButton) findViewById(R.id.rbMale);
        rbFemale = (RadioButton) findViewById(R.id.rbFeMale);
        rbPrivary = (RadioButton) findViewById(R.id.rbPrivary);
        rbMale.setOnCheckedChangeListener(this);
        rbFemale.setOnCheckedChangeListener(this);
        rbFemale.setOnCheckedChangeListener(this);
    }

    @Override
    public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
        String strMsg = "";
        if (b) {
            strMsg = "复选框" + compoundButton.getText() + "[" + compoundButton.getId() + "]被选中";
        } else {
            strMsg = "复选框" + compoundButton.getText() + "[" + compoundButton.getId() + "]被取消";
        }
        tvMessage.setText(strMsg);
    }

    @Override
    public void onClick(View v) {
        ......
    }
}

也可以通过给RadioGroup绑定RadioGroup.OnCheckedChangeListener监听器来监听选项动作。

import androidx.appcompat.app.AppCompatActivity;

import android.app.ProgressDialog;
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.EditText;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements View.OnClickListener, CompoundButton.OnCheckedChangeListener { // 实现接口
    ......
    private RadioGroup rgSex;
    private RadioButton rbMale, rbFemale, rbPrivary;

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

        rgSex = (RadioGroup) findViewById(R.id.rgSex);
        rbMale = (RadioButton) findViewById(R.id.rbMale);
        rbFemale = (RadioButton) findViewById(R.id.rbFeMale);
        rbPrivary = (RadioButton) findViewById(R.id.rbPrivary);
        rgSex.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup radioGroup, int i) {
                // 选中状态改变时被触发
                switch (i) {
                    case R.id.rbMale:
                        // 当用户选择男性时
                        Toast.makeText(MainActivity.this, "当前用户选择" + rbMale.getText().toString(), Toast.LENGTH_SHORT).show();
                        break;
                    case R.id.rbFeMale:
                        // 当用户选择女性时
                        Toast.makeText(MainActivity.this, "当前用户选择" + rbFemale.getText().toString(), Toast.LENGTH_SHORT).show();
                        break;
                    case R.id.rbPrivary:
                        // 当用户选择男性时
                        Toast.makeText(MainActivity.this, "当前用户选择" + rbPrivary.getText().toString(), Toast.LENGTH_SHORT).show();
                        break;
                }
            }
        });
    }

    @Override
    public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
        String strMsg = "";
        if (b) {
            strMsg = "复选框" + compoundButton.getText() + "[" + compoundButton.getId() + "]被选中";
        } else {
            strMsg = "复选框" + compoundButton.getText() + "[" + compoundButton.getId() + "]被取消";
        }
        tvMessage.setText(strMsg);
    }

    @Override
    public void onClick(View v) {
        ......
    }
}

【扩展提高】

如果有一组单选按钮,初始化时任何选项未选中,点击选项可以选中一个,也可以将选中的取消,这样该怎么设置?

activity_mail.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"
    android:orientation="vertical"
    tools:context=".activity.MainActivity">

    <RadioGroup
        android:id="@+id/rgFruit"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <RadioButton
            android:id="@+id/rbApple"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="苹果" />

        <RadioButton
            android:id="@+id/rbBanana"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="香蕉" />
    </RadioGroup>

</LinearLayout>

MainActivity.java

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.RadioButton;
import android.widget.RadioGroup;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private static final String TAG = "MainActivity";
    private RadioGroup rgFruit;
    private RadioButton rbApple, rbBanana;
    private boolean isApple, isBanana;

    @Override
    public void onClick(View view) { // View 控件
        switch (view.getId()) {
            case R.id.rbApple:
                rgFruit.clearCheck(); // 清除RadioGroup的选中状态
                // 根据选中标识变量来设置选中状态
                if (isApple == false) {
                    rbApple.setChecked(true);
                    isApple = true;
                    rbBanana.setChecked(false);
                    isBanana = false;
                } else {
                    rbApple.setChecked(false);
                    isApple = false;
                }
                break;

            case R.id.rbBanana:
                rgFruit.clearCheck(); // 清除RadioGroup的选中状态
                // 根据选中标识变量来设置选中状态
                if (isBanana == false) {
                    rbBanana.setChecked(true);
                    isBanana = true;
                    rbApple.setChecked(false);
                    isApple = false;
                } else {
                    rbBanana.setChecked(false);
                    isBanana = false;
                }
                break;
        }
    }


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

        rgFruit = findViewById(R.id.rgFruit);
        rbApple = findViewById(R.id.rbApple);
        rbBanana = findViewById(R.id.rbBanana);
        rbApple.setOnClickListener(this);
        rbBanana.setOnClickListener(this);
    }

}

 

posted @ 2022-09-08 21:30  熊猫Panda先生  阅读(380)  评论(0编辑  收藏  举报