Application Fundamentals(应用程序基础)

Android apps are written in the Java programming language. The Android SDKtools compile your code—along with any data and resource files—into an APK: an Androidpackage, which is an archive file with an .apk suffix. One APKfile contains all the contents of an Android app and is the file that Android-powereddevices use to install the app.

Android应用是用Java语言编写的。Android SDK将代码和数据、资源打包成以apk为后缀的压缩文件(apk = Android package)。一个APK文件包含了Android应用所有的内容,APK是Android系统的安装应用包。

Once installed on a device, each Android app lives in its own securitysandbox:

安装到设备后,每一个Android应用运行在各自的安全沙箱里。

  • The Android operating system is a multi-user Linux system in which each app is a different user.

Android操作系统是一个多用户Linux系统,每一个应用是一个用户。

  • By default, the system assigns each app a unique Linux user ID (the ID is used only by the system and is unknown to the app). The system sets permissions for all the files in an app so that only the user ID assigned to that app can access them.

默认情况,系统给每一个应用一个唯一的Linux用户ID(只有系统可以用此ID,应用本身不知道此ID)。系统给每一个应用下所有的文件都设置了权限(访问权限),只有被分配到相同用户ID的应用可以访问这些文件。

  • Each process has its own virtual machine (VM), so an app's code runs in isolation from other apps.

每一个进程都有自己的虚拟机(VM),所以每个应用的代码都运行在各自的虚拟机中(相互之前没有影响)。

  • By default, every app runs in its own Linux process. Android starts the process when any of the app's components need to be executed, then shuts down the process when it's no longer needed or when the system must recover memory for other apps.

默认情况下,每一个应用运行在他们自己的Linux进程中。当应用的任何组件需要运行时Android启动进程,当不再需要或者为了其他应用正常运行回收内存时才关闭进程。

In this way, the Android system implements the principle of leastprivilege. That is, each app, by default, has access only to thecomponents that it requires to do its work and no more. This creates a verysecure environment in which an app cannot access parts of the system for whichit is not given permission.

这种方式下,Android系统奉行最少特权原则—默认情况下,每一个应用(为了完成工作)只用它需要的组件。这就给应用营造了一个非常安全的运行环境,应用无法访问未授权的“资源”(组件、文件等)。

However, there are ways for an app to share data with other apps and foran app to access system services:

对于一个应用来说,有几种方式可以跟其他应用分享它的数据,也可以访问系统服务。

  • It's possible to arrange for two apps to share the same Linux user ID, in which case they are able to access each other's files. To conserve system resources, apps with the same user ID can also arrange to run in the same Linux process and share the same VM (the apps must also be signed with the same certificate).

两个相同Linux用户ID的应用可以相互访问对方的文件。为了节省(保护?)系统资源,两个相同用户ID应用可以运行在同一个Linux进程中并且可以分享同一个虚拟机(两个应用必须拥有相同的签名)。

  • An app can request permission to access device data such as the user's contacts, SMS messages, the mountable storage (SD card), camera, Bluetooth, and more. All app permissions must be granted by the user at install time.

一个应用可以申请权限获取设备数据,如:用户联系人、短信、SD卡、相机、蓝牙等待。所有的权限必须在用户安装时授权。

That covers the basics regarding how an Android app exists within thesystem. The rest of this document introduces you to:

接下来的文档将介绍Android应用的一些基础:

  • The core framework components that define your app.

开发app的主要框架组件

  • The manifest file in which you declare components and required device features for your app.

声明组件、权限的清单(manifest)文件

  • Resources that are separate from the app code and allow your app to gracefully optimize its behavior for a variety of device configurations.

与代码分离的(为了优雅地适配不同配置的设备)资源文件

App Components


App components are the essential building blocks of anAndroid app. Each component is a different point through which the system canenter your app. Not all components are actual entry points for the user andsome depend on each other, but each one exists as its own entity and plays aspecific role—each one is a unique building block that helps define your app'soverall behavior.

App组件是一个安卓应用最基本的构建模块。每一个组件都是进入APP不同的切入点。对用户来说不是所有的组件都是实际的切入点,有一些会依赖其他的组件;每一个组件都作为一个实体存在并扮演着不同的角色,每一个组件都是独一无二的构建块以此构建出一个APP。

There are four different types of app components. Each type serves adistinct purpose and has a distinct lifecycle that defines how the component iscreated and destroyed.

