Android布局

安卓APP(3)——安卓布局控件 阅读详情

  

Android布局  

我们对Android应用程序运行原理及布局文件可谓有了比较深刻的认识和理解,并且用“Hello World!”程序来实践证明了。在继续深入Android开发之旅之前,有必要解决前两篇中没有介绍的遗留问题:View的几种布局显示方法,以后就不会在针对布局方面做过多的介绍。View的布局显示方式有下面几种:线性布局(Linear Layout)、相对布局(Relative Layout)、表格布局(Table Layout)、网格视图(Grid View)、标签布局(Tab Layout)、列表视图(List View)、绝对布局(AbsoluteLayout)。本文虽然是介绍View的布局方式,但不仅仅是这样,其中涉及了很多小的知识点,绝对能给你带来Android大餐!

本文的主要内容就是分别介绍以上视图的七种布局显示方式效果及实现,大纲如下:

  • 1、View布局概述
  • 2、线性布局(Linear Layout)
    • 2.1、Tips:android:layout_weight="1"
  • 3、相对布局(Relative Layout)
  • 4、表格布局(Table Layout)
  • 5、列表视图(List View)
    • 5.1、一个小的改进
    • 5.2、补充说明
  • 6、网格视图(Grid View)
  • 7 、绝对布局()
  • 8、标签布局(Tab Layout)
1、view的布局显示概述

通过前面的学习我们知道:在一个Android应用程序中,用户界面通过View和ViewGroup对象构建。Android中有很多种View和ViewGroup,他们都继承自View类。View对象是Android平台上表示用户界面的基本单元。

View的布局显示方式直接影响用户界面,View的布局方式是指一组View元素如何布局,准确的说是一个ViewGroup中包含的一些View怎么样布局。ViewGroup类是布局(layout)和视图容器(View container)的基类,此类也定义了ViewGroup.LayoutParams类,它作为布局参数的基类,此类告诉父视图其中的子视图想如何显示。例如,XML布局文件中名为layout_something的属性(参加上篇的4.2节)。我们要介绍的View的布局方式的类,都是直接或间接继承自ViewGroup类,如下图所示:

ViewGroup的继承 

图1、继承自ViewGroup的一些布局类

其实,所有的布局方式都可以归类为ViewGroup的5个类别,即ViewGroup的5个直接子类。其它的一些布局都扩展自这5个类。下面分小节分别介绍View的七种布局显示方式。

2、线性布局(Linear Layout)

线性布局:是一个ViewGroup以线性方向显示它的子视图(view)元素,即垂直地或水平地。之前我们的Hello World!程序中view的布局方式就是线性布局的,一定不陌生!如下所示res/layour/main.xml: 

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
              android:layout_width="fill_parent" 
              android:layout_height="fill_parent" 
              android:orientation="horizontal"><!-- have an eye on ! --> 
    <Button android:id="@+id/button1" 
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content"            
            android:text="Hello, I am a Button1" 
            android:layout_weight="1" 
            /> 
    <Button android:id="@+id/button2" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="Hello, I am a Button2" 
    android:layout_weight="1" 
    /> 
    <Button android:id="@+id/button3" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="Hello, I am a Button3" 
    android:layout_weight="1" 
    /> 
    <Button android:id="@+id/button4" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="Hello, I am a Button4" 
    android:layout_weight="1" 
    /> 
    <Button android:id="@+id/button5" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="Hello, I am a Button5" 
    android:layout_weight="1" 
    /> 
</LinearLayout>

从上面可以看出根LinearLayout视图组(ViewGroup)包含5个Button,它的子元素是以线性方式(horizontal,水平的)布局,运行效果如下图所示:

linearlayout1

图2、线性布局(水平或者说是横向)

 

 

如果你在android:orientation="horizontal"设置为vertical,则是是垂直或者说是纵向的,如下图所示:

linearlayout2

 

图3、线性布局(垂直或者说是纵向)

2.1、Tips:android:layout_weight="1"

 这个属性很关键,如果你没有显示设置它,它默认为0。把上面布局文件(水平显示的那个)中的这个属性都去掉,运行会得出如下结果:

linearlayout3

图4、layout_weight属性

没有了这个属性,我们本来定义的5个Button运行后却只显示了2个Button,为什么呢??

"weight"顾名思义是权重的意思,layout_weight 用于给一个线性布局中的诸多视图的重要程度赋值。所有的视图都有一个layout_weight值,默认为零,意思是需要显示多大的视图就占据多大的屏幕空间。这就不难解释为什么会造成上面的情况了:Button1~Button5都设置了layout_height和layout_width属性为wrap_content即包住文字内容,他们都没有设置layout_weight 属性,即默认为0.,这样Button1和Button2根据需要的内容占据了整个屏幕,别的就显示不了啦!

