Android第三章 (UI)

3.1 如何编写程序界面
Android提供了一系列UI,这些UI可以为我们的界面提供布局和控件,使我们的界面变得美观、合理
3.2 常用控件使用方法
3.2.1 TextView
用途:主要用于在界面上显示一段文本信息

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <TextView
        android:id="@+id/text_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="This is TextView"
        />
</LinearLayout>

在TextView中,match_parent和fill_parent表示让当前控件的大小和父布局的大小一样;wrap_content表示让当前控件的大小能够刚好包含住里面的内容

TextView里面还有一些属性可以改变文字的位置、颜色、大小,如下

	android:gravity="center"
    android:textSize="24sp"
    android:textColor="#00ff00"

android:gravity表示指定文字的对齐方式
android:textSize表示指定文字的大小
android:textColor表示指定文字的颜色
3.2.2 Button
用途:表示在界面上显示一个按钮

 <Button
        android:id="@+id/button_1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button 1"
        android:textAllCaps="false"//该属性表示禁止控件名称显示时自动转为大写,表示你的按钮名称大小写变化,true为默认,即大写情况;false则把按钮里的文字改为小写
        />

在主活动中,有两种注册监听器的方法
法一(匿名类方式注册):

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

法二(实现接口的方式注册):
1、继承View.OnClickListener接口 2、重写onClick(View v) 方法

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

3.1.3 EditText
用途:允许用户在控件里输入和编辑内容,并可以在程序中对这些内容进行处理

 <EditText
        android:id="@+id/edit_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Type something here"
        android:maxLines="2"
        />

android:hint 表示在输入框内显示一些提示性的文字,当用户输入任何内容时,这些提示性文字就会消失
android:maxLines表示指定Edit的最大行数为两行

我们还可以结合使用EditText和Button来完成一些功能,比如通过点击按钮来获取EditText中输入的内容

private EditText editText;
@Override
protected void onCreate(Bundle savedInstanceState) {
    
    
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Button button = (Button)findViewById(R.id.button_1);
    editText = (EditText)findViewById(R.id.edit_text); 
    button.setOnClickListener(this);
}
@Override
public void onClick(View v) {
    
    
    switch (v.getId()){
    
    
        case R.id.button_1:
            String inputText = editText.getText().toString();
            Toast.makeText(MainActivity.this,inputText,Toast.LENGTH_SHORT).show();
            break;
            default:
                break;
    }
}

3.2.4 ImageView
用途:适用于在界面上展示图片的一个控件,他可以使得程序界面变得更加丰富多彩
做法:
在这里插入图片描述

<ImageView
        android:id="@+id/image_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/img_1"/>

我们还可以通过点击按钮来更换图片

   private ImageView imageView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button = (Button)findViewById(R.id.button_1);
        imageView = (ImageView) findViewById(R.id.image_view);
        button.setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
    
    
        switch (v.getId()){
    
    
            case R.id.button_1:
               imageView.setImageResource(R.drawable.img_2);//该办法表示动态更改图片
                break;
                default:
                    break;
        }
    }

3.2.5 ProgressBar
用途:用于在界面上显示一个进度条,表示我们的程序正在加载一些数据,代码如下:

	<ProgressBar
        android:id="@+id/progress_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />

当数据加载完成时,如何让进度条消失?
1、这里提供一个新的知识点:Android控件的可见属性,可以通过android:visibility进行指定,其中选定的值有三种:visible、invisible、gone;①visible表示控件是可见的;②invisible表示控件不可见,但是仍然占据着原来的位置的大小;③gone表示控件不仅不可见,而且不再占用任何屏幕空间
2、通过代码来设置控件的可见性,使用的是setVisibility()方法,可以传入View.VISIBLE、View.INVISIBLE、View.GONE这三种值
实现代码:

public class MainActivity<onClick> extends AppCompatActivity implements View.OnClickListener{
    
    
    private ProgressBar progressBar;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button = (Button)findViewById(R.id.button_1);
        progressBar = (ProgressBar)findViewById(R.id.progress_bar);
        button.setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
    
    
        switch (v.getId()){
    
    
            case R.id.button_1:
                if(progressBar.getVisibility() == View.GONE){
    
    //调用该方法判断ProgressBar是否可见,若可见则隐藏掉;反之就将他显示出来
                    progressBar.setVisibility(View.VISIBLE);
                }else{
    
    
                    progressBar.setVisibility(View.GONE);
                }
                break;
                default:
                    break;
        }
    }
}