Android提供了四种不同的APP组件。每一种都有它存在的目的,拥有不同的生命周期,如何被构建、销毁。

Here are the four types of app components:

以下是四种应用组件:

Activities(活动)

An activityrepresents a single screen with a user interface. For example, an email appmight have one activity that shows a list of new emails, another activity tocompose an email, and another activity for reading emails. Although theactivities work together to form a cohesive user experience in the email app,each one is independent of the others. As such, a different app can start anyone of these activities (if the email app allows it). For example, a camera appcan start the activity in the email app that composes new mail, in order forthe user to share a picture.

 

一个Activity代表了一个单独的拥有用户界面的屏幕。例如,一个邮件应用拥有一个邮件列表的Activity、一个编写新邮件Activity、一个读邮件Activity。每一个独立的Activity组合在一起就组建了一个拥有粘性用户体验的邮件应用。如果允许(有开启权限),其他的应用也可以开启这些Activity(以上提到的那几个)。例如,为了用户可以分享图片,一个相机应用可以开启邮件应用中编写新邮件的Activity。

An activity is implemented as a subclass of Activity and you can learn more about it in the Activities developer guide.

一个具体的Activity是Activity的子类,你可以从Activities学习更多相关知识。

Services(服务)

A serviceis a component that runs in the background to perform long-running operationsor to perform work for remote processes. A service does not provide a userinterface. For example, a service might play music in the background while theuser is in a different app, or it might fetch data over the network withoutblocking user interaction with an activity. Another component, such as anactivity, can start the service and let it run or bind to it in order tointeract with it.

 

Service是一个运行在后台执行长时间操作或者被远程调用的组件。Service并不提供用户界面。例如,当用户在使用另一个应用时,Service可以在后台播放音乐,或者在不影响用户操作情况下通过网络获取数据。其他的组件,例如Activity,可以通过start或者bind方式启动Service。

A service is implemented as a subclass of Service and you can learn more about it in the Services developer guide.

一个服务是一个Service的子类,你可以从Services学到更多内容。

Content providers(内容提供者)

A contentprovider manages a shared set of app data. You can store the data in thefile system, an SQLite database, on the web, or any other persistent storagelocation your app can access. Through the content provider, other apps canquery or even modify the data (if the content provider allows it). For example,the Android system provides a content provider that manages the user's contactinformation. As such, any app with the proper permissions can query part of thecontent provider (such as ContactsContract.Data) to read and write information about a particular person.

 

一个内容提供者管理了一系列应用共享数据。你可以将数据存储在文件系统、SQlite数据库、网络、或者你应用可以访问到的其他可以永久存储的地方。通过ContentProvider其他应用可以查询甚至可以修改数据(如果被允许)。例如,Android系统提供了一个管理用户联系人信息的内容提供者。任何有适当权限的应用都可以询问内容提供者的一部分(例如ContactsContract.Data),读写一个特定人的信息。

Content providers are also useful for reading and writingdata that is private to your app and not shared. For example, the Note Pad sample app uses a content provider to save notes.

ContentProvider对那些不共享的、应用私有的数据读写非常有用(可以控制读写)。例如,记事本应用就是用一个ContentProvider保存笔记。

A content provider is implemented as a subclass of ContentProvider and must implement a standard set of APIs that enable other apps toperform transactions. For more information, see the Content Providers developer guide.

一个内容提供者是一个ContentProvider的子类,它必须实现一系列标准的API(重写几个方法)以便使其他应用可以使用。更多信息请查阅Content Providers

Broadcast receivers(广播接受者)

A broadcastreceiver is a component that responds to system-wide broadcastannouncements. Many broadcasts originate from the system—for example, abroadcast announcing that the screen has turned off, the battery is low, or apicture was captured. Apps can also initiate broadcasts—for example, to let otherapps know that some data has been downloaded to the device and is available forthem to use. Although broadcast receivers don't display a user interface, theymay create a status bar notification to alert the user when a broadcast event occurs. Morecommonly, though, a broadcast receiver is just a "gateway" to othercomponents and is intended to do a very minimal amount of work. For instance,it might initiate a service to perform some work based on the event.

 