若赋一个高于零的值,则将父视图中的可用空间分割,分割大小具体取决于每一个视图的layout_weight值以及该值在当前屏幕布局的整体layout_weight值和在其它视图屏幕布局的layout_weight值中所占的比率而定。举个例子:比如说我们在 水平方向上有一个文本标签和两个文本编辑元素。该文本标签并无指定layout_weight值,所以它将占据需要提供的最少空间。如果两个文本编辑元素每一个的layout_weight值都设置为1,则两者平分在父视图布局剩余的宽度(因为我们声明这两者的重要度相等)。如果两个文本编辑元素其中第一个的layout_weight值设置为1,而第二个的设置为2,则剩余空间的三分之二分给第一个,三分之一分给第二个(数值越小,重要度越高)。 

3、相对布局(Relative Layout)

相对布局:是一个ViewGroup以相对位置显示它的子视图(view)元素,一个视图可以指定相对于它的兄弟视图的位置(例如在给定视图的左边或者下面)或相对于RelativeLayout的特定区域的位置(例如底部对齐,或中间偏左)。

相对布局是设计用户界面的有力工具,因为它消除了嵌套视图组。如果你发现你使用了多个嵌套的LinearLayout视图组后,你可以考虑使用一个RelativeLayout视图组了。看下面的res/layour/main.xml: 

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent"> 
    <TextView 
        android:id="@+id/label" 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:text="Type here:"/> 
    <EditText 
        android:id="@+id/entry" 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:background="@android:drawable/editbox_background" 
        android:layout_below="@id/label"/><!-- have an eye on ! --> 
    <Button 
        android:id="@+id/ok" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:layout_below="@id/entry"  <!-- have an eye on ! --> 
       android:layout_alignParentRight="true" <!-- have an eye on ! --> 
        android:layout_marginLeft="10dip" 
        android:text="OK" /> 
    <Button 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:layout_toLeftOf="@id/ok" <!-- have an eye on ! --> 
        android:layout_alignTop="@id/ok" <!-- have an eye on ! -->
 
        android:text="Cancel" /> 
</RelativeLayout> 

从上面的布局文件我们知道,RelativeLayout视图组包含一个TextView、一个EditView、两个Button,注意标记了<!-- have an eye on ! -->的属性,在使用相对布局方式中就是使用这些类似的属性来定位视图到你想要的位置,它们的值是你参照的视图的id。这些属性的意思很简单,就是英文单词的直译,就不多做介绍了。运行之后,得如下结果:

relativelayout

图5、相对布局

4、 表格布局(Table Layout)

表格布局:是一个ViewGroup以表格显示它的子视图(view)元素,即行和列标识一个视图的位置。其实Android的表格布局跟HTML中的表格布局非常类似,TableRow 就像HTML表格的<tr>标记。

用表格布局需要知道以下几点:

看下面的res/layour/main.xml: 

<?xml version="1.0" encoding="utf-8"?> 
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android" 
              android:layout_width="fill_parent" 
              android:layout_height="fill_parent" 
              android:shrinkColumns="0,1,2"><!-- have an eye on ! --> 
    <TableRow><!-- row1 --> 
    <Button android:id="@+id/button1" 
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content"            
            android:text="Hello, I am a Button1" 
            android:layout_column="0" 
            /> 
       <Button android:id="@+id/button2" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:text="Hello, I am a Button2" 
     android:layout_column="1" 
     /> 
     </TableRow> 
    <TableRow><!-- row2 --> 
    <Button android:id="@+id/button3" 
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content"            
            android:text="Hello, I am a Button3" 
            android:layout_column="1" 
            /> 
<Button android:id="@+id/button4" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:text="Hello, I am a Button4" 
     android:layout_column="1" 
     /> 
</TableRow> 
<TableRow>    
     <Button android:id="@+id/button5" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:text="Hello, I am a Button5" 
     android:layout_column="2" 
     /> 
</TableRow> 
</TableLayout> 

运行之后可以得出下面的结果:

tablelayout

图6、表格布局

5、列表视图(List View)

列表布局:是一个ViewGroup以列表显示它的子视图(view)元素,列表是可滚动的列表。列表元素通过ListAdapter自动插入到列表。

ListAdapter:扩展自Adapter,它是ListView和数据列表之间的桥梁。ListView可以显示任何包装在ListAdapter中的数据。该类提供两个公有类型的抽象方法:

  1. public abstract boolean  areAllItemsEnabled () :表示ListAdapter中的所有元素是否可激活的?如果返回真,即所有的元素是可选择的即可点击的。
  2. public abstract boolean  isEnabled (int position) :判断指定位置的元素是否可激活的?

