Android UI Design:表格布局(Table Layouts)

原文地址:http://mobile.tutsplus.com/tutorials/android/android-sdk_table-layout/

表格布局(Table Layout)是被用于显示表格式的数据的一种布局。接下来让我们学习如何通过XML布局文件和代码两种方式来创建表格布局(Table Layout)。

理解布局对于设计好的Android应用程序是非常重要的。在本教程中,你能学到关于表格布局(Table Layout)的一切知识,其中包括如何在屏幕上定义好的行与列中去布置UI控件或widgets。使用得当的话,表格布局(Table Layout)能帮助你在你的Android应用程序中设计出强大的布局来显示表格式的数据。

什么是表格布局(Table Layout)?

一个表格布局(Table Layout)正是你所期待的:由行和列组成的网格,且每个单元格能显示一个视图控件。从一个用户界面设计角度来看,一个表格布局(Table Layout)由TableRow控件组成-在你的表格中一行。TableRow的内容只是盛放表格中每个单元格的视图控件。

表格布局(Table Layout)的外观是由几个附加规则来管理的。首先,整个表格的列数要匹配表格中最多列数的那行的列数。第二,每一列的宽度应该用在列中最宽的内容来定义。表格布局(Table Layout)中的行和单元格的宽度属性一般设置为MATCH_PARENT。表格布局(Table Layout)中单元格的layout_height属性也可以被定义,但是TableRow的layout_height属性总是为WRAP_CONTENT。单元格可以跨越列,而不能是行。这是通过设置一个TableRow的子视图的layout_span属性来是实现的。 一个单元格是一个TableRow中的单独的子视图。如果你想要一个更复杂的多视图单元格,使用一个布局来把其他视图装进去。

也就是说,有的规则是可以修改的。列可以被标记为可伸缩的,这意味着它的宽度可以扩展到父容器尺寸。列可以标记为可收缩的,这意味着他们可以减少行宽来使得整个行来适应父容器提供的空间。

表格布局(Table Layout)的完整文档,可以到Android SDK文档来查看TableLayout类。用于XML资源文件的相关XML属性也同样在文档定义了。

设计一个简单的表格布局(Table Layout)

Layouts are best explained by example, and table layouts are no different. Let’s say we want to design a screen that shows the extended weather forecast. A table layout might be a good choice for organizing this information:

  • In the first TableRow, we can display a title for the screen.
  • In the second TableRow, we can display the dates in a familiar calendar-like format.
  • In the third TableRow, we can display a Daily High temperature information.
  • In the fourth TableRow, we can display a Daily Low temperature information.
  • In the fifth TableRow, we can display graphics to identify the weather conditions, such as rain, snow, sun, or cloudy with a chance of meatballs.

This first figure shows an early look at the table inside the layout editor:

Defining an XML Layout Resource with a Table Layout

The most convenient and maintainable way to design application user interfaces is by creating XML layout resources. This method greatly simplifies the UI design process, moving much of the static creation and layout of user interface controls and definition of control attributes, to the XML, instead of littering the code.

XML layout resources must be stored in the /res/layout project directory hierarchy. Let’s take a look at the table layout introduced in the previous section. This layout resource file, aptly named /res/layout/table.xml, is defined in XML as follows:

<?xml version="1.0" encoding="utf-8"?>  
<TableLayout  
    xmlns:android="http://schemas.android.com/apk/res/android"  
    android:id="@+id/tableLayout1"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    android:shrinkColumns="*"  
    android:stretchColumns="*">  
    <TableRow  
        android:id="@+id/tableRow4"  
        android:layout_height="wrap_content"  
        android:layout_width="match_parent"  
        android:gravity="center_horizontal">  
        <TextView  
            android:id="@+id/textView9"  
            android:layout_width="match_parent"  
            android:layout_height="wrap_content"  
            android:textStyle="bold"  
            android:typeface="serif"  
            android:textSize="18dp"  
            android:text="Weather Table"  
            android:gravity="center"  
            android:layout_span="6"></TextView>  
    </TableRow>  
    <TableRow  
        android:id="@+id/tableRow1"  
        android:layout_height="wrap_content"  
        android:layout_width="match_parent">  
        <TextView  
            android:id="@+id/TextView04"  
            android:text=""></TextView>  
        <TextView  
            android:id="@+id/TextView04"  
            android:text="Feb 7"  
            android:textStyle="bold"  
            android:typeface="serif"></TextView>  
        <TextView  
            android:id="@+id/TextView03"  
            android:text="Feb 8"  
            android:textStyle="bold"  
            android:typeface="serif"></TextView>  
        <TextView  
            android:id="@+id/TextView02"  
            android:text="Feb 9"  
            android:textStyle="bold"  
            android:typeface="serif"></TextView>  
        <TextView  
            android:id="@+id/TextView01"  
            android:text="Feb 10"  
            android:textStyle="bold"  
            android:typeface="serif"></TextView>  
        <TextView  
            android:text="Feb 11"  
            android:id="@+id/textView1"  
            android:textStyle="bold"  
            android:typeface="serif"></TextView>  
    </TableRow>  
    <TableRow  
        android:layout_height="wrap_content"  
        android:id="@+id/tableRow2"  
        android:layout_width="match_parent">  
        <TextView  
            android:text="Day High"  
            android:id="@+id/textView2"  
            android:textStyle="bold"></TextView>  
        <TextView  
            android:id="@+id/textView3"  
            android:text="28°F"  
            android:gravity="center_horizontal"></TextView>  
        <TextView  
            android:text="26°F"  
            android:id="@+id/textView4"  
            android:gravity="center_horizontal"></TextView>  
        <TextView  
            android:text="23°F"  
            android:id="@+id/textView5"  
            android:gravity="center_horizontal"></TextView>  
        <TextView  
            android:text="17°F"  
            android:id="@+id/textView6"  
            android:gravity="center_horizontal"></TextView>  
        <TextView  
            android:text="19°F"  
            android:id="@+id/textView7"  
            android:gravity="center_horizontal"></TextView>  
    </TableRow>  
    <TableRow  
        android:layout_height="wrap_content"  
        android:id="@+id/tableRow2"  
        android:layout_width="match_parent">  
        <TextView  
            android:text="Day Low"  
            android:id="@+id/textView2"  
            android:textStyle="bold"></TextView>  
        <TextView  
            android:text="15°F"  
            android:id="@+id/textView3"  
            android:gravity="center_horizontal"></TextView>  
        <TextView  
            android:text="14°F"  
            android:id="@+id/textView4"  
            android:gravity="center_horizontal"></TextView>  
        <TextView  
            android:text="3°F"  
            android:id="@+id/textView5"  
            android:gravity="center_horizontal"></TextView>  
        <TextView  
            android:text="5°F"  
            android:id="@+id/textView6"  
            android:gravity="center_horizontal"></TextView>  
        <TextView  
            android:text="6°F"  
            android:id="@+id/textView7"  
            android:gravity="center_horizontal"></TextView>  
    </TableRow>  
    <TableRow  
        android:id="@+id/tableRow3"  
        android:layout_height="wrap_content"  
        android:layout_width="match_parent"  
        android:gravity="center">  
        <TextView  
            android:id="@+id/textView8"  
            android:text="Conditions"  
            android:textStyle="bold"></TextView>  
        <ImageView  
            android:id="@+id/imageView1"  
            android:src="@drawable/hot"></ImageView>  
        <ImageView  
            android:id="@+id/imageView2"  
            android:src="@drawable/pt_cloud"></ImageView>  
        <ImageView  
            android:id="@+id/imageView3"  
            android:src="@drawable/snow"></ImageView>  
        <ImageView  
            android:id="@+id/imageView4"  
            android:src="@drawable/lt_snow"></ImageView>  
        <ImageView  
            android:id="@+id/imageView5"  
            android:src="@drawable/pt_sun"></ImageView>  
    </TableRow>  
</TableLayout>  

Recall that, from within the Activity, only a single line of code within the onCreate() method is necessary to load and display a layout resource on the screen. If the layout resource was stored in the /res/layout/table.xml file, that line of code would be:
setContentView(R.layout.table);  

This table layout has all its columns set to both shrink and stretch by using a “*” in the value. If just certain columns should shrink or stretch, the values would be a comma seperated list (using 0-based indexes for columns).

The table now looks like the following to screenshots when in portrait and landscape mode.





Defining a Table Layout Programmatically

You can also programmatically create and configure table layouts in Java. This is done using the TableLayout and TableRow classes (android.widget.TableLayout and android.widget.TableRow). You’ll find the unique display parameters for each control in the TableLayout.LayoutParams and TableRow.LayoutParams classes. Also, the typical layout parameters (android.view.ViewGroup.LayoutParams), such as layout_height and layout_width, as well as margin parameters (ViewGroup.MarginLayoutParams), still apply to TableLayout and TableRow objects, but not necessarily table cells. For table cells (any View inside the TableRow), the width is always MATCH_PARENT. The height can be defined, but defaults to WRAP_CONTENT and need not be specified.
Instead of loading a layout resource directly using the setContentView() method as shown earlier, if you create a layout programmatically, you must instead build up the screen contents in Java and then supply a parent layout object which contains all the control contents to display as child views to the setContentView() method. In this case, your parent layout used would be the table layout created.