一个广播接受者是与全系统的广播公告相对应的组件。很多广播都是由系统发出的,例如:熄屏广播、低电量广播、截图广播。应用自己也可以发广播,例如:通知其他应用某些数据已下载并可以使用。虽然广播接受者不显示用户界面,但是它可以创建一个状态栏通知提醒用户收到一个广播。大多数情况下,一个广播接受者仅仅是只做一点点工作为打开其他组件的一个“入口”。例如,根据不同事件初始化一个服务去完成某些任务。

A broadcast receiver is implemented as a subclass of BroadcastReceiver and each broadcast is delivered as an Intent object. For more information, see the BroadcastReceiver class.

一个广播接受者是一个BroadcastReceiver的子类,每一个广播都是都过Intent传递地。更多内容,请查阅BroadcastReceiver

A unique aspect of the Android system design is that any app can startanother app’s component. For example, if you want the user to capture a photowith the device camera, there's probably another app that does that and yourapp can use it, instead of developing an activity to capture a photo yourself.You don't need to incorporate or even link to the code from the camera app.Instead, you can simply start the activity in the camera app that captures aphoto. When complete, the photo is even returned to your app so you can use it.To the user, it seems as if the camera is actually a part of your app.

Android系统设计独特一个点是任何一个应用都可以打开另一个应用的组件。例如,你打算让用户用相机拍照,你可以调用其他有拍照功能的应用拍照,而不是自己开发一个Activity去完成功能。你不必合并甚至链接相机应用的代码。你紧紧需要打开具有拍照功能的Activity。完成拍照后,返回到你的应用时你甚至可以使用它。对于用户而言,相机就像是你应用的一部分。

When the system starts a component, it starts the process for that app (ifit's not already running) and instantiates the classes needed for thecomponent. For example, if your app starts the activity in the camera app thatcaptures a photo, that activity runs in the process that belongs to the cameraapp, not in your app's process. Therefore, unlike apps on most other systems,Android apps don't have a single entry point (there's no main() function, for example).

当系统开启一个组件时,它会开启它所在的进程(还没有运行时)并初始化组件所用到的类(对象)。例如,如果你的应用打开一个相机应用中可以拍照的Activity时,此Activity运行在相机应用进程而不是你的进程中。因此,Android应用不像其他大多数的系统的应用只有一个入口--Android应用入口不唯一(没有main方法)。

Because the system runs each app in a separate process with filepermissions that restrict access to other apps, your app cannot directlyactivate a component from another app. The Android system, however, can. So, toactivate a component in another app, you must deliver a message to the systemthat specifies your intent to start a particular component. The systemthen activates the component for you.

由于Android系统中每一个应用都运行在一个单独的进程中,对其他应用有着严格的文件访问权限,你的应用不能直接激活另一个应用中的组件。Android系统是允许打开其他的应用组件的,然而不能直接打开;你必须通过Intent告诉系统你准备打开某一个特定的组件,最后由系统为你打开(激活)此组件。

Activating Components(激活组件)

Three of the four component types—activities, services, and broadcastreceivers—are activated by an asynchronous message called an intent.Intents bind individual components to each other at runtime (you can think ofthem as the messengers that request an action from other components), whetherthe component belongs to your app or another.

四种组件中的三种(Activity、Service、BroadcastReceiver)由一个异步信息Intent激活的。

An intent is created with an Intent object, which defines a message to activate either a specific componentor a specific type of component—an intent can be either explicit orimplicit, respectively.

一个意图是有Intent对象来构建的,它包括激活哪一个特定的或者哪一类组件,

Intent可以为隐式的也可以为显示的。

For activities and services, an intent defines the action to perform (forexample, to "view" or "send" something) and may specify theURI of the data to act on (among other things that the component being startedmight need to know). For example, an intent might convey a request for anactivity to show an image or to open a web page. In some cases, you can startan activity to receive a result, in which case, the activity also returns theresult in an Intent (for example, you can issue an intent to let the user pick a personalcontact and have it returned to you—the return intent includes a URI pointingto the chosen contact).

对于Activity和Service而言,意图定义要执行的操作(例如,“查看”或“发送”的东西),并且可以指定操作数据的URI(将要被启动的组件需要包括URI在内的一些东西)。例如,一个Intent可能会传达一个需要一个Activity展示图片或者打开一个网页的需求。在某些情况下,你打开一个Activity是为了获得一个返回结果,在这种情况下,activity需要返回一个Intent(例如,你可以发出一个intent让用户选择一个联系人然后返回,返回的intent中包括被选中联系人的URI)。