我们还可以给ProgressBar控件指定不同的样式

 <ProgressBar
        android:id="@+id/progress_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        style="?android:attr/progressBarStyleHorizontal"//提供圆形进度条
        android:max="100"//给进度条设置一个最大值
        />

3.2.6 AlertDialog
用途:可以在当前得界面弹出一个对话框,该对话框置顶于所有界面元素之上的,能够屏蔽掉其他控件得交互能力,因此AlertDialog一般都是用于提示一些非常重要的内容或着警告信息,示例代码如下:

    @Override
    public void onClick(View v) {
    
    
        switch (v.getId()){
    
    
            case R.id.button_1:
            //1、首先创建一个实例
                AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);
            //2、设置一些内容    
                dialog.setTitle("This is a dialog");
                dialog.setMessage("Something important.");
            //3、可否用Back键关闭对话框,true表示可以;false表示不可以
                dialog.setCancelable(false);
            //4、调用setPositiveButton()方法为对话框设置确定按钮的点击事件
                dialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
    
    
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
    
    
                    	//在此处添加逻辑
                    }
                });
            //5、调用setNegativeButton()方法为对话框设置取消按钮的点击事件
                dialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
    
    
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
    
    
                    	//在此处添加逻辑
                    }
                });
            //6、调用show()方法显示  
                dialog.show();
                break;
                default:
                    break;
        }
    }

3.2.7 ProgressDialog
用途:跟ProgressDialog类似,弹出一个对话框,能够屏蔽掉其他控件的交互能力。不同的是,ProgressDialog会在对话框中显示一个进度条,一般用于表示当前操作比较耗时,让用户耐心地等待

3.3 详解4种基本布局
布局:一种可用于放置很多控件的容器,可以按照一定的规律调整内部控件的位置
3.3.1 线性布局(LinearLayout)
定义:该布局会将它所包含的控件在线性方向上依次排列,其代码都是在LinearLayout元素下实现的
1、其中,布局文件中的android:orientation属性指定了控件的排列方向,
若是vertical,则控件按垂直方向排列;若为horizontal,则控件按水平方向排列。
注意:如果声明为vertical,则内部控件的高度不能指定为match_parent;
如果声明为horizontal,则内部控件的宽度不能指定为match_parent;
2、android:gravity用于指定文字在控件中的对齐方式;而android:layout_gravity用于指定控件在布局中的对齐方式。
3、若LinearLayout的排列方向为vertical时,只有水平方向上的对齐方式才会改变;若为horizontal时,只有垂直方向上的对齐方式才会改变
4、android:layout_weight允许我们使用比例的方式来制定控件的大小,注意此时控件的排列方向为horizontal
5、dp是Android中用于指定控件大小、间距等属性的单位
6、我们发现此时layout_width都是用“0dp”表示,这时我们的宽度是由layout_weight决定的。EditText和Button的layout_weight的值都为1,表明这两个控件在水平方向上平分宽度
在这里插入图片描述

此外,Button的代码还可以这么写:
在这里插入图片描述
这表示Button控件的宽度仍为原来大小,而水平方向上剩余的空间会被EditText所填满
3.3.2 相对布局(RelativeLayout)
定义:他可以通过相对定位的方式让控件出现在布局的任何位置,其控件都是在RelativeLayout布局下实现的
相对布局具有两种相对性:
1、相对于父布局定位,其中几个常见的属性:
android:layout_alignParentRight:表示相对于父布局处在右边
android:layout_alignParentLeft:表示相对于父布局处在左边
android:layout_alignParentTop:表示相对于父布局处在上边
android:layout_alignParentButton:表示相对于父布局处在下边
2、相对于控件定位,其中几种常见的属性:
android:layout_centerInParent:表示定义定位于中间位置的控件(我们以控件Button 3为基准)
android:layout_above="@id/button_3":表示定义定位相对于中间控件顶部的位置
android:layout_below="@id/button_3":表示定义定位相对于中间控件底部的位置
android:layout_toLeftOf="@id/button_3":表示定义定位相对于中间控件左边的位置
android:layout_toRightOf="@id/button_3":表示定义定位相对于中间控件右边的位置
3、补充:
android:layout_alignLeft:表示让一个控件的左边缘和另一个控件的左边缘对齐
android:layout_alignRight:表示让一个控件的右边缘和另一个控件的右边缘对齐
android:layout_alignLeft:表示让一个控件的顶部边缘和另一个控件的顶部边缘对齐
android:layout_alignLeft:表示让一个控件的底部边缘和另一个控件的底部边缘对齐
3.3.3 帧布局(FrameLayout)
定义:此布局没有方便的定位方式,所有的控件都会默认摆放在布局的左上角,其代码都是在FrameLayout布局下实现的
当然我们也可以通过android:layout_gravity对控件的对齐方式进行调整,以达到避免所有控件摆放在左上角的情况。向对于前两种布局,这种情况的布局使用较少

