Android布局

时间:2020-01-09 10:34:00  来源:igfitidea点击:

在Android中,术语"布局"是指定义"视图"组件如何相对于彼此在屏幕上显示。布局通常部分由"视图"定义,部分由包含"视图"的"视图组"定义。如View和ViewGroup中所述,ViewGroup是View的子类,View本身可以包含View实例。

我们可以通过编程或者通过XML布局文件指定布局(即要使用的" ViewGroup"及其包含的" View"实例)。在大多数情况下,使用XML布局文件是最容易的,但是在某些情况下,可能有必要以编程方式定义用户界面布局。因此,本文涵盖了这两种选择。

布局XML文件

由于布局XML文件是最常用的布局选项,因此我将首先介绍它们。布局XML文件是一种XML文件,存储在Android项目的/ app / src / main / res / layout目录中。

按照惯例,应在布局文件所代表的名称之后命名布局文件。例如,通常为活动的布局文件指定一个以actvity_开头的名称。因此,名为" MainActivity"的活动的布局文件将被命名为" activity_main.xml"。

布局XML文件始终包含一个根元素。这个根元素通常引用一个" ViewGroup"实例。这是仅带有根元素的布局XML文件示例:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical" android:layout_width="match_parent"
              android:layout_height="match_parent">

</LinearLayout>

注意,根元素是一个LineLineLayout元素,它引用了LinearLayout ViewGroup子类。

在根ViewGroup实例内部,布局文件可以声明其他View和ViewGroup实例。这是一个布局文件示例,该示例显示了以前的根元素,其中包含TextView元素:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical" android:layout_width="match_parent"
              android:layout_height="match_parent">

    <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            >

    </TextView>

</LinearLayout>

在活动中使用布局文件

创建布局文件后,可以将其用作"活动"子类的内容视图。换句话说,我们可以显示活动中布局文件中定义的布局。

要将布局文件用作活动的内容视图,请从活动的onCreate()方法内部调用活动的setContentView()方法。这是一个例子:

public class MainActivity extends Activity {

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

注意传递给setContentView()的参数:

R.layout.activity_main

这是Android Studio生成的常量,它引用布局文件" activity_main.xml"。

宽度和高度

使用布局XML文件声明布局时,必须为每个ViewGroupView元素分别设置两个属性layout_widthlayout_height的值。这是一个看起来的例子:

<RelativeLayout 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"
                tools:context=".MainActivity">

    <TextView android:text="@string/hello_world"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />

</RelativeLayout>

我们可以为layout_width和layout_height使用两个不同的值:

  • match_parent
  • wrap_content

值match_parent表示ViewGroup或者View应该尝试匹配其父级的宽度或者高度(减去任何填充)。

值" wrap_content"表示" ViewGroup"或者" View"的宽度和高度应与其所包含内容的宽度和高度相对应(意味着在上方,下方或者旁边没有额外的空间)。

填充

布局文件中的ViewGroupView元素都可以指定要在其周围添加的填充。填充是什么也没画的空间。因此,填充在屏幕上的"视图"或者"视图组"与其相邻的"视图"或者"视图组"之间留出空间。

我们可以使用以下XML属性之一在"视图"周围设置填充:

  • android:paddingLeft
  • android:paddingRight
  • android:paddingTop
  • android:paddingBottom

这是前面的布局文件示例,其中添加了padding属性:

<RelativeLayout 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:paddingLeft="@dimen/activity_horizontal_margin"
                android:paddingRight="@dimen/activity_horizontal_margin"
                android:paddingTop="@dimen/activity_vertical_margin"
                android:paddingBottom="@dimen/activity_vertical_margin"
                tools:context=".MainActivity">

    <TextView android:text="@string/hello_world"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content" />

</RelativeLayout>

四个不同填充属性中使用的值引用了位于" app / src / main / res / values / dimens.xml"中的" dimensions.xml"文件中定义的值。上面引用的定义如下所示:

<resources>
    <dimen name="activity_horizontal_margin">16dp</dimen>
    <dimen name="activity_vertical_margin">16dp</dimen>
</resources>

值" 16dp"表示16个与设备无关的像素,表示与中等屏幕分辨率设备上的16个像素相对应的像素数量。因此,在高分辨率设备上,实际的像素数可以是24或者32个像素等,具体取决于设备的确切分辨率(实际上是像素密度)。

程序布局

如果要为活动创建布局,也可以通过编程方式进行。我们可以通过从活动的onCreate()方法内部实例化一个View或者ViewGroup来实现。这是一个例子:

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        TextView textView = new TextView(this);
        textView.setText("Content View");

        setContentView(textView);
    }
}

本示例创建一个" TextView"并将其用作内容视图。

由于活动只能将单个"视图"用作内容视图,因此通常将" ViewGroup"用作内容视图。 ViewGroup是View的子类。一个ViewGroup可以其中包含多个View,因此使用ViewGroup作为内容视图可以使视图包含多个View实例。

这是一个使用LinearLayout(ViewGroup的子类)作为内容视图并其中放入TextView的示例:

public class MainActivity extends Activity {

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

        TextView textView1 = new TextView(this);
        textView1.setText("Text View 1");

        TextView textView2 = new TextView(this);
        textView2.setText("Text View 2");

        LinearLayout linearLayout = new LinearLayout(this);
        linearLayout.addView(textView1);
        linearLayout.addView(textView2);

        setContentView(linearLayout);
    }
}

以编程方式设置宽度和高度

如果以编程方式创建布局,则很可能还需要为该布局设置一些布局参数。这是一个设置上一示例中两个TextView实例的宽度和高度布局参数的示例:

public class MainActivity extends Activity {

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

