Android机型适配

来源:互联网 发布:用js给html的div传值 编辑:程序博客网 时间:2024/04/28 17:26

2015/10/21 15:35:54 lucas 初步编辑

2015年11月23日 03:44:59 lucas 参照了CSDN上的一些博客进行了修改。(因为没有找到原博主,所以无法列出链接,抱歉!sorry)

201X年XX月XX日 XX:XX:XX 等待下一次修改,等下次空闲时,再完善一些内容,以及提供样例代码以及部分截图。

Android机型适配

PS:Android机型适配一直以来都折磨着我们这些开发者,本篇文章讲介绍Android的屏幕适配,所谓的屏幕适配往往指的就是屏幕大小和屏幕密度的适配。

  • 需要做好一款软件的屏幕适配方案,我们应该学习以下几个方面的知识:
  1. 了解基本的屏幕适配知识。
  2. Google官方的解决方案啊。
  3. 与ScrollView的结合。
  4. 结合Html5和css3优化界面布局和适配。
  5. 与Weight的结合。
  6. .9.png图片的使用。
  7. 题外话

基本的屏幕适配知识

  • 屏幕大小

在Android系统中,将屏幕大小划分成以下几种:small、normal、large、extra large。

  • 屏幕密度

在Android系统中,屏幕密度往往是在指定的屏幕大小区域内,有多少个像素,基本单位是dpi(点/每英寸)。

基本包括四种密度:low、dedium(中等)、hign、extra hign(更高的密度)

常见的密度如下:QVGA(240X320)、HVGA(320X480)、WVGA800(480X800)

Google官方的解决方案

1. 创建不同的布局(Create Different Layouts)

  • 为了让用户在不同的分辨率的设备上的体验得到优化,我们应该为每一个我们所想支持的屏幕尺寸都创建一个自己的layout XML文件,每个文件都保存在相应的资源目录,例如,如果我们想支持large screens,我们就应该在资源目录res文件夹下创建一个layout-large。android系统会根据屏幕的尺寸大小去自动的加载相应的布局。
  • 如下,一个包含这默认的layout和一个供选择的large screen的layout
    res/        layout/            main.xml        layout-large/            main.xml    // 需要注意的是,文件名必须相同,但文件里面的内容可以相同,你可以根据不同的屏幕的尺       寸制定不同的布局以优化用户的体验

在具体的代码中,没有什么变化,android系统会自动调用不同屏幕尺寸的布局

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

系统会根据应用程序所运行在的android设备的屏幕大小加载相同的布局,具体的android如何选择合适的资源将在另外一篇博客关于android资源的详解中介绍到。

  • 下面是一个关于横屏和竖屏的布局:
MyProject/    res/        layout/            main.xml        layout-land/            main.xml

如果想要提供一个特殊的layout在大屏幕设备横屏的时候,则large和land两个限定符都需要使用。

MyProject/    res/        layout/              # default (portrait)            main.xml        layout-land/         # landscape            main.xml        layout-large/        # large (portrait)            main.xml        layout-large-land/   # large landscape            main.xml    

安卓3.2及以上支持定义屏幕尺寸的一种先进方法,允许您指定资源基于最小宽度和高度的屏幕尺寸的密度独立像素。后面我们会详细的解释。

2. 创建不同的位图(Create Different Bitmaps)

  • 因为需要适配不同屏幕,我们需要提供不同的图片来适配,这样才能带来更好的用户体验.
  • [通常我们需要提供下面的资源图片来适配]

xhdpi: (dpi=320, density=2)
hdpi: (dpi=240, density=1.5)
mdpi: (dpi=160, density=1) (baseline)
ldpi: (dpi=120, density=0.75)

这意味着如果我们为xhdpi的设备生成了一张200x200的图片,同时也需要为hdpi的设备生成150x150的图片,为mdpi的设备生成100x100的图片,最后为ldpi的设备生成75x75的图片。

MyProject/    res/        drawable-xhdpi/            awesomeimage.png        drawable-hdpi/            awesomeimage.png        drawable-mdpi/            awesomeimage.png        drawable-ldpi/            awesomeimage.png

这样之后,在任何地方引用@drawable/awesomeimage,系统都会自动根据当前设备的dpi来选择合适的图片进行显示。