3.3.4 百分比布局
百分比布局只为FrameLayoutRelativeLayout中进行了扩展,其代码分别是在PercentFrameLayoutPrecentRelativeLayout布局下实现的,这两个布局分别继承了前者的所有属性和方法
1、首先我们要在build.gradle文件中添加百分比布局库的依赖在这里插入图片描述
2、在布局文件中,在控件声明完后的结尾处定义一个app的命名空间,才能使百分比布局的自定义属性在这里插入图片描述
3.4 创建自定义控件
在这里插入图片描述
我们可以看到提到的控件都是直接或间接继承自View的,提到的所有的布局都是直接或间接继承自ViewGroup的。View是Android中最基本的一种UI组件,他可以在屏幕上绘制一块矩形区域,并能够响应这块区域的各种事件。ViewGroup是一种特殊的View,他可以包含很多子View和子ViewGroup,是一个用于放置控件和布局的容器
3.4.1 引入自定义布局
我们以创建下面活动界面为例:
在这里插入图片描述

作用:我们可以只创建一个通用格式的布局,然后在其他的活动中调用此布局文件,这样就避免频繁的重复的操作控件
1、在layout包下创建一个布局文件title.xml,然后添加控件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:id="@+id/title_back"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        android:text="Back"
        android:textColor="#00ff66" />
    <TextView
        android:id="@+id/title_text"
        android:layout_width="0dp"
        android:layout_height="58dp"
        android:layout_weight="1"
        android:gravity="center"
        android:text="Title Text"
        android:textColor="#00ff66"
        android:textSize="24sp" />
    <Button
        android:id="@+id/title_edit"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"//可以指定控件在上下左右方向上偏移的距离
        android:text="Edit"
        android:textColor="#00ff66" />
</LinearLayout>

2、在layout包下的主布局文件(或是你想调用该布局的布局文件),做如下操作:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    
    <include layout="@layout/title"/>
</LinearLayout>

在include中,引号里的格式:“@包名/布局文件名”
3、在主活动中,将系统自带的标题栏隐藏掉

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null){
    
    
            actionBar.hide();
        }
    }

3.4.2 创建自定义控件
作用:以上述的自定义布局中的Back键为例,Back键的目的就是销毁该活动,我们可以通过自定义Back的控件,使得每一个自定义的布局中Back键执行的情况都是相同,这样就避免在每一个活动中都需要重新注册一遍返回按钮的点击事件。
1、新建一个类,继承LinearLayout,让他成为我们自定义的标题栏控件,并重写其中的方法

public class TitleLayout extends LinearLayout {
    
    
    public TitleLayout(Context context, AttributeSet attrs) {
    
    
        super(context, attrs);
        LayoutInflater.from(context).inflate(R.layout.title,this);
    }
}

其中LayoutInflater的from()方法调用inflate方法以动态加载一个布局文件,传入的第一个参数就要加载的布局文件的id,第二个参数就是给加载好的布局再添加一个父布局
2、主活动布局文件中添加自定义控件代码:

 <com.example.uicustomviews.TitleLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

3、然后再在第一点的类中为按钮注册点击事件