        TextView textView1 = new TextView(this);
        textView1.setText("Text View 1");
        LinearLayout.LayoutParams layoutParams1 = new LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
        textView1.setLayoutParams(layoutParams1);

        TextView textView2 = new TextView(this);
        textView2.setText("Text View 2");
        LinearLayout.LayoutParams layoutParams2 = new LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
        textView2.setLayoutParams(layoutParams2);

        LinearLayout linearLayout = new LinearLayout(this);
        linearLayout.setOrientation(LinearLayout.VERTICAL);
        linearLayout.addView(textView1);
        linearLayout.addView(textView2);

        setContentView(linearLayout);
    }
}

还要注意," LinearLayout"上的布局方向设置为" Layout.VERTICAL",这意味着" TextView"实例将在彼此下方显示。

以编程方式设置填充

我们也可以使用setPadding()方法在给定的View上以编程方式设置填充。这是一个例子:

textView2.setPadding(20, 20, 20, 20);

本示例将左侧,顶部,右侧和底部的填充设置为20像素。注意:这些是真实像素,而不是与设备无关的像素。

我们也可以用同样的方法在ViewGroup上设置填充。

线性布局

" LinearLayout"是" ViewGroup"子类,它会根据所处的方向以线性方式(垂直或者水平)呈现添加到其中的所有" View"实例。我们可以在布局XML文件中或者以编程方式创建" LinearLayout"。

这是一个使用布局XML创建的" LinearLayout"示例:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:paddingLeft="@dimen/activity_horizontal_margin"
              android:paddingRight="@dimen/activity_horizontal_margin"
              android:paddingTop="@dimen/activity_vertical_margin"
              android:paddingBottom="@dimen/activity_vertical_margin"
              tools:context=".MainActivity">

    <TextView android:text="@string/hello_world"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content" />

</LinearLayout>

注意" android:orientation"属性,可以将其设置为"水平"或者"垂直"。

这是通过编程创建的" LinearLayout"示例:

LinearLayout linearLayout = new LinearLayout(this);
linearLayout.setOrientation(LinearLayout.VERTICAL);
linearLayout.addView(textView1);
linearLayout.addView(textView2);

相对布局

" RelativeLayout"是一个" ViewGroup",它相对于父级" ViewGroup"的边缘(即" RelativeLayout"实例本身)或者相对于内部显示的其他" View"实例,将其中显示的" View"实例定位相同的" RelativeLayout"。

" RelativeLayout"提供了两组XML属性,可用于指定如何定位给定的" View"实例。第一组属性将"视图"相对于其父" RelativeLayout"元素边缘定位。第二组属性将"视图"相对于同一" RelativeLayout"中的另一个"视图"定位。

这是用于相对于其父" RelativeLayout"边缘定位"视图"的属性集:

  • android:layout_alignParentLeft
  • android:layout_alignParentRight
  • android:layout_alignParentTop
  • android:layout_alignParentBottom
  • android:layout_alignParentStart
  • android:layout_alignParentEnd
  • android:layout_centerHorizontal
  • android:layout_centerVertical
  • android:layout_centerInParent
  • android:layout_alignWithParentIfMissing

所有这些属性都可以采用" true"或者" false"的值。我们可以指定多个,例如layout_alignParentRightlayout_alignParentBottom会将View放在RelativeLayout的右下角。

这是用于将一个"视图"相对于同一" RelativeLayout"中的另一个"视图"定位的属性集:

  • android:layout_above
  • android:layout_alignBaseline
  • android:layout_alignBottom
  • android:layout_alignEnd
  • android:layout_alignLeft
  • android:layout_alignRight
  • android:layout_alignStart
  • android:layout_alignTop
  • android:layout_below
  • android:layout_toEndOf
  • android:layout_toLeftOf
  • android:layout_toRightOf
  • android:layout_toStartOf

这些属性大多数都是不言而喻的。与他们一起玩耍,以更好地了解他们的工作方式。

这是一个" RelativeLayout"示例:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent">

    <TextView
            android:id="@+id/textview_one"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"

            android:text="One"
            />

    <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"

            android:layout_above="@id/textview_one"
            android:text="Two"
            />

</RelativeLayout>

这个示例包含一个布局XML文件,该文件以RelativeLayout作为根View。在" RelativeLayout"内部是两个" TextView"实例。第一个TextView元素使用属性layout_alignParentBottom来将TextView放置在RelativeLayout的底部。第二个TextView元素使用layout_above属性在ID为textview_one的View上定位自身(这是第一个TextView实例)。

熟悉RelativeLayout之后,我们可以实现一些功能非常强大的布局。

框架布局

一个FrameLayout是一个ViewGroup子类,它将它包含的View实例彼此叠放在一起,就像一副纸牌。因此,当仅在FrameLayout内部显示单个View时(例如WebView),通常会使用FrameLayout。但是,如有必要,可以在第一个"视图"的顶部获取" FrameLayout"以显示其他视图。

这是一个使用布局XML文件的FrameLayout示例:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             android:layout_width="match_parent"
             android:layout_height="match_parent">

    <WebView
            android:id="@+id/webview_one"
            android:layout_width="match_parent"
            android:layout_height="match_parent"></WebView>

    <TextView
            android:id="@+id/textview_one"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="top|right"

            android:text="One"
            />

    <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"

            android:layout_gravity="bottom|right"
            android:text="Two"
            />

</FrameLayout>

这个例子创建了一个带有WebView和两个TextView实例的FrameLayout。 FrameLayout将首先显示WebView,然后在WebView顶部显示两个TextView实例(因为它们稍后在XML文件中列出)。

注意两个TextView实例如何使用layout_gravity属性来指定它们在FrameLayout中的显示位置。