For broadcast receivers, the intent simply defines the announcement beingbroadcast (for example, a broadcast to indicate the device battery is lowincludes only a known action string that indicates "battery is low").

对于广播接收者,Intent只是简单地定义了一个将被广播的声明(例如,指示设备电量低的广播只包括了一个已知的指示“电量低”action字符串)。

The other component type, content provider, is not activated by intents.Rather, it is activated when targeted by a request from a ContentResolver. The content resolver handles all direct transactions with the contentprovider so that the component that's performing transactions with the providerdoesn't need to and instead calls methods on the ContentResolver object. This leaves a layer of abstraction between the content providerand the component requesting information (for security).

ContentProvider不是用intent激动。当ContentResolver发出一个请求时会激活对应的ContentProvider。ContentResolver处理与ContentProvider的所有的直接事务,所以处理与ContentProvider事务的这样一个组件是并不需要的,而是直接调用ContentResolver的方法。这就导致了(需要信息的)组件与ContentProvider之间有了一层抽象层。

There are separate methods for activating each type of component:

有几个激活每一个类型组件的独立方法。

可以给Context.startActivity()或者Context.startActivityForResult()传递一个Intent(当需要返回结果是用此方法)打开一个Activity(或者给予一个新的任务)。

可以给startService()传递一个Intent打开一个Service(或者给予一个任务)。或者给bindService()传一个Intent绑定一个Service。

可以给像sendBroadcast(), sendOrderedBroadcast(), 或者sendStickyBroadcast()方法传递一个Intent发送一个广播。

可以使用ContentResolver的query()方法在一个内容提供者上作一次查询。

For more information about using intents, see the Intents and Intent Filters document. More information about activating specificcomponents is also provided in the following documents: Activities, Services, BroadcastReceiver and Content Providers.

更多内容请查阅:Intents and Intent Filters  Activities, Services, BroadcastReceiver and Content Providers.

 

The Manifest File(清单文件)


Before the Android system can start an app component, the system must knowthat the component exists by reading the app's AndroidManifest.xml file (the "manifest" file). Your app must declare all itscomponents in this file, which must be at the root of the app projectdirectory.

在Android系统可以打开一个应用的组件前,系统会通过读取应用的清单文件知道组件的存在。开发者必须在项目的根目录的清单文件中声明所有的组件。

The manifest does a number of things in addition to declaring the app'scomponents, such as:

除了声明应用组件外,清单文件还会做其他的一些事情,就像:

  • Identify any user permissions the app requires, such as Internet access or read-access to the user's contacts.

罗列出应用需要的所有的用户权限,例如访问网络、读取用户联系人

  • Declare the minimum API Level required by the app, based on which APIs the app uses.

根据app用的API声明最小API等级

  • Declare hardware and software features used or required by the app, such as a camera, bluetooth services, or a multitouch screen.

声明APP需要的硬件以及软件功能,像相机、蓝牙服务、多点触控屏幕

  • API libraries the app needs to be linked against (other than the Android framework APIs), such as the Google Maps library.

APP需要的API库(或者Android framework API),像谷歌地图库

  • And more

还有更多

Declaring components(声明组件)

The primary task of the manifest is to inform the system about the app'scomponents. For example, a manifest file can declare an activity as follows:

清单文件最主要的任务是告诉系统APP所有的组件,例如下面声明一个Activity清单文件:

<?xml version="1.0"encoding="utf-8"?>
<manifest ... >
    <application android:icon="@drawable/app_icon.png"... >
        <activityandroid:name="com.example.project.ExampleActivity"
                  android:label="@string/example_label"... >
        </activity>
        ...
    </application>
</manifest>

In the <application> element, the android:icon attribute points to resources for an icon thatidentifies the app.

application元素中的android:icon是鉴别APP的链接图片资源的属性。

In the <activity> element, the android:name attribute specifies the fully qualified class name ofthe Activity subclass and the android:label attributes specifies a stringto use as the user-visible label for the activity.

在activity元素中,android:name属性指定了Activity子类全名;android:label指定了Activity的用户可见标签。

You must declare all app components this way:

你必须用这种方式指定APP所有的组件:

Activities, services, and content providers that you include in yoursource but do not declare in the manifest are not visible to the system and,consequently, can never run. However, broadcast receivers can be eitherdeclared in the manifest or created dynamically in code (as BroadcastReceiver objects) and registered with the system by calling registerReceiver().

