Android多屏适配

android因为开源的关系,出现了很多不同尺寸的android手机,为了更好的用户体验,我们应该让开发的应用适应更多的屏幕。所以需要学习多屏适配,以下主要收集解决方法。

1、字体大小采用“sp”单位,比如24sp

不使用奇数、小数,以免丢失精度


2、使用wrap_content, fill_parent, 或者 dp 来定义layout的尺寸大小。

使用dp来定义组件的尺寸的好处是:系统会根据设备dpi自动转换尺寸的大小。举个列子,在密度为160dpi的机器上,假如你定义组件的尺寸是100dp,那么显示的实际大小就是100px。而在密度为240的机器上,系统会把它显示成px=100 * (240/160) px= 150px大小的尺寸。通过这种转换,可以达到在不同分辨率的设备上,对于同一个组件,显示的物理尺寸是相同的,不会出现变大或者变小的情况。


3、多使用RelativeLayout(相对布局),禁用绝对布局,在使用线性布局的时候多使用weight(权重)


4、在后缀不同的drawable文件夹里面放不同大小的图片尺寸

drawable- hdpi、drawable- mdpi、drawable-ldpi的区别:
  (1)drawable-hdpi里面存放高分辨率的图片,如WVGA (480×800),FWVGA (480×854)
  (2)drawable-mdpi里面存放中等分辨率的图片,如HVGA (320×480)
  (3)drawable-ldpi里面存放低分辨率的图片,如QVGA (240×320)
  系统会根据机器的分辨率来分别到这几个文件夹里面去找对应的图片。


drawable的小技巧http://blog.csdn.net/guolin_blog/article/details/50727753

      实际情况下,公司的UI们通常就只会给一套图片资源,想让他们针对每种密度的设备都设计一套图片资源,并且还是按照我们上面讲的缩放比例规则来设计,就有点想得太开心了。没错,这个就是现实情况,那么在这种情况下,我们应该将仅有的这一套图片资源放在哪个密度的文件夹下呢?
      可以这样来分析,根据我们刚才所学的内容,如果将一张图片放在低密度文件夹下,那么在高密度设备上显示图片时就会被自动放大,而如果将一张图片放在高密度文件夹下,那么在低密度设备上显示图片时就会被自动缩小。那我们可以通过成本的方式来评估一下,一张原图片被缩小了之后显示其实并没有什么副作用,但是一张原图片被放大了之后显示就意味着要占用更多的内存了。因为图片被放大了,像素点也就变多了,而每个像素点都是要占用内存的。

      图片资源应该尽量放在高密度文件夹下,这样可以节省图片的内存开支,而UI在设计图片的时候也应该尽量面向高密度屏幕的设备来进行设计。就目前来讲,最佳放置图片资源的文件夹就是drawable-xxhdpi。那么有的朋友可能会问了,不是还有更高密度的drawable-xxxhdpi吗?干吗不放在这里?这是因为,市面上480dpi到640dpi的设备实在是太少了,如果针对这种级别的屏幕密度来设计图片,图片在不缩放的情况下本身就已经很大了,基本也起不到节省内存开支的作用了。

 drawable横屏竖屏目录区分

a) drawable-hdpi该图片适用于横屏,也适用于竖屏;

b) drawable-land-hdpi,当屏幕为横屏,且为高密度时,加载此文件夹的资源;

c) drawable-port-hdpi,当屏幕为竖屏,且为高密度时,加载此文件夹中的资源。其他同理。


对于四种密度low-dpi, medium-dpi, high-dpi, extra high-hdpi的设备,在指定一个相同的图像文件时,分配给各种密度的图像文件的尺寸应该符合以下比例:3:4:6:9. 也就是要符合密度比例(120:160:240:360).

举个列子,假如我们要在一个密度为160dpi的设备上使用到一个48 * 48的图像文件。那么对于其它密度的设备,我们要准备的图像文件分别是:

low-density (120dpi) : 36×36

medium-density(160dpi): 48×48

high-density (240dpi) : 72×72

high-density (360dpi): 96×96



5、创建不同的layout文件夹

Android中一般分为四种尺寸: small, normal, large, xlarge,一般创建不同的布局来适配这四种尺寸。


layout-smalllayout-large  , layout-xlarge , layout-xlarge-land

适配不同尺寸可以创建下面目录:

 layout/

            main.xml

layout-large/

            main.xml

适配横屏、竖屏可以创建如下目录:

layout/

            main.xml

layout-land/

            main.xml

如果需要同时适配,需要更多的条件:

  layout/              # default (portrait)

            main.xml

  layout-land/         # landscape

            main.xml

  layout-large/        #large (portrait)

            main.xml

 layout-large-land/   # largelandscape

            main.xml

使用最小宽度限定符:上面讲到的large,到底是多大,这个时候就可以使用最小宽度限定符,它允许我们对屏幕的宽度指定一个最小值(以dp为单位),然后以这个最小值为零界点,屏幕大于这个值得设备就加载该布局,

当程序运行在屏幕大于600dp的设备上,就会加载layout-sw600dp下的文件


6、使用拉伸位图,即点9图

点九图,是Android开发中用到的一种特殊格式的图片,文件名以”.9.png“结尾。这种图片能告诉程序,图像哪一部分可以被拉升,哪一部分不能被拉升需要保持原有比列。运用点九图可以保证图片在不模糊变形的前提下做到自适应。点九图常用于对话框背景图片中。

比如下图,是使用了QQ聊天气泡的聊天截图,

 

使用的背景其实就是右边这小图,通过制作.9图让该背景自适应不同的聊天内容




Android SDK中提供了编辑9-Patch图片的工具,在tools目录下draw9patch.bat,能够立刻看到编辑后的拉伸效果,也可以直接用其他图片编辑工具编辑。