For example, the following code illustrates how to programmatically have an Activity instantiate a TableLayout layout parameters and reproduce the example shown earlier in XML:

@Override  
public void onCreate(Bundle savedInstanceState) {  
    super.onCreate(savedInstanceState);  
  
    TableLayout table = new TableLayout(this);  
  
    table.setStretchAllColumns(true);  
    table.setShrinkAllColumns(true);  
  
    TableRow rowTitle = new TableRow(this);  
    rowTitle.setGravity(Gravity.CENTER_HORIZONTAL);  
  
    TableRow rowDayLabels = new TableRow(this);  
    TableRow rowHighs = new TableRow(this);  
    TableRow rowLows = new TableRow(this);  
    TableRow rowConditions = new TableRow(this);  
    rowConditions.setGravity(Gravity.CENTER);  
  
    TextView empty = new TextView(this);  
  
    // title column/row  
    TextView title = new TextView(this);  
    title.setText("Java Weather Table");  
  
    title.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18);  
    title.setGravity(Gravity.CENTER);  
    title.setTypeface(Typeface.SERIF, Typeface.BOLD);  
  
    TableRow.LayoutParams params = new TableRow.LayoutParams();  
    params.span = 6;  
  
    rowTitle.addView(title, params);  
  
    // labels column  
    TextView highsLabel = new TextView(this);  
    highsLabel.setText("Day High");  
    highsLabel.setTypeface(Typeface.DEFAULT_BOLD);  
  
    TextView lowsLabel = new TextView(this);  
    lowsLabel.setText("Day Low");  
    lowsLabel.setTypeface(Typeface.DEFAULT_BOLD);  
  
    TextView conditionsLabel = new TextView(this);  
    conditionsLabel.setText("Conditions");  
    conditionsLabel.setTypeface(Typeface.DEFAULT_BOLD);  
  
    rowDayLabels.addView(empty);  
    rowHighs.addView(highsLabel);  
    rowLows.addView(lowsLabel);  
    rowConditions.addView(conditionsLabel);  
  
    // day 1 column  
    TextView day1Label = new TextView(this);  
    day1Label.setText("Feb 7");  
    day1Label.setTypeface(Typeface.SERIF, Typeface.BOLD);  
  
    TextView day1High = new TextView(this);  
    day1High.setText("28°F");  
    day1High.setGravity(Gravity.CENTER_HORIZONTAL);  
  
    TextView day1Low = new TextView(this);  
    day1Low.setText("15°F");  
    day1Low.setGravity(Gravity.CENTER_HORIZONTAL);  
  
    ImageView day1Conditions = new ImageView(this);  
    day1Conditions.setImageResource(R.drawable.hot);  
  
    rowDayLabels.addView(day1Label);  
    rowHighs.addView(day1High);  
    rowLows.addView(day1Low);  
    rowConditions.addView(day1Conditions);  
  
    // day2 column  
    TextView day2Label = new TextView(this);  
    day2Label.setText("Feb 8");  
    day2Label.setTypeface(Typeface.SERIF, Typeface.BOLD);  
  
    TextView day2High = new TextView(this);  
    day2High.setText("26°F");  
    day2High.setGravity(Gravity.CENTER_HORIZONTAL);  
  
    TextView day2Low = new TextView(this);  
    day2Low.setText("14°F");  
    day2Low.setGravity(Gravity.CENTER_HORIZONTAL);  
  
    ImageView day2Conditions = new ImageView(this);  
    day2Conditions.setImageResource(R.drawable.pt_cloud);  
  
    rowDayLabels.addView(day2Label);  
    rowHighs.addView(day2High);  
    rowLows.addView(day2Low);  
    rowConditions.addView(day2Conditions);  
  
    // day3 column  
    TextView day3Label = new TextView(this);  
    day3Label.setText("Feb 9");  
    day3Label.setTypeface(Typeface.SERIF, Typeface.BOLD);  
  
    TextView day3High = new TextView(this);  
    day3High.setText("23°F");  
    day3High.setGravity(Gravity.CENTER_HORIZONTAL);  
  
    TextView day3Low = new TextView(this);  
    day3Low.setText("3°F");  
    day3Low.setGravity(Gravity.CENTER_HORIZONTAL);  
  
    ImageView day3Conditions = new ImageView(this);  
    day3Conditions.setImageResource(R.drawable.snow);  
  
    rowDayLabels.addView(day3Label);  
    rowHighs.addView(day3High);  
    rowLows.addView(day3Low);  
    rowConditions.addView(day3Conditions);  
  
    // day4 column  
    TextView day4Label = new TextView(this);  
    day4Label.setText("Feb 10");  
    day4Label.setTypeface(Typeface.SERIF, Typeface.BOLD);  
  
    TextView day4High = new TextView(this);  
    day4High.setText("17°F");  
    day4High.setGravity(Gravity.CENTER_HORIZONTAL);  
  
    TextView day4Low = new TextView(this);  
    day4Low.setText("5°F");  
    day4Low.setGravity(Gravity.CENTER_HORIZONTAL);  
  
    ImageView day4Conditions = new ImageView(this);  
    day4Conditions.setImageResource(R.drawable.lt_snow);  
  
    rowDayLabels.addView(day4Label);  
    rowHighs.addView(day4High);  
    rowLows.addView(day4Low);  
    rowConditions.addView(day4Conditions);  
  
    // day5 column  
    TextView day5Label = new TextView(this);  
    day5Label.setText("Feb 11");  
    day5Label.setTypeface(Typeface.SERIF, Typeface.BOLD);  
  
    TextView day5High = new TextView(this);  
    day5High.setText("19°F");  
    day5High.setGravity(Gravity.CENTER_HORIZONTAL);  
  
    TextView day5Low = new TextView(this);  
    day5Low.setText("6°F");  
    day5Low.setGravity(Gravity.CENTER_HORIZONTAL);  
  
    ImageView day5Conditions = new ImageView(this);  
    day5Conditions.setImageResource(R.drawable.pt_sun);  
  
    rowDayLabels.addView(day5Label);  
    rowHighs.addView(day5High);  
    rowLows.addView(day5Low);  
    rowConditions.addView(day5Conditions);  
  
    table.addView(rowTitle);  
    table.addView(rowDayLabels);  
    table.addView(rowHighs);  
    table.addView(rowLows);  
    table.addView(rowConditions);  
  
    setContentView(table);  
  
}  