下面通过一个例子来,创建一个可滚动的列表,并从一个字符串数组读取列表元素。当一个元素被选择时,显示该元素在列表中的位置的消息。

1)、首先,将res/layour/main.xml的内容置为如下: 

<?xml version="1.0" encoding="utf-8"?> 
<TextView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:padding="10dp" 
    android:textSize="16sp" > 
</TextView>

这样就定义了元素在列表中的布局。

2)、src/skynet.com.cnblogs.www/HelloWorld.Java文件的代码如下:

package skynet.com.cnblogs.www;import android.app.ListActivity;import android.os.Bundle;import android.view.View;import android.widget.AdapterView;import android.widget.ArrayAdapter;import android.widget.ListView;import android.widget.TextView;import android.widget.Toast;import android.widget.AdapterView.OnItemClickListener;public class HelloWorld extends ListActivity  {
    //注意这里Helloworld类不是扩展自Acitvity,而是扩展自ListAcitivty    /** Called when the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setListAdapter(new ArrayAdapter<String>(this, R.layout.main, COUNTRIES));        ListView lv = getListView();        lv.setTextFilterEnabled(true);        lv.setOnItemClickListener(new OnItemClickListener() {          public void onItemClick(AdapterView<?> parent, View view,              int position, long id) {            // When clicked, show a toast with the TextView text            Toast.makeText(getApplicationContext(), ((TextView) view).getText(),                Toast.LENGTH_SHORT).show();          }        });    }    static final String[] COUNTRIES = new String[] {	    "1", "2", "3", "4", "5",	    "6", "7", "8", "9", "10",	    "11", "12", "13", "14", "15",	    "16", "17", "18", "19", "20",	    "21", "22", "23", "24"	  };}

Note:onCreate()函数中并不像往常一样通过setContentView()为活动(Activity)加载布局文件,替代的是通过setListAdapter(ListAdapter)自动添加一个ListView填充整个屏幕的ListActivity。在此文件中这个方法以一个ArrayAdapter为参数:setListAdapter(new ArrayAdapter<String>(this, R.layout.main, COUNTRIES)),这个ArrayAdapter管理填入ListView中的列表元素。ArrayAdapter的构造函数的参数为:this(表示应用程序的上下文context)、表示ListViewde布局文件(这里是R.layout.main)、插入ListView的List对象对数组(这里是COUNTRES)。

setOnItemClickListener(OnItemClickListener)定义了每个元素的点击(on-click)的监听器,当ListView中的元素被点击时,onItemClick()方法被调用,在这里是即一个Toast消息——每个元素的位置将显示。

3)、运行应用程序得如下结果(点击1之后,在下面显示了1):

listview

图7、列表布局

NOTE:如果你改了HelloWorld extends ListActivity 而不是Activity之后,运行程序是提示:“Conversion to Dalvik format failed with error 1”。可以这么解决:解决办法是 Project > Clean... > Clean project selected below > Ok

5.1、一个小的改进

上面我们是把要填充到ListView中的元素硬编码到HelloWorld.java文件中,这样就缺乏灵活性!也不符合推荐的应用程序的界面与控制它行为的代码更好地分离的准则!

其实我们可以把要填充到ListView的元素写到res/values/strings.xml文件中的<string-array>元素中,然后再源码中动态地读取。这样strings.xml的内容类似下面:

<?xml version="1.0" encoding="utf-8"?><resources>    <string-array name="countries_array">        <item>1</item>        <item>2</item>        <item>3</item>        <item>4</item>        <item>5</item>        <item>6</item>        <item>7</item>    </string-array></resources>

然而HelloWorld.java文件中的onCreate()函数,则这样动态访问这个数组及填充到ListVies: 

String[] countries = getResources().getStringArray(R.array.countries_array); 
setListAdapter(new ArrayAdapter<String>(this, R.layout.list_item, countries));

5.2、补充说明

首先总结一下列表布局的关键部分:

  • 布局文件中定义ListView
  • Adapter用来将数据填充到ListView
  • 要填充到ListView的数据,这些数据可以字符串、图片、控件等等

其中Adapter是ListView和数据源之间的桥梁,根据数据源的不同Adapter可以分为三类:

  • String[]: ArrayAdapter
  • List<Map<String,?>>: SimpleAdapter
  • 数据库Cursor: SimpleCursorAdapter

使用ArrayAdapter(数组适配器)顾名思义,需要把数据放入一个数组以便显示,上面的例子就是这样的;SimpleAdapter能定义各种各样的布局出来,可以放上ImageView(图片),还可以放上Button(按钮),CheckBox(复选框)等等;SimpleCursorAdapter是和数据库有关的东西。篇幅有限后面两种就不举例实践了。你可以参考android ListView详解orArrayAdapter ,SimpleAdapter ,SimpleCursorAdapter 区别。