public class TitleLayout extends LinearLayout {
    
    
    public TitleLayout(Context context, AttributeSet attrs) {
    
    
        super(context, attrs);
        LayoutInflater.from(context).inflate(R.layout.title,this);
        Button titleback = (Button)findViewById(R.id.title_back);
        Button titleEdit = (Button)findViewById(R.id.title_edit);
        titleback.setOnClickListener(new OnClickListener() {
    
    
            @Override
            public void onClick(View v) {
    
    
                ((Activity)getContext()).finish();
            }
        });
        titleEdit.setOnClickListener(new OnClickListener() {
    
    
            @Override
            public void onClick(View v) {
    
    
                Toast.makeText(getContext(),"Editing",Toast.LENGTH_SHORT).show();
            }
        });
    }
}

这样子我们就实现了自定义控件
3.5 ListView控件
作用:该控件允许用户通过手指上下滑动的方式将屏幕外的数据滚动到屏幕内,同时屏幕上原有的数据则会滚出屏幕
3.5.1 ListView 的简单用法
1、首先创建一个ListViewTest项目,并且自动创建好活动,然后修改activity_main.xml中的代码,如下图所示
在这里插入图片描述
2、在主活动的类中把需要展示的数据提供好,这些数据既可以是从网上下载的,也可以是从数据库中读取的,这里我们采用data数组来测试,里面包含了很多水果的名称
3、对于要展示数据,我们需要借用适配器才能将数据传入到ListView控件当中,这里采用ArrayAdapter适配器。它可以通过泛型指定要传入的数据的数据类型,然后在构造函数中依次传入当前上下文活动,我们使用android.R.layout.simple_list_item_1作为ListView子项布局的id,这是一个内置的布局文件,里面只有一个TextView。再传入要传入的数据的数组名。最后调用ListView的setAdapter()方法建立联系。这样ListView的简单用法就实现了
在这里插入图片描述
如图所示:
在这里插入图片描述
3.5.2 定制ListView的界面
我们以上面的例子为例:
1、首先准备好一组图片,分别对应好每一种水果
2、接着定义一个实体类,作为ListView适配器的适配类型。新建Fruit类,代码如下图所示:
在这里插入图片描述
Fruit类中存入两个字段,一个水果的名字,一个水果的图片
3、然后需要为ListView的子项指定一个我们自定义的布局,在layout目录下新建fruit_item.xml,代码如下图所示:
在这里插入图片描述
其中ImageView用于显示水果图片,Textview用于显示水果名字
4、接下来创建一个自定义的适配器,这个适配器要继承自ArrayAdapter,并将泛型指定为Fruit类。新建一个FruitAdapter类,代码如下:
在这里插入图片描述
①我们看到,FruitAdapter重写了父类的一组构造函数,用于将上下文、ListView的子项布局的id和数据都传进来
②重写了getView()方法,这个方法在每个子项被滚动到屏幕内的时候会被调用
③在getView()方法中,首先通过getItem()方法得到当前项的Fruit实例,然后使用LayoutInflater来为这个子项加载我们传入的布局
④inflate()方法中传入的第三个参数表示只让我们在父布局中声明的layout属性生效,但不会为这个View添加父布局
⑤接下来就是获取两个控件的实例,并分别调用set方法来设置图片和文字,最后将布局返回,这样自定义的适配器就完成了