Let’s take a closer look at the Java code listing above. First we create the TableLayout control and set the shrinkable and stretchable attributes to true for all columns using the setStretchAllColumns() and setShrinkAllColumns() methods. Next, we systematically create five TableRow. Each TableRow will contain view controls (TextView controls for the title, dates, highs and low data as well as ImageView controls for the weather condition graphics). You’ll see how the column span is handled with the first TableRow. Specific columns of views are created, styled, and added, in order, to the appropriate TableRow using the addView() method. Each TableRow is added to the TableLayout control, in order, using the addView() method of the TableLayout. Finally, we load the TableLayout and display it on the screen using the setContentView() method.

As you can see, the code can rapidly grow in size as more controls are added to the screen. For organization and maintainability, defining and using layouts programmatically is best left for the odd case rather than the norm. Additionally, in a case like this, the data would typically be coming from some other source than strings we type in, so a loop may be more appropriate for many applications.

The results are shown in the following figure. As you can see, they are the same as the previous results — as expected.



TableLayout Concerns

Although table layouts can be used to design entire user interfaces, they usually aren’t the best tool for doing so, as they are derived from LinearLayout and not the most efficient of layout controls. If you think about it, a TableLayout is little more than an organized set of nested LinearLayouts, and nesting layouts too deeply is generally discouraged for performance concerns. However, for data that is already in a format suitable for a table, such as spreadsheet data, table layout may be a reasonable choice.

Also, table layout data may vary based upon screen sizes and resolutions. It’s generally a good design practice to ensure you enable scrolling when displaying large quantities of data. For example, if the weather example used earlier also included a “write-up” of the conditions, this text might be one sentence or twenty sentences, so enabling vertical and/or horizontal scrolling would be prudent.

Conclusion

Android application user interfaces are defined using layouts, and table layouts are incredibly handy for displaying view data or controls in rows and columns. Using table layouts where they are appropriate can make many screen designs simpler and faster. However, keep in mind that TableLayout is derived from LinearLayout, and has many of the same performance limitations.

About the Authors

Mobile developers Lauren Darcey and Shane Conder have coauthored several books on Android development: an in-depth programming book entitled Android Wireless Application Development and Sams TeachYourself Android Application Development in 24 Hours. When not writing, they spend their time developing mobile software at their company and providing consulting services. They can be reached at via email to androidwirelessdev+mt@gmail.com, via their blog at androidbook.blogspot.com, and on Twitter@androidwireless.


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值