6、网格视图(Grid View)

网格布局:是一个ViewGroup以网格显示它的子视图(view)元素,即二维的、滚动的网格。网格元素通过ListAdapter自动插入到网格。ListAdapter跟上面的列表布局是一样的,这里就不重复累述了。

下面也通过一个例子来,创建一个显示图片缩略图的网格。当一个元素被选择时,显示该元素在列表中的位置的消息。

1)、首先,将上面实践截取的图片放入res/drawable/

2)、res/layour/main.xml的内容置为如下:这个GridView填满整个屏幕,而且它的属性都很好理解,按英文单词的意思就对了。

<?xml version="1.0" encoding="utf-8"?><GridView xmlns:android="http://schemas.android.com/apk/res/android"     android:id="@+id/gridview"    android:layout_width="fill_parent"     android:layout_height="fill_parent"    android:columnWidth="90dp"    android:numColumns="auto_fit"    android:verticalSpacing="10dp"    android:horizontalSpacing="10dp"    android:stretchMode="columnWidth"    android:gravity="center"/>

3)、然后,HelloWorld.java文件中onCreate()函数如下:

    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);        GridView gridview = (GridView) findViewById(R.id.gridview);        gridview.setAdapter(new ImageAdapter(this));        gridview.setOnItemClickListener(new OnItemClickListener() {            public void onItemClick(AdapterView<?> parent, View v, int position, long id) {                Toast.makeText(HelloWorld.this, " " + position, Toast.LENGTH_SHORT).show();            }        });    } 

 

onCreate()函数跟通常一样,首先调用超类的onCreate()函数函数,然后通过setContentView()为活动(Activity)加载布局文件。紧接着是,通过GridView的id获取布局文件中的gridview,然后调用它的setListAdapter(ListAdapter)函数填充它,它的参数是一个我们自定义的ImageAdapter。后面的工作跟列表布局中一样,为监听网格中的元素被点击的事件而做的工作。

4)、实现我们自定义ImageAdapter,新添加一个类文件,它的代码如下:

package skynet.com.cnblogs.www;import android.content.Context;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.GridView;import android.widget.ImageView;public class ImageAdapter extends BaseAdapter {    private Context mContext;    public ImageAdapter(Context c) {        mContext = c;    }    public int getCount() {        return mThumbIds.length;    }    public Object getItem(int position) {        return null;    }    public long getItemId(int position) {        return 0;    }    // create a new ImageView for each item referenced by the Adapter    public View getView(int position, View convertView, ViewGroup parent) {        ImageView imageView;        if (convertView == null) {  // if it's not recycled, initialize some attributes            imageView = new ImageView(mContext);            imageView.setLayoutParams(new GridView.LayoutParams(85, 85));            imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);            imageView.setPadding(8, 8, 8, 8);        } else {            imageView = (ImageView) convertView;        }        imageView.setImageResource(mThumbIds[position]);        return imageView;    }    // references to our images    private Integer[] mThumbIds = {            R.drawable.linearlayout1, R.drawable.linearlayout2,            R.drawable.linearlayout3, R.drawable.listview,            R.drawable.relativelayout, R.drawable.tablelayout    };}

 

 

 

ImageAdapter类扩展自BaseAdapter,所以首先得实现它所要求必须实现的方法。构造函数和getcount()函数很好理解,而getItem(int)应该返回实际对象在适配器中的特定位置,但是这里我们不需要。类似地,getItemId(int)应该返回元素的行号,但是这里也不需要。

这里重点要介绍的是getView()方法,它为每个要添加到ImageAdapter的图片都创建了一个新的View。当调用这个方法时,一个View是循环再用的,因此要确认对象是否为空。如果是空的话,一个ImageView就被实例化且配置想要的显示属性:

如果View传到getView()不是空的,则本地的ImageView初始化时将循环再用View对象。在getView()方法末尾,position整数传入setImageResource()方法以从mThumbIds数组中选择图片。

运行程序会得到如下结果(点击第一张图片之后):

gridviewlayout

图8、网格布局

7、绝对布局(AbsoluteLayout)

绝对布局:是一个ViewGroup以绝对方式显示它的子视图(view)元素,即以坐标的方式来定位在屏幕上位置。

这种布局方式很好理解,在布局文件或编程地设置View的坐标,从而绝对地定位。如下所示布局文件:

<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/AbsoluteLayout01"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    >   <TextView android:id="@+id/txtIntro"     android:text="绝对布局"     android:layout_width="fill_parent"     android:layout_height="wrap_content"     android:layout_x="20dip"<!-- have an eye on ! -->     android:layout_y="20dip"><!-- have an eye on ! -->   </TextView></AbsoluteLayout>

 

简单吧,这里不在深入了!

8、标签布局(Tab Layout)

标签布局:是一个ViewGroup以标签的方式显示它的子视图(view)元素,就像在Firefox中的一个窗口中显示多个网页一样。

为了狂创建一个标签UI(tabbed UI),需要使用到TabHost和TabWidget。TabHost必须是布局的根节点,它包含为了显示标签的TabWidget和显示标签内容的FrameLayout。

可以有两种方式实现标签内容:使用标签在同一个活动中交换视图、使用标签在完全隔离的活动之间改变。根据你的需要,选择不同的方式,但是如果每个标签提供不同的用户活动,为每个标签选择隔离的活动,因此你可以更好地以分离的组管理应用程序,而不是一个巨大的应用程序和布局。下面还有一个例子来创建一个标签UI,每个标签使用隔离的活动。

1)、在项目中建立三个隔离的Activity类:ArtistisActivity、AlbumActivity、SongActivity。它们每个表示一个分隔的标签。每个通过TextView显示简单的一个消息,例如:

public class ArtistsActivity extends Activity {    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        TextView textview = new TextView(this);        textview.setText("This is the Artists tab");        setContentView(textview);    }}

 

其它两个类也类似。

2)、设置每个标签的图标,每个图标应该有两个版本:一个是选中时的,一个是未选中时的。通常的设计建议是,选中的图标应该是深色(灰色),未选中的图标是浅色(白色)。

现在创建一个state-list drawable指定哪个图标表示标签的状态:将图片放到res/drawable目录下并创建一个新的XML文件命名为ic_tab_artists.xml,内容如下:

<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android">    <!-- When selected, use grey -->    <item android:drawable="@drawable/ic_tab_artists_grey"          android:state_selected="true" />    <!-- When not selected, use white-->    <item android:drawable="@drawable/ic_tab_artists_white" /></selector>

 

3)、res/layour/main.xml的内容置为如下:

<?xml version="1.0" encoding="utf-8"?><TabHost xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@android:id/tabhost"    android:layout_width="fill_parent"    android:layout_height="fill_parent">    <LinearLayout        android:orientation="vertical"        android:layout_width="fill_parent"        android:layout_height="fill_parent"        android:padding="5dp">        <TabWidget            android:id="@android:id/tabs"            android:layout_width="fill_parent"            android:layout_height="wrap_content" />        <FrameLayout            android:id="@android:id/tabcontent"            android:layout_width="fill_parent"            android:layout_height="fill_parent"            android:padding="5dp" />    </LinearLayout></TabHost>

 

这个布局将显示标签和提供上面创建的活动之间的导航。TabHost要求包含一个TabWidget和一个FrameLayout。TabWidget和FrameLayoutTabHost以线性垂直地显示。

4)、HelloWorld.java文件源码如下:

package skynet.com.cnblogs.www;import android.widget.TabHost;import android.app.TabActivity;import android.content.Intent;import android.content.res.Resources;import android.os.Bundle;public class HelloWorld extends TabActivity{    /** Called when the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);        Resources res = getResources(); // Resource object to get Drawables        TabHost tabHost = getTabHost();  // The activity TabHost        TabHost.TabSpec spec;  // Resusable TabSpec for each tab        Intent intent;  // Reusable Intent for each tab        // Create an Intent to launch an Activity for the tab (to be reused)        intent = new Intent().setClass(this, ArtistsActivity.class);        // Initialize a TabSpec for each tab and add it to the TabHost        spec = tabHost.newTabSpec("artists").setIndicator("Artists",                          res.getDrawable(R.drawable.ic_tab_artists))                      .setContent(intent);        tabHost.addTab(spec);        // Do the same for the other tabs        intent = new Intent().setClass(this, AlbumsActivity.class);        spec = tabHost.newTabSpec("albums").setIndicator("Albums",                          res.getDrawable(R.drawable.ic_tab_artists))                      .setContent(intent);        tabHost.addTab(spec);        intent = new Intent().setClass(this, SongsActivity.class);        spec = tabHost.newTabSpec("songs").setIndicator("Songs",                          res.getDrawable(R.drawable.ic_tab_artists))                      .setContent(intent);        tabHost.addTab(spec);        tabHost.setCurrentTab(2);    }}

 

 

 

设置每个标签的文字和图标,并分配每个标签一个活动(这里为了方便三个标签都有相同的图标)。TabHost的引用第一次通过getTabHost()获取。然后,为每个标签,创建TabHost.TabSpec定义标签的属性。newTabSpec(String)方法创建一个新的TabHost.TabSpec以给定的字符串标识标签。调用TabHost.TabSpec, setIndicator(CharSequence, Drawable)为每个标签设置文字和图标,调用setContent(Intent)指定Intent去打开合适的活动。每个TabHost.TabSpec通过调用addTab(TabHost.TabSpec)添加到TabHost。

最后,setCurrentTab(int)设置打开默认显示的标签,通过索引标签的位置。

5)、打开Android的清单文件AndroidManifest.xml,添加NoTitleBar主题到HelloWorld的<activity>标记。这将移除默认应用程序的标题和顶端布局,给标签腾出位置。<activity>标记应该像这样:

        <activity android:name=".HelloWorld"                  android:label="@string/app_name"                  android:theme="@android:style/Theme.NoTitleBar">

 

你运行这个程序能够得到什么结果呢?请自行检查。不过我在这里告诉你很有可能会运行不了,报“java.lang.NullPointerException”错!我想运行这个例子的很多人都会有这个问题,不信你试试!

PS:其实这也算是Android的一个bug,而且这个bug在2.2中还没有解决,这个问题全球N多人都碰到了,并在http://code.google.com/p/android/issues中挂号了,相关问题的编号有不止一个。

接着往下看……

如果你看了我这篇文章,你一定会是个幸运儿!经过我艰苦的调试+找资料,我找到了解决方法:

在清单文件AndroidManifest.xml,添加下面三个Activity: 

<activity android:name=".AlbumsActivity"  android:label="@string/app_name"></activity> 
<activity android:name=".ArtistsActivity" android:label="@string/app_name"></


vivado安装空间与依赖要求:入门须知要点 准备安装Vivado时,需重点关注系统空间和依赖环境的配置。结合vivado安装教程,详细说明最低磁盘要求、内存配置及操作系统兼容性,帮助新手快速搭建开发环境,避免常见安装失败问题。 阅读详情

相关推荐

系统安装、qt配置、安装pcie驱动

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 安装Linux系统指定:ununtu20.04并配置相关软件环境 前言 提示:这里可以添加本文要记录的大概内容: ununtu20.04、Qt 5.9.0、pcie驱动 提示:以下是本篇文章正文内容,下面案例可供参考 一、安装系统 制作系统盘(win10),在开机时按相应键进入BIOS,(华硕需要先改配置启动->CSM->开启->第一个选项选第一个或第二个),等待即可 进入后按照https://www.sysgeek.

weixin_44832804的博客 2204

Android 开发之旅:view的几种布局方式及实践

引言 通过前面两篇: Android 开发之旅:又见Hello World! Android 开发之旅:深入分析布局文件&又是“Hello World!” 我们对Android应用程序运行原理及布局文件可谓有了比较深刻的认识和理解,并且用“Hello World!”程序来实践证明了。在继续深入Android开发之旅之前,有必要解决前两篇中没有介绍的遗留问题:View的几种布局显示方法,以后就不会在针对布局方面做过多的介绍。View的布局显示方式有下面几种:线性布局(Linear La

吴秦 6115

解决RocketMQ中@Bean配置DefaultMQProducer时的MQClientException问题

本文针对Spring Boot整合RocketMQ时,因在@Bean配置中手动调用DefaultMQProducer的start()方法而引发的MQClientException问题,深入剖析了其根本原因在于生命周期管理冲突。文章提供了简洁有效的解决方案——移除手动启动,让Spring容器自动管理,并给出了完整的配置示例与生产环境最佳实践。

rnn9storyteller的博客 688

View的布局详解(三种方法)

UIView提供了用来通知系统某个view布局发生变化的方法,也提供了在view布局重新计算后调用的可重写的方法。当一个视图“认为”应该重新布局自己的子控件时,它便会自动调用自己的layoutSubviews方法,在该方法中“刷新”子控件的布局。使用setNeedsLayout()方法,不会立刻更新布局,而是在下一个run loop中将带有“标记”的视图更新,此时调用。当你“马上”,“立刻”需要刷新布局的时候调用,这时候会立刻调用。

ScheenDuan的博客 645

TCS34725颜色识别模块实战调校:从“一坨”例程到精准RGB

本文针对TCS34725颜色识别模块初始数据不准的问题,提供了从基础例程到精准调校的实战指南。核心在于通过白光校正与黑白光校正两种方法,补偿传感器偏差与环境光影响,将原始数据准确映射为标准RGB值。文章详细阐述了校准原理、操作步骤与代码实现,并分享了进阶调试技巧与避坑指南,帮助开发者显著提升颜色识别的准确性与项目可靠性。

weixin_29188043的博客 287

嵌入式环境下XML配置文件解析实践

在资源受限的嵌入式环境中,如何轻量级地解析XML配置文件成为关键。通过简化语法结构与优化内存使用,实现快速读取和解析配置文件,提升系统启动效率与稳定性。

weixin_31869917的博客 398

多个view横向排列的便捷方法

多个view横向排列的便捷方法 在写自适应div( web端 )或view(微信端)的布局时,可以用以下俩种方法进行便捷布局 : 利用外层div或外层view的display : flex ; flex-flow : row; 利用外层div或外层view的white-space:nowrap;属性 white-space属性值 normal 默认。空白会被浏览器忽略。 pre 空白会被浏览器保留。其行为方式类似 wxml中的标签。 nowrap 文本不会换行,文本会在在同一行上继续,直到遇到 标签为止。

MarryLinDa的博客 2314

硬核拆解华为/大疆/小米硬件面试真题:手撕电路+考点思维导图(附答案)

设计一个增益为20dB、带宽≥100kHz的同相放大器,电源电压±5V,要求输出摆幅≥8V。12位ADC的参考电压2.5V,输入信号1kHz正弦波,峰峰值2V。输入24V转5V/10A的同步降压电路,开关频率500kHz,计算MOSFET的损耗并选择型号(需提供TI官网截图)。设计无人机图传系统,要求1080P@30fps,传输距离2km。FPGA设计中,100MHz时钟域到50MHz时钟域传输32位数据,给出同步方案并画时序图。“设计一个输入12V、输出5V/3A的同步降压电路,给出关键参数计算”

qq_63103361的博客 3534

View&五大布局介绍

一:UI视图结构 什么是View     这个类是用户接口的基础构件。 View 表示屏幕上的一块矩形区域,负责绘制这个区域和事件处理。     View 是所有widget类的基类,Widget 类用于创建交互式UI构件(按钮,输入框等)。     View 类的ViewGroup子类是layout 的基类,Layout是一个不可见的容器,它保存着View(或ViewGroup)并定

九天的学习历程 4564

深入URP之Shader篇1: URP Shader概述

我们知道,URP和HDRP都是基于SRP的,尽管现在可以使用Shader Graph编写Shader,但是手写Shader仍然是有一定的优势,特别是在性能方面,手写Shader可以更极致的优化,因此我们在项目中前期都是直接使用Shader Graph编写Shader,项目后期会改成手写Shader来提高性能。而在SRP中手写Shader,我们仍然使用的是Shader Lab,这个结构并没有太大的变化,但是SRP Shader中使用Shader Lab语言还是有几点不同。

聚焦游戏和图形引擎开发技术 4637

uniapp - 超详细的 H5 公众号网页微信登录示例代码,提供从 0-1 公众号配置及详细注释代码(站在新手小白的角度)第三方微信授权登录的实现!!

uniapp微信浏览器H5授权微信登录,UniApp开发H5接入微信登录的全过程,uniapp的H5页面使用微信登录,uniapp H5微信授权登录,H5之微信授权登陆 (uniapp网页版微信授权登录),uni-app开发H5第三方微信授权登录的实现,uniapp如何实现微信授权登录,公众号H5页面接入微信登录流程,uni-app - 最详细 H5 网页接入微信登录功能,提供公众号配置与详细注释示例代码(移动端网页实现点击登录按钮后 调用微信公众号授权登录功能 详细讲解接入流程与详细示例代码)官方最新超级

✅ 精选推荐文章 1万+

小程序view基本组件使用

适合小程序小白使用

weixin_51330376的博客 2922

手把手教你新建一个winform项目(史上最全)

本文介绍如何利用visual studio新建一个winform程序

qq_34059233的博客 4万+

安卓前端布局Android,Android开发的几种常见布局

目前正在从事iOS开发,对于安卓就是大学的时候自学了点,做过几个小的项目,软件外包大赛、计算机设计大赛、移动应用大赛都拿过奖项,呵呵。。。现在回想起来以前大学做的安卓比赛是多么的幼稚。 从现在开始我要从头一步一步回顾安卓,作为一个前端开发工程师要崛起了。。。。哈哈。。。请大家支持的我创作,多提提宝贵的意见。步入正题!!!!!!!关于Android的几种常见的布局其实很简单的,是一个入门的关键。主要...

weixin_35064201的博客 430

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

【Android】安卓六大布局基本了解

Android六种布局: 1. 线性布局(LinearLayout) 按照垂直或者水平方向布局的组件 2. 帧布局(FrameLayout) 组件从屏幕左上方布局组件 3. 表格布局(TableLayout) 按照行列方式布局组件 4. 绝对布局(AbsoluteLa...

Healer 3285

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

安卓Android 架构模式及UI布局设计

界面设计与程序逻辑分离:有利于并行安卓中的架构模式 **优势:** 1. 设计可扩展的应用程序,方便进行未来的更改和更新。 2. 实现模块化设计,提高代码质量,便于测试和维护。开发,后期修改界面时不需修改程序逻辑代码。设计模式MVC、MVP、MVVM

m0_74154295的博客 3918

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Android 的各种布局(初识安卓!)

初识定位

HumanAwake的博客 1954

【Android】安卓开发常用的布局

前言布局是安卓开发中很基础的部分,作为移动开发的初学者,我也在不断的学习进步中~正文文件的位置一般都在layout文件夹内。一个布局文件,一般对应一个Activity,在代码中通过setContentView(R.layout.first_layout);将页面跟逻辑关联起来布局的分类常见的布局LinearLayout,线性布局方式 一种使用单个水平行或垂直行来组织子项的布局。它会在窗口长度超出

Code Metaverse 4663

Android:安卓布局分类及布局和页面的关系

布局有多少种? 其实安卓有六大基本布局 View 被 ViewGroup继承,View是组件 View:是绘制在屏幕上的用户能与之交互的一个对象 ViewGroup:是一个用于存放其他view(和viewGroup)对象的布局容器 所谓的布局就是说:我们如何把很多的组件放在画布上,进行描述,绘画,画布有不同的玩法和规则 分为:Absolute Layout FrameLayout Linealayout Tabl...

m0_57089315的博客 1125

Android 安卓 基本 布局

水平布局宽为0,垂直布局高为0. 代码案例: <?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:layou

m0_70083038的博客 324

【Android】安卓中的布局与事件

【Android】安卓开发中的布局与事件 1、Android Studio下载配置 非常简单的百度然后点击下载安装就好了。注意的是,本来我是打算使用评价还不错的Genymotion这个软件来充当虚拟机的,捆版下载VirtualBox先不说,安装了之后还报错无法启动,找了一下午也未解决,最后导致VirtualBox还卸载不了,搞得人头大,所以最终使用了AS自带的虚拟机。 如何配置虚拟机呢,为了不让他下载到C盘,需要改一个环境变量 ANDROID_SDK_HOME D:\Environment\Android\

woodwhale的博客 921

Android安卓——UI布局

安卓应用在用户面前所呈现出来的就是一个布局方式。 一、页面布局概述1、界面布局(Layout)是用户界面结构的描述,定义了界面中所有的元素、结构和相互关系 2、声明Android程序的界面布局有两种方法 1)、使用XML文件描述界面布局 2)、在程序运行时动态添加或修改界面布局 3、用户既可以独立使用任何一种声明界面布局的方式,也可以同时使用两种方式 4、使用XML文件声明界面

Deniece_X的博客 1062

android 安卓布局,安卓(android)六大布局详解

线性布局:(LinearLayout)layout_width:fill_parent;match_parent;wrap_contentlayout_height:layout_weight:如果设置成wrap_content,权重越大得到越大如果设置成fill_parent,权重越大得到越小orientation:horizontal,vertical(垂直)gravity:子空间或者显示内容...

weixin_32171133的博客 223

android 界面布局教程,安卓页面布局技巧

安卓布局技巧1.include2.最外层为FrameLayout以及不用考虑background时使用merge(合并)3.用TextView同时显示图片和文字xml: drawableTop、drawableLeft.....代码:setCompoundDrawables(Drawable left, Drawable top, Drawable right, Drawable bottom)4...

weixin_31968223的博客 854

android linearlayout布局,初识安卓之LinearLayout线性布局

0.前言在安卓的多种布局方式中,LinearLayout(线性布局)和RelativeLayout(相对布局)算是最为常用的两种方式了,这里只讲解线性布局,随后将会更新相对布局的相关知识。1.常用属性下面列出几种之后可能会用到LinearLayout中的属性,遗忘时查询即可。属性名意义orientation布局方式,有horizontal(水平布局)和vertical(垂直布局)两种方式id组件名...

weixin_29098391的博客 521

安卓系列课程跟我学Android之六 布局

本章内容 第1节 线性布局 第2节 相对布局 第3节 帧布局 第4节 表格布局 第5节 网格布局 线性布局 线性布局使用标签进行配置,对应代码中的类是android.widget.LinearLayout,线性布局分为水平和垂直两种方向。 线性布局的常用属性如下: android:orienta

张晨光老师的播客 4031
上一篇: Android学习笔记(二)
下一篇: Android开发EditText属性
轻鸿飘羽
博客等级 码龄16年 124粉丝 74原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值