• 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);
        }
    
    }
  • 相关阅读:
    linux设备驱动程序第3版学习笔记(例程3--scull)未完1
    linux设备驱动程序第3版学习笔记(例程2--hellop.c)
    linux设备驱动程序第3版学习笔记(例程1)
    Intellij中request等对象无法解析
    OneNote学习笔记----语言概述
    四、归并排序(mergesort)
    三、堆排序(Heapsort),优先队列可以用于O(N log N)
    二、希尔排序(Shellsort)-- 缩减增量排序(diminishing increment sort)
    一、插入排序(insertion sort)
    hashmap冲突的解决方法以及原理分析:
  • 原文地址:https://www.cnblogs.com/lihuawei/p/16636931.html
Copyright © 2020-2023  润新知