3. Android 多屏幕设计(Designing for Multiple Screens)

支持不同的屏幕尺寸(Supporting Different Screen Sizes)

  • 确保你的布局可以根据屏幕的大小自适应调整
  • 为不同的屏幕配置提供对应的UI布局
  • 确保正确的布局适合正确的屏幕。
  • 提供缩放正确的位图( bitmap)
使用“wrap_content”和“match_parent”

为了确保你的布局能灵活的适应不同的屏幕尺寸, 针对一些view组件, 你应该使wrap_content和match_parent来设置他们的宽和高。 如果你使用了wrap_content, view的宽和高会被设置该view所包含的内容的大小值。 如果是match_parent( 在API 8之前是fill_parent) 则会匹配该组件的父控件的大小。
通过使用wrap_content和match_parent尺寸值代替硬编码的尺寸, 你的视图将分别只使用控件所需要的空间或者被拓展以填
充所有有效的空间。 比如:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="match_parent"    android:layout_height="match_parent">    <LinearLayout android:layout_width="match_parent"                android:id="@+id/linearLayout1"                android:gravity="center"                android:layout_height="50dp">            <ImageView android:id="@+id/imageView1"                    android:layout_height="wrap_content"                    android:layout_width="wrap_content"                    android:src="@drawable/logo"                    android:paddingRight="30dp"                    android:layout_gravity="left"                    android:layout_weight="0" />            <View android:layout_height="wrap_content"                    android:id="@+id/view1"                    android:layout_width="wrap_content"                    android:layout_weight="1" />            <Button android:id="@+id/categorybutton"                    android:background="@drawable/button_bg"                    android:layout_height="match_parent"                    android:layout_weight="0"                    android:layout_width="120dp"                    style="@style/CategoryButtonStyle"/>    </LinearLayout>    <fragment android:id="@+id/headlines"            android:layout_height="fill_parent"            android:name="com.example.android.newsreader.HeadlinesFragment"            android:layout_width="match_parent" /></LinearLayout>

横竖屏下使用wrap_content 和 match_parent的效果图

使用相对布局( RelativeLayout)

你可以使用LinearLayout以及wrap_content和match_parent组合来构建复杂的布局, 但是LinearLayout却不允许你精准的控制它子view的关系,子view在LinearLayout中只能简单一个接一个的排成行。如果你需要你的子view不只是简简单单的排成行的排列,更好的方法是使用RelativeLayout,它允许你指定你布局中控件与控件之间的关系, 比如,你可以指定一个子
view在左边, 另一个则在屏幕的右边。

~

使用尺寸限定词(Use Size Qualifiers)

PS:这里的限定词主要是指在编写布局文件时, 将布局文件放在加上类似large, sw600dp等这样限定词的文件夹中,以此来告诉系统根据屏幕选择对应的布局文件, 比如下面例子的layout-large文件夹。
* res/layout/main.xml,单个窗格布局(默认)

~~~

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="horizontal">    <fragment android:id="@+id/headlines"              android:layout_height="fill_parent"              android:name="com.example.android.newsreader.HeadlinesFragment"              android:layout_width="400dp"              android:layout_marginRight="10dp"/>    <fragment android:id="@+id/article"              android:layout_height="fill_parent"              android:name="com.example.android.newsreader.ArticleFragment"              android:layout_width="fill_parent" /></LinearLayout>

注意第二个布局文件的目录名字“large qualifier”, 在大尺寸的设备屏幕时( 比如7寸平板或者其他大屏幕的设备) 就会选择该布局文件, 而其他比较小的设备则会选择没有限定词的另一个布局( 也就是第一个布局文件) 。

使用最小宽度限定词

在Android 3.2之前, 开发者还有一个困难, 那就是Android设备的“large”屏幕尺寸, 其中包括Dell Streak( 设备名称),老版Galaxy Tab和一般的7寸平板,有很多的应用都想针对这些不同的设备( 比如5和7寸的设备) 定义不同的布局, 但是这些设备都被定义为了large尺寸屏幕。 也是因为这个, 所以Android在3.2的时候开始使用最小宽度限定词。