在代码中有而清单文件中没有声明的Activity、Service、ContentProvider永远不会被执行(如启动一个此类Activity会抛异常)。然而,BroadcastReceiver既可以在清单文件中声明也可以在代码中用registerReceiver()动态注册。

For more about how to structure the manifest file for your app, see The AndroidManifest.xml File documentation.

有关更多清单文件结构知识,请阅读AndroidManifest.xml File文档。

Declaring component capabilities(声明组件功能)

As discussed above, in Activating Components, you can use an Intent to start activities, services, and broadcast receivers. You can do so byexplicitly naming the target component (using the component class name) in theintent. However, the real power of intents lies in the concept of implicitintents. An implicit intent simply describes the type of action to perform(and, optionally, the data upon which you’d like to perform the action) andallows the system to find a component on the device that can perform the actionand start it. If there are multiple components that can perform the actiondescribed by the intent, then the user selects which one to use.

与上面谈论的一样,你可以使用一个Intent开启一个Activity、Service、BroadcastReceiver。可以在Intent中用组件的名字(全名)显式地打开一个组件。然而,Intent的真正强大的地方在于隐式的Intent概念。一个隐式意图只是简单地描述了操作Action的类型(还有可选的操作此Action的数据),让系统在设备中找到一个可操作此类型Action的组件并可开它。当有多个组件可以操作此类型的Action时,用户选择一个去执行。

The way the system identifies the components that can respond to an intentis by comparing the intent received to the intent filters provided inthe manifest file of other apps on the device.

系统通过比较设备中其他应用的清单文件中的intent filter和收到的intent来判断组件是否可以响应此Intent。

When you declare an activity in your app's manifest, you can optionallyinclude intent filters that declare the capabilities of the activity so it canrespond to intents from other apps. You can declare an intent filter for yourcomponent by adding an <intent-filter> element as a child of the component's declarationelement.

当你在清单文件中声明一个Activity时,你可能会额外的包含一个intent filter以此来说明此Activity是否能够响应其他APP的Intent。在声明组件的元素中添加一个<intent-filter>子孩子便可以声明一个意图过滤器。

For example, if you've built an email app with an activity for composing anew email, you can declare an intent filter to respond to "send"intents (in order to send a new email) like this:

举个例子,如果你构建一个可以编写新邮件的邮件应用时,你可以添加如下意图过滤器以此声明此Activity可以处理“发送”新邮件意图。

<manifest ... >
    ...
    <application ... >
        <activity android:name="com.example.project.ComposeEmailActivity">
            <intent-filter>
                <actionandroid:name="android.intent.action.SEND" />
                <dataandroid:type="*/*" />
                <categoryandroid:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
    </application>
</manifest>

Then, if another app creates an intent with the ACTION_SEND action and pass it to startActivity(), the system may start your activity so the user can draft and send anemail.

然后如果你的应用创建一个ACTION_SEND动作的意图并传给startActivity()开启一个Activity,系统可能会打开ComposeEmailActivity让用户编辑并发送邮件

For more about creating intent filters, see the Intents and Intent Filters document.

Declaring app requirements(声明APP要求)

There are a variety of devices powered by Android and not all of themprovide the same features and capabilities. In order to prevent your app frombeing installed on devices that lack features needed by your app, it'simportant that you clearly define a profile for the types of devices your appsupports by declaring device and software requirements in your manifest file.Most of these declarations are informational only and the system does not readthem, but external services such as Google Play do read them in order toprovide filtering for users when they search for apps from their device.

形形色色的Android手机有着不同的功能、配置、性能。通过在清单文件中声明你应用需要软硬件的功能便可以阻止那些你APP需要而设备上没有此功能的设备安装你的应用。大多数这些声明仅仅是通知性的,系统不会去读取他们。但是像Google Play这种外部服务会读取他们,Google Play会过滤掉用户设备不支持的应用。

For example, if your app requires a camera and uses APIs introduced inAndroid 2.1 (API Level 7), you should declare these as requirements in your manifest file likethis:

例如,你的APP需要相机并且系统是Android 2.1及以上设备才能安装,你需要有如下声明。

<manifest ... >
    <uses-featureandroid:name="android.hardware.camera.any"
                 android:required="true" />
    <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="19"/>
    ...
