第1章 简单控件 1.2 视图基础

        本节介绍视图的几个基本概念及其用法,包括:如何设置视图的宽度和高度,如何设置视图的外部间距和内部间距,如何设置视图的外部对齐方式和内部对齐方式,等等。

1.2.1    设置视图的宽和高

        手机屏幕是块长方形区域,较短的那条边叫做宽,较长的那条边叫做高。App控件通常也是长方形形状,控件宽度通过属性android:layout_width表达,控件高度通过属性android:layout_height表达,宽和高的取值主要有下列3种:

        (1)match_parent:表示与上级视图保持一致。上级视图的尺寸有多大,当前视图的尺寸就有多大。

        (2)wrap_content:表示与内容自适应。对于文本视图来说,内部文字需要多大的显示空间,当前视图就要占据多大的尺寸。但最宽不能超过上级视图的宽度,一旦超过就要换行;最高不能超过上级视图的高度,一旦超过就会被隐藏。

        (3)以dp为单位的具体尺寸,比如300dp,表示宽度或高度就是这么大。

        在XML文件中采用以上任一方式均可设置视图的宽和高,但在Java代码中设置宽和高就有点复杂了,首先确保XML中的宽、高属性值为wrap_content,这样才允许在代码中修改宽和高。接着打开该页面对应的Java代码,依序执行以下3个步骤:

01    调用控件对象的getLayoutParams方法来获取布局参数,参数类型为ViewGroup.LayoutParams。

02    布局参数的width属性表示宽度,height属性表示高度,修改这两个属性值,即可调整控件的宽和高。

03    调用控件对象的setLayoutParams方法,填入修改后的布局参数使之生效。

        不过布局参数的width和height两个数值默认是px单位,需要将dp单位的数值转换为px单位的数值,然后才能赋值给width属性和height属性。下面是把dp大小转为px大小的方法代码:

public class Utils {
    //根据手机的分辨率从dp的单位转成为px(像素)
    public static int dip2px(Context context,float dpValue){
        //获取当前手机的像素密度(1个dp对应几个px)
        float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue*scale+0.5f); //四舍五入取整
    }
}

        有了上面定义的公共方法dip2px,就能将某个dp数值转换成px数值,比如准备把文本视图的宽度改为300dp,那么调整宽度的Java代码示例如下: 

<TextView
    android:id="@+id/tv_code"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="#00ffff"
    android:text="通过代码指定视图宽度"
    android:textColor="#000000"
    android:textSize="17sp" />
//获取名为tv_code的文本视图
TextView tv_code = findViewById(R.id.tv_code);
//获取tv_code的布局参数(含宽度和高度)
ViewGroup.LayoutParams params = tv_code.getLayoutParams();
//修改布局参数中的宽度数值,注意默认是px单位,需要把dp数值转成px数值
params.width = Utils.dip2px(this,300);
tv_code.setLayoutParams(params);  //设置tv_code的布局参数

        接下来通过演示页面并观察几种尺寸设置方式的界面效果,主要通过背景色区分当前视图的宽高范围,详细的XML文件内容如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ViewBorderActivity">
    <TextView
        android:id="@+id/tv_code"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#00ffff"
        android:text="通过代码指定视图宽度"
        android:layout_marginTop="5dp"
        android:textColor="#000000"
        android:textSize="17sp" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:background="#00ffff"
        android:text="视图宽度采用wrap_content定义"
        android:textColor="#000000"
        android:textSize="17sp" />
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:background="#00ffff"
        android:text="视图宽度采用match_parent定义"
        android:textColor="#000000"
        android:textSize="17sp" />
    <TextView
        android:layout_width="300dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:background="#00ffff"
        android:text="视图宽度采用固定大小"
        android:textColor="#000000"
        android:textSize="17sp" />
</LinearLayout>

        运行测试App,打开的演示界面如图所示,依据背景色判断文本视图的边界,可见wrap_content方式刚好包住了文本内容,match_parent方式扩展到了与屏幕等宽,而300dp的宽度介于前两者之间(安卓手机的屏幕宽度基本为360dp)。

1.2.2    设置视图的间距 

        在上一小节末尾的XML文件中,每个TextView标签都携带新的属性android:layout_marginTop="5dp",该属性的作用是让当前视图与上方间隔一段距离。同理,android:layout_marginLeft让当前视图与左边间隔一段距离,android:layout_marginRight让当前视图与右边间隔一段距离,android:layout_marginBottom让当前视图与下方间隔一段距离。如果上下左右都间隔同样的距离,还能使用android:layout_margin一次性设置四周的间距。

        layout_margin不单单用于文本视图,还可用于所有视图,包括各类布局和各类控件。因为不管布局还是控件,它们统统由视图基类View派生而来,而layout_margin正是View的一个通用属性,所以View的子子孙孙都能使用layout_margin。在View的大家族中,视图组ViewGroup尤为特殊它既是View的子类,又是各类布局的基类。布局下面能容纳其他视图,而控件却不行,这正源自ViewGroup的组装特性。View、ViewGroup、控件、布局四者的继承关系如图所示。

        除了layout_margin之外,padding也是View的一个通用属性,它用来设置视图的内部间距,并且padding也提供了paddingTop、paddingBottom、paddingLeft、paddingRight四个方向的距离属性。同样是设置间距,layout_margin指的是当前视图与外部视图(包括上级视图和平级视图)之间的距离,而padding指的是当前视图与内部视图(包括下级视图和内部文本)之间的距离。为了观察外部间距和内部间距的差异,接下来做个实验,看看layout_margin与padding究竟有什么区别。

        首先创建新的活动页面,并给该页面的XML文件填入以下的布局内容:

<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:id="@+id/main"
    android:orientation="vertical"
    android:background="#00aaff"
    android:layout_width="match_parent"
    android:layout_height="300dp"
    tools:context=".ViewMarginActivity">
    <!--中间层的布局背景为黄色-->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="20dp"
        android:background="#ffff99"
        android:padding="60dp" >
        <!--最内层的视图背景为红色-->
        <View
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#ff0000" />
    </LinearLayout>
</LinearLayout>

        上面的XML文件有两层视图嵌套,第一层是蓝色背景布局里面放黄色背景布局,第二层是黄色背景布局里面放红色背景视图。中间层的黄色背景布局,同时设置了20dp的layout_margin,以及60dp的padding,其中padding是layout_margin的三倍宽(60/20=3)。接着运行测试App,看到的演示界面如图所示。

        从效果图可见,外面一圈间隔较窄,里面一圈间隔较宽,表示20dp的layout_margin位于外圈,而60dp的padding位于内圈。这种情况印证了:layout_margin指的是当前图层与外部图层的距离,而padding指的是当前图层与内部图层的距离。

1.2.3    设置视图的对齐方式

        App界面上的视图排列,默认靠左朝上对齐,这也符合日常的书写格式。然而页面的排版不是一成不变的,有时出于美观或者其他原因,要将视图排列改为朝下或靠右对齐,为此需要另外指定视图的对齐方式。在XML文件中通过属性android:layout_gravity可以指定当前视图的对齐方向,当属性值为top时表示视图朝上对齐,为bottom时表示视图朝下对齐,为left时表示视图靠左对齐,为right时表示视图靠右对齐。如果希望视图既朝上又靠左,则用竖线连接top与left,此时属性标记为android:layout_gravity="top|left";如果希望视图既朝下又靠右,则用竖线连接bottom与right,此时属性标记为android:layout_gravity="bottom|right"。

        注意layout_gravity规定的对齐方式,指的是当前视图往上级视图的哪个方向对齐,并非当前视图的内部对齐。若想设置内部视图的对齐方向,则需由当前视图的属性android:gravity指定,该属性一样拥有top、bottom、left、right  4种取值及其组合。它与layout_gravity的不同之处在于:layout_gravity设定了当前视图相对于上级视图的对齐方式,而gravity设定了下级视图相对于当前视图的对齐方式;前者决定了当前视图的位置,而后者决定了下级视图的位置。

        为了进一步分辨layout_gravity与gravity的区别,接下来做个实验,对某个布局视图同时设置android:layout_gravity和android:gravity属性,再观察内外视图的对齐情况。下面便是实验用的XML文件例子:

<?xml version="1.0" encoding="utf-8"?>
<!--最外层的布局背景为橙色,它的下级视图在水平方向排列-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:background="#ffff99"
    android:padding="5dp"
    android:layout_width="match_parent"
    android:layout_height="300dp"
    tools:context=".ViewGravityActivity">
    <!--第一个子布局背景为红色,它在上级视图中朝下对齐,它的下级视图则靠左对齐-->
    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="200dp"
        android:layout_weight="1"
        android:layout_gravity="bottom"
        android:gravity="left"
        android:background="#ff0000"
        android:layout_margin="10dp"
        android:padding="10dp">
        <!--内部视图的宽度和高度都是100dp,且背景色为青色-->
        <View
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:background="#00ffff" />
    </LinearLayout>
    <!--第二个子布局背景为红色,它在上级视图中朝上对齐,它的下级视图则靠右对齐-->
    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="200dp"
        android:layout_weight="1"
        android:background="#ff0000"
        android:layout_gravity="top"
        android:gravity="right"
        android:layout_margin="10dp"
        android:padding="10dp">
        <!--内部视图的宽度和高度都是100dp,且背景色为青色-->
        <View
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:background="#00ffff" />
    </LinearLayout>
</LinearLayout>

        运行测试App,打开演示界面如图所示。

 

        由效果图可见,第一个子布局朝下,并且它的内部视图靠左;而第二个子布局朝上,并且它的内部视图靠右。对比XML文件中的layout_gravity和gravity取值,证明了二者的对齐情况正如之前所言:layout_gravity决定当前视图位于上级视图的哪个方位,而gravity决定了下级视图位于当前视图的哪个方位。 

  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值