最小宽度限定词允许你根据设备的最小宽度( dp单位) 来指定不同布局。 比如, 传统的7寸平板最小宽度为600dp, 如果你希望你的UI能够在这样的屏幕上显示两个窗格( 不是一个窗格显示在小屏幕上),你可以使用上节中提到的使用同样的两个布局文件。 同的是, 使用sw600来指定两个方框的布局使用在最小宽度为600dp的设备上。

  • res/layout/main.xml,单个窗格布局(默认)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="match_parent"    android:layout_height="match_parent">    <fragment android:id="@+id/headlines"              android:layout_height="fill_parent"              android:name="com.example.android.newsreader.HeadlinesFragment"              android:layout_width="match_parent" /></LinearLayout>
  • res/layout-large/main.xml,两个窗格的布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="horizontal">    <fragment android:id="@+id/headlines"              android:layout_height="fill_parent"              android:name="com.example.android.newsreader.HeadlinesFragment"              android:layout_width="400dp"              android:layout_marginRight="10dp"/>    <fragment android:id="@+id/article"              android:layout_height="fill_parent"              android:name="com.example.android.newsreader.ArticleFragment"              android:layout_width="fill_parent" /></LinearLayout>

这样意味着当你的设备的最小宽度等于600dp或者更大时, 系统选择layout-sw600dp/main.xml(两个窗格) 的布局,而小一点的屏幕则会选择layout/main.xml( 单个窗格) 的布局。 然而,在3.2之前的设备上, 这样做并不是很好的选择。因为3.2之前还没有将sw600dp作为一个限定词出现,所以,你还是需要使用large限定词来做。因此,你还是应该要有一个布局文件名为res/layout-large/main.xml, 和res/layout-sw600dp/main.xml一样。在后续的博客中,我们将介绍到如何避免出现这样重复的布局。

使用布局别名(Use Layout Aliases)

最小宽度限定词只能在android3.2或者更高的版本上使用。因此,你还是需要使用抽象尺寸( small,normal,large,xlarge)来兼容以前的版本。比如,你想要将你的UI设计为在手机上只显示一个方框的布局,而在7寸平板或电视, 或者其他大屏幕设备上显示多个方框的布局, 你可能得提供这些文件:
* res/layout/main.xml,单个窗格布局
* res/layout-large,多个窗格布局
* res/layout-sw600dp,多个窗格布局

最后两个文件都是一样的,因为其中一个将会适配Android3.2的设备,而另外一个则会适配其他Android低版本的平板或者电
视。为了避免这些重复的文件( 维护让人感觉头痛就是因为这个),你可以使用别名文件。 比如,你可以定义如下布局:res/layout/main.xml, 单个方框布局 res/layout/main_twopans.xml, 两个方框布局 然后添加这两个文件:

res/valueslargelayout.xml:

<resources>    <item name="main" type="layout">@layout/main_twopanes</item></resources>

res/values-sw600dp/layout.xml:

<resources>    <item name="main" type="layout">@layout/main_twopanes</item></resources>
使用方向限定词(Use Orientation Qualifiers)

有一些布局不管是在横向还是纵向的屏幕配置中都能显示的非常好,但是更多的时候,适当的调整一下会更好。 在NewsReader应用例子中, 以下是布局在不同屏幕尺寸和方向的行为:
* small screen, portrait:,纵向,一个窗格加logo,小屏幕
* small screen, landscape:,横向,一个窗格加logo,小屏幕
* 7" tablet, portrait:,纵向,一个窗格加actionBar,7寸屏幕
* 7" tablet, landscape:,横向,两个宽窗格加actionBar,7寸屏幕
* 10" tablet, portrait:,纵向,两个窄窗格加actionBar ,平板
* 10" tablet, landscape:,横向,两个宽窗格加actionBar,平板
* TV, landscape:,两个窗格,宽屏,加actionBar,电视

这些每个布局都会在res/layout目录下定义一个xml文件,如此,应用就能根据屏幕配置的变化根据别名匹配到对应的布局来适应屏幕。

res/layout/onepane.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="match_parent"    android:layout_height="match_parent">    <fragment android:id="@+id/headlines"              android:layout_height="fill_parent"              android:name="com.example.android.newsreader.HeadlinesFragment"              android:layout_width="match_parent" /></LinearLayout>

