应用程序的用户界面就是用户能看到并能够与它交互的任何东西。Android提供多种预置的UI组件,如结构化布局对象和容许你为应用程序建立图形用户界面的UI控件。Android也会为特殊的接口提供其余UI模块,如对话框,通知和菜单。在一个Android应用中,全部用户界面元素都是由View和ViewGroup对象建立的。View 是一种能够在屏幕上绘制某种画面而且能够与用户互动的对象。ViewGroup对象则是为了定义布局的接口而保存其余View(和ViewGroup)对象。Android提供一个View和ViewGroup子类的集合,这个集合能为你提供相同的输入控制(例如按钮和文本框)和各类各样的布局模式(例如一个线性或者相对布局)html
对应用程序的每一个组件来讲,用户界面都是由View对象和ViewGroup对象的层次结构来定义的,如图1-1所示。每个view group都是用来组织子view的一个不可见容器,然而子 views多是输入控制UI或者绘制UI某些部分的其余widgets。这个树形结构能够根据你的须要简单化或复杂化。(可是对于性能来讲简单最好)java
图1-1 定义UI布局的view层次结构图android
为了声明你的布局,你能够在代码中实例化View对象而后启动构建树,但定义布局最容易、最有效的方法是利用XML文件。XML文件能够为布局提供一个可读结构,这与HTML文件类似。一个View的XML节点名称与它表明的Android类相对应。因此UI里的一个<TextView>节点会建立一个TextView widget,一个<LinearLayout>节点会建立一个LinearLayout view group。例如,包含一个文本视图和一个按钮的简单纵向布局,正如代码清单1-1所示:web
<?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="vertical" > <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="I am a TextView" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="I am a Button" /> </LinearLayout>
代码清单1-1数据库
当你在应用程序中载入一个布局资源时,Android会初始化每一个进入到正运行对象的布局节点,这时你能够用它来定义附加行为,查询对象状态,或修改布局。数组
你不须要用View和ViewGroup对象来构建你全部的UI。Android系统提供了几个标准UI布局的应用程序组件,所以你只须要定义内容。这些应用程序组件都有一组惟一的API,如Action Bar,Dialogs,和Status Notifications,这些都会在他们各自的文档中被一一介绍。异步
布局为用户界面定义了一个可视化结构。能够用两种方式声明一个布局:ide
◆在XML中声明UI元素函数
Android提供了简单的XML元素,它的元素名字与View类以及子类对应,就像布局和widgets同样。工具
◆在运行时动态实例化布局元素
使用代码建立布局元素(而且操做他们的属性)
Android提供了很是灵活的方法来声明和管理应用UI。例如,能够先在XML中声明默认布局,屏幕元素会根据它们的属性显示。接下来能够在应用中添加代码来修改屏幕对象的状态,也能够在运行时修改在XML中声明的对象。 在XML中声明UI的好处是,能够更好地区分显示和控制这些行为的代码。UI描述与应用代码无关,也就是说能够修改和调整XML中的UI布局可是不用修改源java代码。例如,可以为不一样的屏幕目标、不用的设备屏幕大小、不一样的语言建立不一样的XML布局文件。另外,在XML中声明布局使得UI更容易可视化,这样更容易调试界面。本章主要用于教会你如何在xml中声明布局。若是你对运行时动态建立布局感兴趣,那么请参考viewgroup以及view类说明。 通常来讲,xml声明UI元素的词汇和类的命名以及方法名密切相关,元素根据类名、属性名根据方法名来命名。实际上,能猜到什么XML属性对应一个类的方法, 或者可以猜到哪一个类对应给定的XML元素,这每每是直接的对应。可是,注意并非全部的词汇都是等同的。在某些状况下,有的命名有些许不一样。例如,EditText元素有个text属性对应EditText.setText()方法。
使用android的XML词汇,能够快速的设计UI布局和它们包含的屏幕元素。跟建立web页面使用html相似(一系列的嵌套)。 每个布局文件必须包含一个根节点。这个根节点必须是一个View 或者ViewGroup对象。一旦你定义了根节点,能够添加任意的布局对象或者widgets做为子元素,逐步构建一个View层次布局。例如,这是一个XML布局文件使用了纵向的线性布局(LinearLayout)来排列一个TextView和Button,如代码清单1-2所示:
<?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="vertical" > <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello, I am a TextView" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello, I am a Button" /> </LinearLayout>
代码清单1-2
这个文件应该是在当前android工程/res/layout/目录下.xml的扩展名来保存这个文件,这样才会正确编译。咱们接下来会讨论这里显示的每一个属性。
当编译应用程序的时候,每个XML布局文件都被编译到view资源中。应该在Activity.onCreate()回调方法中实现加载布局资源。经过调用setContentView()来设置布局资源(按照R.layout.layout_file_name的格式)。例如,若是你的XML布局文件被保存为main_layout.xml,那么能够在activity中这样加载,如代码清单1-3所示:
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main_layout); }
代码清单1-3
每个View和ViewGroup对象支持他们各自的XML属性。有些属性是特定的View对象(例如,TextView支持textSize属性)可是只要继承这个类,这些属性也能够在其余地方使用。有些属性是对全部的的View对象都适用的,由于它们是从最原始抽象的View类继承下来的(像id属性)。其它的属性被认为是布局参数,比较容易的理解是这样的,ViewGroup表明布局,View表明布局中的元素(好比Button之类),可是ViewGroup是继承自View的,因此你能够理解为,一切皆View。
1.6.1 ID
每个View对象均可能有一个int型的ID和它相关,这是在树中View对象的惟一标识。当程序编译完,这个ID就是一个引用,可是ID属性在XML布局文件里面是经过string类型赋值的。下面让咱们看一下XML中如何定义一个View对象的ID:
android:id="@+id/my_button"
这个@符号在字符串开头代表xml解析器会解析和扩展剩余的ID字符串,并把它定义为ID资源。“+”表示这是一个新的资源名字,要建立而且增长的咱们的资源中(在R.java文件里)。Android framework层也提供了一部分ID资源。若是直接使用android 资源ID的话,你不须要”+”,可是要加上android包名命名空间,以下所示:
android:id="@android:id/empty"
Android的包命名空间中,咱们如今引用android.R资源类的ID,而不是本地的资源类中引用。 为了建立views,并在应用中使用,经常使用的流程以下:
1.在布局文件中建立view/widget,并为他们分配一个惟一的ID
<Button android:id="@+id/my_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/my_button_text"/>
2.接下来在代码中建立view对象实例,从布局中找到它(通常在OnCreate()方法中)
Button myButton = (Button) findViewById(R.id.my_button);
若是是在相对布局(RelativeLayout)中的话定义好ID是很是重要的。由于它们的布局定义就是须要依赖ID。一个ID在整个树中不必定要求惟一,可是你搜索的部分树应该是惟一的(常常是整个树,因此最好的办法是在整个树中是惟一的)尽可能让你的ID全局惟一。
1.6.1布局参数
XML布局属性命名为layout_something 的文件,在其所在的视图组中定义了合适的view的布局参数。
每个ViewGroup类都是继承了Viewgroup.LayoutParams。通常子类使用父类的布局参数,刚开始也许有些难理解,让咱们看下图1-2::
图1-2 带布局参数的View层级
每个布局参数子类拥有本身的语法赋值。每个子元素必须根据父元素来定义恰当的布局参数,尽管父元素也为它的子元素定义了不一样的布局参数。全部的ViewGroup包含宽度和高度,每个View都要定义这两个属性。许多布局参数也包含可选边距。宽度和高度可使用精确的测量工具,但通常不这么作。每每,会使用这些常量来设置宽度和高度。
◆wrap_content会根据内容自动调整视图到合适的大小(就是内容多大,宽高就多大)。
◆fill_parent会告诉你的View变成和父ViewGroup的范围同样大。
通常说来,不推荐使用用绝对单位像是像素来指定布局的宽度和高度。而使用相对的测量工具像是与密度无关的单位(dp),wrap_content,或者fill_parent是一种较好的方法,由于它可以保证您的应用程序在不一样屏幕大小的设备上都可以正常显示。
一个View的几何形状是一个矩形。一个View有一个坐标、用left和top参数,和两个表示宽高尺寸的参数表示,你能够理解为一个左上角的点,和根据这个点的宽高就是一个矩形了。坐标和尺寸的单位是像素。调用getLeft()和getTop()方法可以获得视图的坐标。前者返回left、或者X轴的坐标。后者返回top,或者Y轴坐标。这些方法都返回的View坐标是相对于父视图的坐标。好比,若是getLeft()返回20,这表示当前视图在父视图左侧边缘向右20个像素的地方。另外,提供了许多便利的方法避免了没必要要的计算,像是getRight()和getBottom()这些方法返回视图矩形的右侧和底侧边缘。例如,调用getRight()和进行这个计算是同样的:getLeft()+getWidth()。
View大小是使用宽度和高度表示的。一个View实际上有两对宽高值。第一对是测量获得的宽度和高度。这些尺寸定义了一个View想在父类中占多大。测量尺寸可以经过调用getMeasuredWidth()和getMeasuredHeight()获得。第二对被简单的成为宽度和高度,有时成为绘制的宽度和高度。这些尺寸定义了在绘制时和布局后视图在屏幕上的实际大小。它或许和测量获得的宽度和高度不一样。这些参数可以经过调用getWidth()和getHeight()获得。
为了测量尺寸,须要考虑padding。padding 表示View的左侧、上侧、右侧和下侧部分。padding可以用来偏移视图中的内容、经过指定必定数量的像素。好比,左侧padding是2,会让视图内容偏移视图左边缘2个像素。padding可以经过使用i setPadding(int,int,int,int)方法进行设置,调用getPaddingLeft(),getPaddingTop(),getPaddingRight()和getPaddingBottom()进行查询。尽管View可以定义padding,它不提供任何margins的支持。只有view group提供了这样的支持。
ViewGroup的每一个子类提供了惟一的方法来显示View,接下来是在Android 平台经常使用一些的布局类型。 注意:虽然为了UI设计,能够在一个布局里面放置一个或者多个布局,可是应该力求让布局层次尽量的少。这样性能更高若是视图层次不多会绘制的很快(一个广度视图层次比深度层次视图好不少)
线性布局:这个布局是让其孩子组织成一个单一的水平或垂直行。若是窗口长度超出了屏幕,它会自动建立滚动条。
相对布局:让你可以指定子对象之间的相对位置(孩子A在孩子B的左侧)或者和父对象之间的相对位置(和父对象顶端对齐)
页面视图:显示web页面
若是布局是动态的或者非预约义的,能够在运行时使用一个布局子类AdapterView来填充布局。AdapterView类的子类使用一个适配器将数据绑定到它的布局。适配器表现为数据源和AdapterView布局之间的中间人-适配器检索数据(从像是数组或者数据库查询这样的数据源)并将它转换成能够添加到AdapterView布局视图中的条目。通用的适配器布局包括:
List View:显示滚动的列的列表
Grid View:显示滚动的网格的行和列
1.10.1用数据填充适配器布局
能够填充一个AdapterView,如ListView和GridView,经过将AdapterView实例绑定到一个适配器上,这个适配器从外部数据源检索数据并为每一个数据条目建立一个布局。 Android提供了许多适配器子类用来检索各类各样的数据并为AdapterView构建布局。最经常使用的通用适配器是:
1. ArrayAdapter
当数据源是数组的时候,就可使用这个适配器。默认状况下,ArrayAdapter为每一个数组元素建立一个布局,经过在每一个元素调用toString()后,将数据存放在TextView里面。
例如,若是您想将一个字符串数组显示在ListView中,使用构造器为每一个字符串和字符串数组指定布局初始化一个ArrayAdapter,如代码清单1-4所示:
ArrayAdapter adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, myStringArray);
代码清单1-4
构造器参数:
◆应用程序Context
◆一个针对字符串数组中的字符串都有一个TextView的布局
◆字符串数组
而后只须要在ListView上调用SetAdapter(),如代码清单2-5所示:
ListView listView = (ListView) findViewById(R.id.listview);
listView.setAdapter(adapter);
代码清单2-5
为了调整元素外观,你能够为了数组中的对象重写toString()函数。或者,为每一个元素建立非TextView的视图(好比,想获取每一个数组元素的ImageView)扩展AdapterArray,重写getView()方法返回想要的View类型。
2. SimpleCursorAdapter
当数据来源是Cursor时,则使用这个适配器。在使用SimpleCursorAdapter时,必须为Cursor的每一行数据指定使用的布局,也必须为Cursor的每一栏指定要使用布局中的哪一个控件。好比,建立一个包含用户名称和电话号码的列表。首先执行Cursor数据库的查询,返回的是Cursor一行用户的信息,其中有用户的名称和电话号码等信息;而后建立一个字符串数组用于指定将显示Cursor的哪一列,建立一个integer数组为每一列指定相应的视图来放置数据,如代码清单1-6所示:
String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER}; int[] toViews = {R.id.display_name, R.id.phone_number};
代码清单1-6
初始化SimpleCursorAdapter时,传入的布局参数和两个数组对Cursor每一个结果都是适用的,代码清单1-7所示:
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.person_name_and_number, cursor, fromColumns, toViews, 0); ListView listView = getListView(); listView.setAdapter(adapter);
代码清单1-7
SimpleCursorAdapter接下来为Cursor每一行使用提供的布局来建立View,经过将每一个fromColumns元素插入到指定的View。
在应用程序的生命周期中,若是适配器对应数据被改变了,应该调用notifyDataSetChanged()。这会通知相应的View数据变化了,它会自我刷新。
1.10.2处理点击(click)事件
您能够经过实现AdapterView.OnItemClickListener接口,来处理AdapterView每一个item的click事件。如代码清单1-8所示:
private OnItemClickListener mMessageClickedHandler = new OnItemClickListener() { public void onItemClick(AdapterView parent, View v, int position, long id) { // Do something } }; listView.setOnItemClickListener(mMessageClickedHandler);
代码清单1-8
线性布局(Linear Layout)是一个ViewGroup,它全部的子视图都在一个方向对齐,水平或者垂直。你能够经过android:orientation 属性来指定布局的方向。线性布局的全部子视图排列都是一个靠着另外一个,所以垂直列表每行仅仅有一个子视图,无论有多宽。水平列表只能有一行的高度(最高子视图的高度加上边距距离)。线性布局对于每个子视图涉及到边缘在子视图和权重(左边或者右边以及中间对齐)之间。
1.11.1布局权重(Weight)
线性布局支持给个别的子视图设定权重,经过android:layout_weight属性。就一个视图在屏幕上占多大的空间而言,这个属性给其设定了一个重要的值。一个大的权重值,容许它扩大到填充父视图中的任何剩余空间。子视图能够指定一个权重值,而后视图组剩余的其余的空间将会分配给其声明权重的子视图。默认的权重是0。例如,若是有三个文本框,其中两个声明的权重为1,另一个没有权重,没有权重第三个文本字段不会增长,只会占用其内容所需的面积。其余两个一样的会扩大以填补剩余的空间,在三个文本域被测量后。若是第三个字段,而后给定的权重为2(而不是0),那么它如今的声明比其余的更重要,因此它获得一半2/(2+1+1)的总的剩余空间,而前两个平均分配剩余的。
若在线性布局中建立占有相同空间的子视图,设置每一个子视图的android:layout_height属性值为"0dp"(对于垂直线性布局来讲),或者设置每一个子视图的android:layout_width属性值为"0dp"(对于水平线性布局来讲)。而后在设置每一个子视图的android:layout_weight属性值为"1"。若是想更详细的了解线性布局的每一个子视图的可用属性,能够参考LinearLayout.LayoutParams
下面让咱们来看下代码清单1-9的实例:
<?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:paddingLeft="16dp" android:paddingRight="16dp" android:orientation="vertical" > <EditText android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="@string/to" /> <EditText android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="@string/subject" /> <EditText android:layout_width="fill_parent" android:layout_height="0dp" android:layout_weight="1" android:gravity="top" android:hint="@string/message" /> <Button android:layout_width="100dp" android:layout_height="wrap_content" android:layout_gravity="right" android:text="@string/send" /> </LinearLayout>
代码清单1-9
例子运行的结果以下图1-3所示:
图1-3 运行后的效果图
RelativeLayout顾名思义,相对布局,在这个容器内部的子元素们可使用彼此之间的相对位置(例如,在某个视图左边left-of)或者和容器间的相对位置(例如,与父视图左对齐,底部对齐或者居中等)来进行定位。
RelativeLayout(相对布局)是一个为用户界面设计,很是强大的工具.由于它能够消除嵌套视图组,并保持你的布局层次更简洁,从而提升性能。若是你发现本身使用多个嵌套的LinearLayout组,您可能可以取代单一RelativeLayout。
1.12.1定位View
相对布局可让它的子View指定本身的相对于父View的位置或者视图元素之间的相对位置(经过指定的ID)。你可使两个元素右边界对齐,或者使一个View在另外一个View下方, 或者使View在屏幕居中偏左等等。默认状况下,全部的子View在布局的左上角。因此你必须经过使用布局属性RelativeLayout.LayoutParams中各类不一样的可用属性值来定义每一个View的位置。
相对布局View的一些可用属性包括:
◆android:layout_alignParentTop
若是设置为“true”,使这一View的顶部边缘匹配父类的顶部边缘
◆android:layout_centerVertical
若是“true”,设置此子视图在父View中垂直居中。
◆android:layout_below
设置此视图的上边缘位于经过资源ID指定的View的下方。
◆android:layout_toRightOf
设置此视图的左边缘位于经过资源ID指定的View的右方。
这仅仅是几个例子,全部的布局属性咱们能够在RelativeLayout.LayoutParams中找到。
每一个布局属性的值既能够是boolean类型的值来肯定布局相对于父布局的位置,也能够是某个子View的ID,来指定布局相对于这个子View的位置。
在你的xml布局文件中,依赖于其余视图的布局能够在声明的时候没有顺序。例如:
你能够声明“View1”在“VIew2”的下方,即便View2是在视图层次结构中最后一个被声明的。下面的例子演示了这种状况。(这是官方的说法,但笔者遇到过的实际状况是顺序是有影响的),下面让咱们看下代码清单1-10:
<?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" android:paddingLeft="16dp" android:paddingRight="16dp" > <EditText android:id="@+id/name" android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="@string/reminder" /> <Spinner android:id="@+id/dates" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_below="@id/name" android:layout_alignParentLeft="true" android:layout_toLeftOf="@+id/times" /> <Spinner android:id="@id/times" android:layout_width="96dp" android:layout_height="wrap_content" android:layout_below="@id/name" android:layout_alignParentRight="true" /> <Button android:layout_width="96dp" android:layout_height="wrap_content" android:layout_below="@id/times" android:layout_alignParentRight="true" android:text="@string/done" /> </RelativeLayout>
代码清单1-10
例子运行的结果以下图1-4所示:
图1-4 运行后的效果图
列表视图是一个纵向显示滚动项的View组合。每一列的项都经过Adapter被自动插入到列表中,其中,Adapter适配器能够从数组或者数据库查询中提取出内容并转化成列表View中的item。
1.13.1使用一个装载器
使用一个CursorLoade是避免一个异步任务查询光标Curso时阻塞程序主线程的标准途径。当CursorLoader收到一个Cursor结果,LoaderCallbacks会收到一个对onLoadFinished()的回调,这时能够利用新的Cursor和列表视图更新Adapter并显示结果。
虽然CursorLoader函数在Android3.0(API级别 11)中才第一次引入,程序能够经过引入Support Library使用它们来支持运行Android 1.6及以上的设备。
要查看更多关于利用Loader异步加载数据的信息,请参看Loaders
下面的例子是把ListView做为惟一默认布局元素的活动ListActivity。它完成向Contacts Provider查询姓名和电话号码清单的功能。
为了使用CursorLoader向列表动态加载数据,这个活动实现了LoaderCallbacks接口。如代码清单1-11所示:
public class ListViewLoader extends ListActivity implements LoaderManager.LoaderCallbacks<Cursor> { SimpleCursorAdapter mAdapter; static final String[] PROJECTION = new String[] {ContactsContract.Data._ID, ContactsContract.Data.DISPLAY_NAME}; static final String SELECTION = "((" + ContactsContract.Data.DISPLAY_NAME + " NOTNULL) AND (" + ContactsContract.Data.DISPLAY_NAME + " != '' ))"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ProgressBar progressBar = new ProgressBar(this); progressBar.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, Gravity.CENTER)); progressBar.setIndeterminate(true); getListView().setEmptyView(progressBar); ViewGroup root = (ViewGroup) findViewById(android.R.id.content); root.addView(progressBar); String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME}; int[] toViews = {android.R.id.text1}; mAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, null, fromColumns, toViews, 0); setListAdapter(mAdapter); getLoaderManager().initLoader(0, null, this); } public Loader<Cursor> onCreateLoader(int id, Bundle args) { return new CursorLoader(this, ContactsContract.Data.CONTENT_URI, PROJECTION, SELECTION, null, null); } public void onLoadFinished(Loader<Cursor> loader, Cursor data) { mAdapter.swapCursor(data); } public void onLoaderReset(Loader<Cursor> loader) { mAdapter.swapCursor(null); } @Override public void onListItemClick(ListView l, View v, int position, long id) { } }
代码清单1-11
注意:由于这个例子要向Contacts Provider请求查询数据,程序须要在制做清单文件中请求READ_CONTACTS权限:
<uses-permission android:name="android.permission.READ_CONTACTS" />
GridView是一个在可滚动的二维网格空间中显示item的ViewGroup。元件会使用ListAdapter自动插入网格布局中。
在本教程中,将建立一个缩略图网格。当一个item被选中,会弹出显示该图像的位置的消息框。
1. 首先建立一个名为HelloGridView的工程
2. 找出一些将要使用的的图像。将准备好的图像放在工程的res/drawable/目录下。
3. 打开 res/layout/main.xml文件,并插入如下代码清单1-12:
<?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" />
代码清单1-12
建立的GridView将填满整个屏幕。这些属性的含义都很明显。更多关于属性的信息,请参阅的GridView的参考。
四、打开 HelloGridView.java 并在其中的onCreate()函数中插入如下代码清单1-13:
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(HelloGridView.this, "" + position, Toast.LENGTH_SHORT).show(); } }); }
代码清单1-13
当main.xml文件完成内容布局之后,GridView会被findViewById(int)方法从布局中捕捉到。setAdapter()方法设置一个自定义的适配器(ImageAdapter)做为被显示在网格中的元件的源。ImageAdapter会在下一步中建立。
setOnItemClickListener()会传递一个新的 AdapterView.OnItemClickListener消息以便于响应网格元件被选中的事件。 匿名实例定义了由onItemClick()回调函数弹出一个Toast消息框显示所选中的网格元件的位置索引号(索引号从零开始计算。在实际程序中能够经过位置索引号获取其全尺寸图像以备其余用途)。
5. 建立一个扩展BaseAdapter并调用ImageAdapter的新类,如代码清代1-14:
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; } public View getView(int position, View convertView, ViewGroup parent) { ImageView imageView; if (convertView == null) { 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; } private Integer[] mThumbIds = { R.drawable.sample_2, R.drawable.sample_3, R.drawable.sample_4, R.drawable.sample_5, R.drawable.sample_6, R.drawable.sample_7, R.drawable.sample_0, R.drawable.sample_1, R.drawable.sample_2, R.drawable.sample_3, R.drawable.sample_4, R.drawable.sample_5, R.drawable.sample_6, R.drawable.sample_7, R.drawable.sample_0, R.drawable.sample_1, R.drawable.sample_2, R.drawable.sample_3, R.drawable.sample_4, R.drawable.sample_5, R.drawable.sample_6, R.drawable.sample_7 }; }
代码清单1-14
首先,实例化一些继承自BaseAdapter的必要函数。构造函数和getCount()不用多解释。一般状况下,getItem(int)应该返回一个适配器中指定位置的真实对象,可是在本例中这点被忽略了。一样的,getItemId(int)应该返回元件的真实编号,可是本例中不须要这样。
第一个必须的方法是getView()。这个方法为每个加入到ImageAdapter的图像建立一个新的View视图。当调用它时,一个View视图对象会被传入而且是可重复使用的(在被调用至少一次之后),因此须要确认对象是否为空。若是为空,就要实例化一个ImageView并根据要呈现的图像设置属性参数。
setLayoutParams(ViewGroup.LayoutParams)设置视图的高度和宽度,这样能够确保不论原图像的大小如何都能适当的调整大小和裁减。
setScaleType(ImageView.ScaleType)声明了图像将依照中心进行裁减(若是须要的话)。
int, int, int) setPadding(int, int, int, int)定义了各边如何进行填充。(须要注意的是,若是图像有不一样的纵横比,那么当图像不匹配ImageView给定的尺寸时,较少的填充就会致使图像更多的裁减)。
若是传给android.view.View, android.view.ViewGroup) getView()的View视图不为空,则本地的ImageView会由可重复使用的View初始化。
在getView()方法的最后,被传入的position参数会用于从被做为ImageView资源的mThumbIds数组中选择图像。
剩下的就是定义绘画资源的mThumbIds数组。
6. 运行程序。
能够经过调整GridVie和ImageView的元素体验其使用方法。例如,使用setAdjustViewBounds(boolean)而不使用setLayoutParams(ViewGroup.LayoutParams)。
本文来自jy02432443,是本人辛辛苦苦一个个字码出来的,转载请保留出处,并保留追究法律责任的权利 QQ78117253