5、最后在MainActivity中的代码如下:
在这里插入图片描述
结果如下:
在这里插入图片描述
3.5.3 提升ListView 的运行效率
修改FruitAdapter中的代码,如下图所示:
在这里插入图片描述
这样子修改前,每次调用都会将布局重新加载一边;修改后,进行判断,如果为null,就加载,反之则直接利用,这样就大大提高了效率。
3.5.4 ListVIew的点击事件
在这里插入图片描述
这里我们使用setOnItenClickListener()方法为ListView注册了一个监听器,当用户点击了ListView中的任何一个子项时,都会回调onItenClick()方法,在该方法中通过判断用户点击了哪一个子项然后获取到相应的水果,并通过Toast将水果名字显现出来
3.6 RecyclerView 滚动控件
RecyclerView控件是ListView的增强版,不仅可以轻松实现和ListView同样的效果,还优化了ListView中存在的不足之处
3.6.1 RecyclerView基本用法
1、首先要添加相应的依赖库
在这里插入图片描述
2、然后修改activity_man.xml中的代码:
在这里插入图片描述
3、同上面ListView一样,①准备一份水果图片②创建一个Fruit类③在layout目录下新建fruit_item.xml
4、自定义适配器
在这里插入图片描述
①首先我们定义了一个内部类ViewHolder,并让他继承RecyclerView.ViewHolder类
②然后在构造函数中传入一个View参数,这个参数通常就是RecyclerView子项的最外层布局
③获取两个控件的实例
④FruitAdapter类中的构造函数用于把要展示的数据源传进来,并赋予给一个全局变量,以便于后续调用
⑤三个被重写的方法中第一个方法用于创建ViewHolder的实例
⑥第二个方法用于对RecyclerView的子项的数据源进行赋值
⑦第三个返回数据源长度
5、修改MainActivity中的代码:
在这里插入图片描述
①在onCreate()方法中我们先获取到RecyclerView的实例
②然后创建了一个LinearLayoutManager对象,并将他设置到RecyclerView当中
③LayoutManager用于指定RecyclerView的布局方式,这里指定的时线性布局的方式
结果:
在这里插入图片描述
3.6.2 实现横向滚动和瀑布流布局
如何实现横向滚动?
1、首先要对fruit_item.xml布局进行修改
在这里插入图片描述
现在我们把排列方向改为垂直方向排列,并把宽度设置为100dp
2、接下来我们修改MainActivity中的代码,改变布局排列方向
在这里插入图片描述
结果如图:
在这里插入图片描述
为啥RecyclerView能够如此轻松实现这种布局而ListView几乎不能实现?——因为前者继承了LayoutManager接口,这样就能实现多种样式

除此之外,我们还可以实现网格布局或者瀑布流布局
如何实现瀑布流布局?
1、首先要对fruit_item.xml布局进行修改
在这里插入图片描述
2、接下来我们修改MainActivity中的代码
在这里插入图片描述
在onCreate()方法中,我们创建了一个StaggeredGridLayoutManager的实例,其中传入两个参数,第一个参数用于指定布局的列数,第二个参数用于指定布局的排列方向
结果如图:
在这里插入图片描述
3.6.3 RecyclerView的点击事件
与ListView不同的是,RecyclerView需要自己给子项具体的View去注册点击事件
如何注册?
1、修改FruitAdapter中的代码,如下图:
在这里插入图片描述
在这里插入图片描述
我们首先修改了ViewHolder,在ViewHolder中添加了fruitView变量来保存子项最外城布局的实例。然后再在onCreateViewHolder()方法中注册点击事件就可以了

3.7 小结
1、本节讲了七种控件及其使用方法
TextView——主要用于在界面上显示一段文本信息
Button——表示在界面上显示一个按钮,有两种注册监听器的方法
EditText——允许用户在控件里输入和编辑内容,并可以在程序中对这些内容进行处理
ImageView——适用于在界面上展示图片的一个控件,他可以使得程序界面变得更加丰富多彩
ProgressBar——用于在界面上显示一个进度条,表示我们的程序正在加载一些数据
AlertDialog——可以在当前得界面弹出一个对话框,该对话框置顶于所有界面元素之上的,能够屏蔽掉其他控件得交互能力,因此AlertDialog一般都是用于提示一些非常重要的内容或着警告信息
ProgressDialog——跟ProgressDialog类似,弹出一个对话框,能够屏蔽掉其他控件的交互能力。不同的是,ProgressDialog会在对话框中显示一个进度条,一般用于表示当前操作比较耗时,让用户耐心地等待
2、四种基本布局
线性布局(LinearLayout)
定义:该布局会将它所包含的控件在线性方向上依次排列,其代码都是在LinearLayout元素下实现的
相对布局(RelativeLayout)
定义:他可以通过相对定位的方式让控件出现在布局的任何位置,其控件都是在RelativeLayout布局下实现的
帧布局(FrameLayout)
定义:此布局没有方便的定位方式,所有的控件都会默认摆放在布局的左上角,其代码都是在FrameLayout布局下实现的
百分比布局
百分比布局只为FrameLayout 、RelativeLayout中进行了扩展,其代码分别是在PercentFrameLayout和PrecentRelativeLayout布局下实现的,这两个布局分别继承了前者的所有属性和方法
3、如何引用自定义布局
4、如何创建自定义控件
5、ListView与RecyclerView的联系与区别

猜你喜欢

转载自blog.csdn.net/Cristiano_san/article/details/106035133