res/layout/onepane_with_bar.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="match_parent"    android:layout_height="match_parent">    <LinearLayout android:layout_width="match_parent"                   android:id="@+id/linearLayout1"                    android:gravity="center"                  android:layout_height="50dp">        <ImageView android:id="@+id/imageView1"                    android:layout_height="wrap_content"                   android:layout_width="wrap_content"                   android:src="@drawable/logo"                   android:paddingRight="30dp"                   android:layout_gravity="left"                   android:layout_weight="0" />        <View android:layout_height="wrap_content"               android:id="@+id/view1"              android:layout_width="wrap_content"              android:layout_weight="1" />        <Button android:id="@+id/categorybutton"                android:background="@drawable/button_bg"                android:layout_height="match_parent"                android:layout_weight="0"                android:layout_width="120dp"                style="@style/CategoryButtonStyle"/>    </LinearLayout>    <fragment android:id="@+id/headlines"               android:layout_height="fill_parent"              android:name="com.example.android.newsreader.HeadlinesFragment"              android:layout_width="match_parent" /></LinearLayout>

res/layout/twopanes.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="horizontal">    <fragment android:id="@+id/headlines"              android:layout_height="fill_parent"              android:name="com.example.android.newsreader.HeadlinesFragment"              android:layout_width="400dp"              android:layout_marginRight="10dp"/>    <fragment android:id="@+id/article"              android:layout_height="fill_parent"              android:name="com.example.android.newsreader.ArticleFragment"              android:layout_width="fill_parent" /></LinearLayout>

res/layout/twopanes_narrow.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="horizontal">    <fragment android:id="@+id/headlines"              android:layout_height="fill_parent"              android:name="com.example.android.newsreader.HeadlinesFragment"              android:layout_width="200dp"              android:layout_marginRight="10dp"/>    <fragment android:id="@+id/article"              android:layout_height="fill_parent"              android:name="com.example.android.newsreader.ArticleFragment"              android:layout_width="fill_parent" /></LinearLayout>

现在所有可能的布局我们都已经定义了,唯一剩下的问题是使用方向限定词来匹配对应的布局给屏幕。这时候,你就可以使用布局别名的功能了:

res/values/layouts.xml:

<resources>    <item name="main_layout" type="layout">@layout/onepane_with_bar</item>    <bool name="has_two_panes">false</bool></resources>

res/values-sw600dp-land/layouts.xml:

<resources>    <item name="main_layout" type="layout">@layout/twopanes</item>    <bool name="has_two_panes">true</bool></resources>

res/values-sw600dp-port/layouts.xml:

<resources>    <item name="main_layout" type="layout">@layout/onepane</item>    <bool name="has_two_panes">false</bool></resources>

res/values-large-land/layouts.xml:

<resources>    <item name="main_layout" type="layout">@layout/twopanes</item>    <bool name="has_two_panes">true</bool></resources>

res/values-large-port/layouts.xml:

<resources>    <item name="main_layout" type="layout">@layout/twopanes_narrow</item>    <bool name="has_two_panes">true</bool></resources>
使用.9.png图片
  • 关于.9图片上下左右四条黑线的含义解释:
  1. 上方黑线代表横向拉伸区域。
  2. 左边黑线代表纵向拉伸区域。
  3. 下方黑线代表横向内容显示区域。
  4. 右边黑线代表纵向内容显示区域。

支持不同的屏幕尺寸同时也意味着你的图片资源也必须能兼容不同的屏幕尺寸。比如,一个button的背景图片就必须要适应该button的各种形状。

如果你在使用组件时可以改变图片的大小,你很快就会发现这是一个不明确的选择。 因为运行的时候,图片会被拉伸或者压缩(这样容易造成图片失真)。避免这种情况的解决方案就是使用点9图片,这是一种能够指定哪些区域能够或者不能够拉伸的特殊png文件。

因此, 在设计的图片需要与组件一起变大变小时, 一定要使用点9.若要将位图转换为点9, 你可以用一个普通的图片开始(下图,是在4倍变焦情况下的图片显示) 。

Figure 4. button.png

你可以通过sdk中的draw9patch程序(位于tools/directory目录下) 来画点9图片。 通过左侧和顶部边框绘制像素来标记应该被拉伸的区域。 也可以通过沿右侧和底部边界绘制像素来标记。 就像下图所示一样:

Figure 5. <code>button.9.png</code>

请注意, 上图沿边界的黑色像素。在顶部边框和左边框的那些表明图像的可拉伸区域,右边和底部边框则表示内容应该放置的地方。

此外,注意.9.png这个格式,你也必须用这个格式,因为系统会检测这是一个点9图片而不是一个普通PNG图片。

当你将这个应用到组件的背景的时候(通过设置android:background=”@drawable/button”),android框架会自动正确的拉伸图像以适应按钮的大小,下图就是各种尺寸中的显示效果:

支持不同的屏幕密度(Supporting Different Densities)

使用密度独立像素(dp)

设计布局时, 要避免使用绝对像素( absolutepixels) 定义距离和尺寸。 使用像素单位来定义布局大小是有问题的。因为,不同的屏幕有不同的像素密度,所以,同样单位的像素在不同的设备上会有不同的物理尺寸。因此,在指定单位的时候,通常使用dp或者sp。一个dp代表一个密度独立像素,也就相当于在160dpi的一个像素的物理尺寸,sp也是一个基本的单位,不过它主要是用在文本尺寸上(它也是一种尺寸规格独立的像素),所以,你在定义文本尺寸的时候应该使用这种规格单位(不要使用在布尺寸上)。

  • 例如,当你是定义两个view之间的空间时,应该使用dp而不是px:
<Button android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:text="@string/clickme"    android:layout_marginTop="20dp" />
  • 当指定文本尺寸时,始终应该使用sp:
<TextView android:layout_width="match_parent"    android:layout_height="wrap_content"    android:textSize="20sp" />

提供可供选择的图片(Provide Alternative Bitmaps)

因为Android能运行在很多不同屏幕密度的设备上,所以,你应该针对不同的设备密度提供不同的bitmap资源:小屏幕(low),medium(中),high(高)以及超高(extra-high)密度。这将能帮助你在所有的屏幕密度中得到非常好的图形质量和性能。

  • 为了提供更好的用户体验,你应该使用以下几种规格来缩放图片大小,为不同的屏幕密度提供相应的位图资源:
    xhdpi: 2.0    hdpi: 1.5    mdpi: 1.0 (baseline)    ldpi: 0.75 
  • 这也就意味着如果在xhdpi设备上你需要一个200x200的图片,那么你则需要一张150x150的图片用于hdpi,100x100的用于mdpi以及75x75的用户ldpi设备。

然后将这些图片资源放到res/对应的目录下面,系统会自动根据当前设备屏幕密度自动去选择合适的资源进行加载:

MyProject/  res/    drawable-xhdpi/        awesomeimage.png    drawable-hdpi/        awesomeimage.png    drawable-mdpi/        awesomeimage.png    drawable-ldpi/        awesomeimage.png

这样放置图片资源后,不论你什么时候使用@drawable/awesomeimage,系统都会给予屏幕的dp来选择合适的图片。

实现可适应的UI流程(Implementing Adaptative UI Flows)

根据当前你的应用显示的布局,它的UI流可能会不一样。比如,当你的应用是双窗格模式,点击左边窗格的条目(item)时,内容(content)显示在右边窗格中。如果是单窗格模式中,当你点击某个item的时候,内容则显示在一个新的activity中。

确定当前布局(Determine the Current Layout)

由于每种布局的实现会略有差别,首先你可能要确定用户当前可见的布局是哪一个。比如,你可能想知道当前用户到底是处于“单窗格”的模式还是“双窗格”的模式。 你可以通过检查指定的视图(view)是否存在和可见来实现:

public class NewsReaderActivity extends FragmentActivity {    boolean mIsDualPane;    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main_layout);        View articleView = findViewById(R.id.article);        mIsDualPane = articleView != null &&                         articleView.getVisibility() == View.VISIBLE;    }}

另一个关于如何适配不同组件是否存在的例子,是在组件执行操作之前先检查它是否是可用的。 比如,在News Reader示例中,有一个按钮点击后打开一个菜单,但是这个按钮仅仅只在Android3.0之后的版本中才能显示(因为这个功能被ActionBar代替,在API 11+中定义)。所以,在给这个按钮添加事件之间,你可以这样做:

Button catButton = (Button) findViewById(R.id.categorybutton);OnClickListener listener = /* create your listener here */;if (catButton != null) {    catButton.setOnClickListener(listener);}

根据当前布局相应(React According to Current Layout)

一些操作会根据当前的布局产生不同的效果。比如,在News Reader示例中,当你点击标题(headlines)列表中的某一条headline时, 如果你的UI是双窗格模式, 内容会显示在右边的窗格中,如果你的UI是单窗格模式,会启动一个分开的Activity并显示:

@Overridepublic void onHeadlineSelected(int index) {    mArtIndex = index;    if (mIsDualPane) {        /* display article on the right pane */        mArticleFragment.displayArticle(mCurrentCat.getArticle(index));    } else {        /* start a separate activity */        Intent intent = new Intent(this, ArticleActivity.class);        intent.putExtra("catIndex", mCatIndex);        intent.putExtra("artIndex", index);        startActivity(intent);    }}

同样,如果你的应用处于多窗格模式,那么它应该在导航栏中设置带有选项卡的action bar。而如果是单窗格模式,那么导航栏应该设置为spinner widget。 所以, 你的代码应该检查哪个方案是最合适的:

final String CATEGORIES[] = { "Top Stories", "Politics", "Economy", "Technology" };public void onCreate(Bundle savedInstanceState) {    ....    if (mIsDualPane) {        /* use tabs for navigation */        actionBar.setNavigationMode(android.app.ActionBar.NAVIGATION_MODE_TABS);        int i;        for (i = 0; i < CATEGORIES.length; i++) {            actionBar.addTab(actionBar.newTab().setText(                CATEGORIES[i]).setTabListener(handler));        }        actionBar.setSelectedNavigationItem(selTab);    }    else {        /* use list navigation (spinner) */        actionBar.setNavigationMode(android.app.ActionBar.NAVIGATION_MODE_LIST);        SpinnerAdapter adap = new ArrayAdapter(this,                 R.layout.headline_item, CATEGORIES);        actionBar.setListNavigationCallbacks(adap, handler);    }}

在其他Activity中复用Fragment

在多屏幕设计时经常出现的情况是:在一些屏幕配置上设计一个窗格,而在其他屏幕配置上启动一个独立的Activity。例如,在News Reader中,新闻内容文字在大屏幕上市显示在屏幕右边的方框中,而在小屏幕中,则是由单独的activity显示的。

像这样的情况,你就应该在不同的activity中使用同一个Fragment,以此来避免代码的重复, 而达到代码复用的效果。比如,ArticleFragment在双窗格模式下是这样用的:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="horizontal">    <fragment android:id="@+id/headlines"              android:layout_height="fill_parent"              android:name="com.example.android.newsreader.HeadlinesFragment"              android:layout_width="400dp"              android:layout_marginRight="10dp"/>    <fragment android:id="@+id/article"              android:layout_height="fill_parent"              android:name="com.example.android.newsreader.ArticleFragment"              android:layout_width="fill_parent" /></LinearLayout>

在小屏幕中,它又是如下方式被复用的(没有布局文件)ArticleActivity

ArticleFragment frag = new ArticleFragment();getSupportFragmentManager().beginTransaction().add(android.R.id.content, frag).commit();

当然,如果将这个fragment定义在XML布局文件中,也有同样的效果 但是在这个例子中则没有必要,因为这个articlefragment是这个activity的唯一组件。

当你在设计fragment的时候,非常重要的一点:不要为某个特定的activity设计耦合度高的fragment。通常的做法是, 通过定义抽象接口,并在接口中定义需要与该fragment进行交互的activity的抽象方法,然后与该fragment进行交互的activity实现这些抽象接口方法。

例如,在News Reader中,HeadlinesFragment就很好的诠释了这一点:

public class HeadlinesFragment extends ListFragment {    ...    OnHeadlineSelectedListener mHeadlineSelectedListener = null;    /* Must be implemented by host activity */    public interface OnHeadlineSelectedListener {        public void onHeadlineSelected(int index);    }    ...    public void setOnHeadlineSelectedListener(OnHeadlineSelectedListener listener) {        mHeadlineSelectedListener = listener;    }}

然后,当用户选择了一个headline item之后,fragment将通知对应的activity指定监听事件( 而不是通过硬编码的方式去通知):