7、限制屏幕的方向

软件的横竖屏切换也会改变布局的,所以如果不想去解决用户横竖屏之间切换的布局问题,最简单的办法就是在项目的 AndroidManifest.xml中找到你所指定的activity中加上android:screenOrientation属性,

他有以下几个参数: 

"unspecified" 默认值 由系统来判断显示方向.判定的策略是和设备相关的,所以不同的设备会有不同的显示方向. 

"landscape" 横屏显示(宽比高要长) 

"portrait" 竖屏显示(高比宽要长)

 "user" 用户当前首选的方向

 "behind" 和该Activity下面的那个Activity的方向一致(在Activity堆栈中的) 

"sensor" 有物理的感应器来决定。如果用户旋转设备这屏幕会横竖屏切换。

 "nosensor" 忽略物理感应器,这样就不会随着用户旋转设备而更改了 ( "unspecified"设置除外 )


8、配置manifest 中的supports_screens

可以查看Multiple Screens Support.的设置,在manifest 中,加入supports-screens标签支持多种屏幕显示:

1
2
3
4
5
6
7
8
< manifest  xmlns:android="http://schemas.android.com/apk/res/android">
     < supports-screens  android:largescreens="true"
         android:normalscreens="true"
         android:smallscreens="true"
         android:resizable="true"
         android:anydensity="true">
     </ supports-screens >
</ manifest >


9、如何让自定义控件可以配置长度和自适应所有设备:

在所有自定义控件中,都不要硬编码长度,宽度等尺寸;应该先根据基线160dpi调式得到控件在标准基线下控件的最佳值,假如设为width。然后通过density = getResources().getDisplayMetrics().density 获取当前设备相对于基线的缩放值,然后得到一个最佳值value = width * density. 在用这个值去绘制控件的UI。这样我们就可以在配置文件中随时改动控件的大小。

注解:density = getResources().getDisplayMetrics().density

这个值在不同密度的设备中返回不同的值:

160dpi:1

240dpi: 1.5

120dpi: 0.75

….类推


多屏适配中巧用fragment适配平板与手机参考出处:http://blog.csdn.net/guolin_blog/article/details/8881711

      为了让界面可以在平板上更好地展示,Android在3.0版本引入了Fragment(碎片)功能,它非常类似于Activity,可以像Activity一样包含布局。Fragment通常是嵌套在Activity中使用的,现在想象这种场景:有两个Fragment,Fragment 1包含了一个ListView,每行显示一本书的标题。Fragment 2包含了TextView和ImageView,来显示书的详细内容和图片。

如果现在程序运行竖屏模式的平板或手机上,Fragment 1可能嵌入在一个Activity中,而Fragment 2可能嵌入在另一个Activity2中,如下图所示:


而如果现在程序运行在横屏模式的平板上,两个Fragment就可以嵌入在同一个Activity中了,如下图所示:


由此可以看出,使用Fragment可以让我们更加充分地利用平板的屏幕空间,下面我们一起来探究下如何使用Fragment达到适配。

fragment1和fragment2的布局都非常简单,这里就不说了。这里重点是代码中怎么知道现在该显示哪一种布局

解决思路:

在不同的layout文件夹下面创建相同名字的xml文件,当程序运行在屏幕大于600dp的设备上,就会加载layout-sw600dp下的文件(即:双页模式),我们只需要在新闻标题点击的时候去判断当前显示的是双页模式还是单页模式,如果是单页模式,则跳转activity来显示新闻详细内容,如果是双页模式,则直接刷新fragment2来显示新闻内容。


layout/

            activity_main.xml  //在单页模式下, 只会加载一个新闻标题的fragment

layout-sw600dp/

            activity_main.xml  //双页模式下我们同时引入了两个fragment

layout/activity_main.xml代码:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
    <fragment
         android:id="@+id/news_title_fragment"
         android:name="com.example.fragmentbestpractice.NewsTitleFragment"
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
</LinearLayout>

layout/layout-sw600dp.xml代码

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent" >
    <fragment
         android:id="@+id/news_title_fragment"
         android:name="com.example.fragmentbestpractice.NewsTitleFragment"
         android:layout_width="0dp"
         android:layout_height="match_parent"
         android:layout_weight="1" />
    <FrameLayout
         android:id="@+id/news_content_layout"
         android:layout_width="0dp"
         android:layout_height="match_parent"
         android:layout_weight="3" >
        <fragment
             android:id="@+id/news_content_fragment"
             android:name="com.example.fragmentbestpractice.NewsContentFragment"
             android:layout_width="match_parent"
             android:layout_height="match_parent" />
    </FrameLayout>
</LinearLayout>

MainActivity代码:

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);
    }
}

在fragment1中去判断是加载的单页还是双页:

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    if (getActivity().findViewById(R.id.news_content_layout) != null) {
        isTwoPane = true; // 可以找到news_content_layout布局时,为双页模式
    } else {
        isTwoPane = false; // 找不到news_content_layout布局时,为单页模式
    }
}
标题点击的时候,去判断是刷新数据还是跳转页面:

 @Override
 public void onItemClick (AdapterView < ? > parent, View view,int position,long id){
    News news = newsList.get(position);
    if (isTwoPane) {
        // 如果是双页模式,则刷新NewsContentFragment中的内容
        NewsContentFragment newsContentFragment = (NewsContentFragment)
                getFragmentManager().findFragmentById(R.id.news_
                        content_fragment);
        newsContentFragment.refresh(news.getTitle(), news.getContent());
    } else {
        // 如果是单页模式,则直接启动NewsContentActivity
        NewsContentActivity.actionStart(getActivity(), news.getTitle(),
                news.getContent());
    }
}
这样就可以在平板和手机上都可以有很好的显示效果了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值