</manifest>

Now, devices that do not have a camera and have an Android version lowerthan 2.1 cannot install your app from Google Play.

没有相机或者Android系统在2.1以下的设备就不能在Google Play上安装你的应用了。

However, you can also declare that your app uses the camera, but does not requireit. In that case, your app must set the required attribute to "false" and check at runtime whether the device has a camera anddisable any camera features as appropriate.

你可以声明你的应用使用相机但是不是必须的。在这种情况下,你需要将uses-feature元素的required属性设置为false,当运行时去检查设备是否相机功能,然后找一种比较优雅的方式解决没有相机设备问题。

More information about how you can manage your app's compatibility withdifferent devices is provided in the Device Compatibility document.

更多有关管理APP兼容性的知识,请阅读Device Compatibility

App Resources(APP资源)


An Android app is composed of more than just code—it requires resourcesthat are separate from the source code, such as images, audio files, andanything relating to the visual presentation of the app. For example, youshould define animations, menus, styles, colors, and the layout of activityuser interfaces with XML files. Using app resources makes it easy to updatevarious characteristics of your app without modifying code and—by providingsets of alternative resources—enables you to optimize your app for a variety ofdevice configurations (such as different languages and screen sizes).

一个Android APP是由代码和像图片、声音文件、有视觉有关等资源文件组合而成。例如,你定义的动画、菜单、风格、颜色、布局文件都是APP资源。通过提供可选资源在不改代码的提前下可以很方便地更新应用特性,非常高效地适配不同配置的设备(不同语言、不同屏幕大小等)。

For every resource that you include in your Android project, the SDK buildtools define a unique integer ID, which you can use to reference the resourcefrom your app code or from other resources defined in XML. For example, if yourapp contains an image file named logo.png (saved in the res/drawable/ directory), the SDK tools generate a resource ID named R.drawable.logo, which you can use to reference the image and insert itin your user interface.

Android SDK编译工具会给Android项目中的每一个资源文件分配一个唯一的ID,你可以使用此ID在代码中或者其他用XML定义的资源文件中引用它。例如,你的APP有一张logo.png的图片,AndroidSDK工具包会给此资源分配R.drawable.logo ID,你就可以使用R.drawable.logo了。

One of the most important aspects of providing resources separate fromyour source code is the ability for you to provide alternative resources fordifferent device configurations. For example, by defining UI strings in XML,you can translate the strings into other languages and save those strings inseparate files. Then, based on a language qualifier that you append tothe resource directory's name (such as res/values-fr/ for French string values) and the user's language setting, the Androidsystem applies the appropriate language strings to your UI.

代码和资源分开最重要的一方面是可以根据不同的配置提供不同的资源(适配不同的设备)。例如,你在XML定义一个字符串时,你可以在一个其他单独的文件中提供其他的翻译。具体做法就是给资源目录加修饰符(如为法语相关的资源提供/values-fr/),Android系统会根据当前的语言设置选择使用适当的字符串(如当前语言设置为法语,APP恰巧提供了法语的字符串此时会用法语的字符串)。

Android supports many different qualifiers for your alternativeresources. The qualifier is a short string that you include in the name of yourresource directories in order to define the device configuration for whichthose resources should be used. As another example, you should often createdifferent layouts for your activities, depending on the device's screenorientation and size. For example, when the device screen is in portraitorientation (tall), you might want a layout with buttons to be vertical, butwhen the screen is in landscape orientation (wide), the buttons should bealigned horizontally. To change the layout depending on the orientation, youcan define two different layouts and apply the appropriate qualifier to eachlayout's directory name. Then, the system automatically applies the appropriatelayout depending on the current device orientation.

对于可选(可替换)资源,Android系统支持多种修饰符。为了适配不同配置的设备,可以给资源文件夹加修饰符以供给不同配置的设备使用。给不同屏幕大小或者横竖屏提供不同的布局文件。例如,当竖屏时你可能想让按钮垂直排布,当横屏时你可能想让按钮水平排布。为了适配横竖屏,你可以给布局文件夹加上不同的修饰符(portland)提供两种布局文件。系统会根据设备当前方向选取适当的布局文件。

For more about the different kinds of resources you can include in yourapplication and how to create alternative resources for different deviceconfigurations, read Providing Resources.

更多关于多种资源文件和如果创建可选资源知识请查阅Providing Resources.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值