public class HeadlinesFragment extends ListFragment {    ...    @Override    public void onItemClick(AdapterView<?> parent,                             View view, int position, long id) {        if (null != mHeadlineSelectedListener) {            mHeadlineSelectedListener.onHeadlineSelected(position);        }    }    ...}

处理屏幕配置变化(Handle Screen Configuration Changes)

如果使用的是单独的activity来实现你界面的不同部分,你需要注意的是,屏幕变化(如旋转变化)的时候,你也应该根据屏幕配置的变化来保持你的UI布局的一致性。

例如,在传统的Android3.0或以上版本的7寸平板上,News Reader示例在竖屏的时候使用独立的activity显示文章内容,而在横屏的时候,则使用两个窗格模式(即内容显示在右边的方中) 。 这也就意味着,当用户在竖屏模式下观看文章的时候,你需要检测屏幕是否变成了横屏, 如果改变了,则结束当前activity并返回到主activity中,这样,content就能显示在双窗格模式布局中。

public class ArticleActivity extends FragmentActivity {    int mCatIndex, mArtIndex;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        mCatIndex = getIntent().getExtras().getInt("catIndex", 0);        mArtIndex = getIntent().getExtras().getInt("artIndex", 0);        // If should be in two-pane mode, finish to return to main activity        if (getResources().getBoolean(R.bool.has_two_panes)) {            finish();            return;        }        ...}

PS:关于官方的屏幕适配解决方案就暂时介绍到这,更详细的内容可以去自行查阅官方文档:develop.google.com/training/basics/supporting-devices/screens.html#create-layouts

与ScrollView的结合

虽然图片完整的展示出来了,但是却发生了轻微的形状改变。为了顺利解决这个问题,就需要与ScrollView结合来完整的展示整张图片。道理不多讲了,直接用一个实例来说明问题。
新建一个工程:test_demo_02。
然后将所需要展示的图片添加到drawable-hdpi 文件夹下面。
接下来开始在layout文件夹中设计布局。

布局代码如下:

<?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"><TextViewandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:text="与ScrollView结合的图片布局"/><ScrollViewandroid:id="@+id/myScrollView"android:layout_width="fill_parent"android:layout_height="wrap_content"android:scrollbars="vertical"android:layout_weight="4"><ImageViewandroid:id="@+id/myImageView"android:layout_width="fill_parent"android:layout_height="wrap_content"android:background="@drawable/guozi3"></ImageView></ScrollView></LinearLayout>

结合Html5 和 css3优化界面布局和配置(这块博主暂时未测试,待测试后更新)

采用HTML5和CSS3制作界面,然后在WebView视图上进行显示,然后通过JavaScript进行事件的交互是一种很不错的开发技巧。
下面举一个例子说明问题。
例如:制作一个“花卉采购计划”的表单,然后在WebView上予以显示。

有以下几项内容需要予以说明:
1、电脑的桌面浏览器不同于移动手机浏览器,因此需要在HTML的文件的head元素中设置viewport meta标签。

与layout_weight的结合(权重属性的使用)

在进行视图布局时,与layout_weight的属性值进行有效的结合,可以达到通用的布局效果。
layout_weight其实就是用来控制比例的,在实践操作中,有同学说是正比例控制,也有同学说是反比例控制。其实正比例和反比例的情况都是存在的,就看如何与layout_width和layout_height的属性值进行适当的结合啦!
俗话说:没有规矩,不成方圆。个人认为,反比例的控制效果,是无节制,无规范结合layout_width和layout_height的产物,极其不提倡,只会把人带入思维的死循环。就像某位所说,这样做,只会将简单问题复杂化,复杂问题深入化,深入问题模糊化,模糊问题抽象化,从而显示学者的高明,实则愚蠢,只是制造垃圾而已。其实,简单的,往往就是最好的。

.9.png图片的使用

PS:在前文的Google官方解决方案中,已经介绍了.9图片,这里就不再介绍。

题外话

为了适配更多的机型,并且防止用户因为应用占用内存太多,不得不卸载的问题,就要让应用支持安装的SDCard中。具体代码如下:为manifest元素增加属性:
android:installLocation="preferExternal"
切记:应用的开发要基于android2.2及以上进行开发才支持安装到SDCard。

0 0