Android 适配语言、图片、横竖屏、不同版本

前言

一、适配国家语言

二、屏幕适配

(1)页面控件属性常用适配方法

(2)手机横竖屏切换兼容适配        

三、适配不同系统版本


前言

智能手机的用户分布在不同国家,且偏好各异,这就要求开发阶段兼容适配;由于各厂家生产出的安卓设备分别率不同、屏幕大小和风格也存在各异,如果手机的用户设备各异,仅用一张图片可能会出现拉伸变形模糊,影响用户体验,因此对应屏幕的兼容适配是重中之重;随着Google不断更新Android版本,每个版本的代码也有区别。Android适配技能日益成为开发者必不可少的一项专业技能。

本篇文章分别讲解了语言适配、屏幕适配、版本适配三个内容。

 

一、适配国家语言

语言适配有两种场景:一种是在手机系统里的“设置”选项中更改了系统的语言,影响的是整个手机内应用,包括系统应用和非系统应用。另一种,是用户可以手动切换某一款应用的内部语言风格,影响的范围仅仅是自身应用。

(1)手机系统语言适配

工程的根目录有个res/的目录,该目录下存放的是资源文件:如drawable、anim、layout、values。其中,value目录下存放/strings.xml,它用来设置项目中需要的字符串对象,可以理解为应用文本显示的内容。如下,默认的应用名称。



     APP_NAME 


 value目录会根据手机语言的改变而加载不同String.xml。因此,在res/目录下创建多个values/strings.xml文件,且values目录需要改名,例如:

Android 适配语言、图片、横竖屏、不同版本_第1张图片

res/
       values/             默认
           strings.xml
       values-en/       英文
           strings.xml

       values-es/       西班牙
           strings.xml
       values-fr/         法语
           strings.xml

英语:/values-en/strings.xml:



    My Application
    Hello World!

西班牙语:/values-es/strings.xml:



    Mi Aplicación
    Hola Mundo!

法语:/values-fr/strings.xml:



    Mon Application
    Bonjour le monde !

最后,我们就可以在代码中使用R.string.语法来引用字符串资源就可以了。配置好了就不怕手机系统语言切换了,但是APP内部语言切换就得换一种实现方式了。

(2)应用切换语言

首先,通过Configuration(配置信息)这个类,获取应用当前的语言,然后修改该配置中的语言,最后更新配置,重启一下Activity才能生效。其次,还有一个比较重要的类Locale(地点),如下。

public final class Locale implements Cloneable, Serializable {
    static private final  Cache LOCALECACHE = new Cache();
    /** 中文
     */
    static public final Locale CHINESE = createConstant("zh", "");
    /**英文
     */
    static public final Locale ENGLISH = createConstant("en", "");
    /** 法文
     */
    static public final Locale FRENCH = createConstant("fr", "");
    /** 德文
     */
    static public final Locale GERMAN = createConstant("de", "");
    /**印度文
     */
    static public final Locale ITALIAN = createConstant("it", "");
    /** 日文
     */
    static public final Locale JAPANESE = createConstant("ja", "");
    /** 韩文
     */
    static public final Locale KOREAN = createConstant("ko", "");
.....
}

点击切换按钮,实现中英文语言切换。 

        @Override
        public void onClick(View v) {
            //1、获取当前语言
            String current_language;
//          注:Locale.getDefault().getLanguage();该方法获取系统语言,对于应用内切换不适用。
            Configuration config = getResources().getConfiguration();
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){//api24 ,android 7.0
                current_language = config.getLocales().toLanguageTags();
            }else{
                current_language = config.locale.getLanguage();
            }
            //2、切换中英语言
            if (current_language.equals(Locale.CHINESE.getLanguage()) || current_language.equals("zh-CN") ){
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
                    config.getLocales();
                    config.setLocale(Locale.ENGLISH);
                }else{
                    config.locale = Locale.ENGLISH;
                }
            }else if (current_language.equals(Locale.ENGLISH.getLanguage())){
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
                    config.getLocales();
                    config.setLocale(Locale.CHINESE);
                }else{
                    config.locale = Locale.CHINESE;
                }
            }
            //3、更新应用配置
            getBaseContext().getResources().updateConfiguration(config,getBaseContext().getResources().getDisplayMetrics());
            //4、重启Activity
            recreate();
        }

 

二、屏幕适配

为什么做屏幕适配?

目前市场上的安卓手机设备的分别率各不相同、屏幕大小和风格(9.0 刘海屏适配方案)也存在各异。例如,项目中仅用一张图片,在多款不同大小的手机上表现可能会出现拉伸变形模糊,影响用户体验。其次,Android设备是支持屏幕旋转功能的,如果不做适配那问题就大了,轻者布局错位,重则生命周期重刷发生异常崩溃。

这里归纳总结的屏幕适配有三个方向:图片适配、布局适配、旋转适配。

(1)图片适配

在项目开发的过程中经常会用到图片,因此有一个重要的沟通,就是与UI设计师的图片大小分别率的沟通。一般UI设计师画图的实现步骤:①在photoshop、coreldraw、Sketch中制作好图标,设置图标的内外边距,单位是px ;②保存输出为PNG位图图片③而开发者在实际开发中“dp”做为单位的更加常见,所以就会涉及到“px”“dp”互转的问题。

dp是一种基于屏幕密度的抽象单位,也叫虚拟像素,在不同的像素密度的设备上会自动适配。原理:我们知道px是像素单位,一款设备的屏幕上会散列着物理像素点,也叫分别率,在屏幕上每英寸160像素点时,1dp是等于1px的。不同手机屏幕尺寸大小不同,分辨率也不同。

Google在系统基本对于设备的适配是以dp为单位的,db会跟着屏幕大小仍保持相对应的px大小。参考下表:

计算公式:px = dp * (dpi/160) ;   dp = dpi/160/px;

分辨率级别 DPI 比率     分别率(px)

 dp 换算 px关系

ldpi(Low:低) 120 0.75 240*320  1dp  = 0.75px
mdpi(Middle:中) 160 1 320*480  1dp = 1px
hdpi(High:高) 240 1.5 480*800  1dp =1.5px
xhdpi(超高,2倍图) 320 2 1280*720 1dp = 2px
xxhdpi(3倍图) 480 3 1920*1080 1dp =3px
xxxhdpi(4倍图) 640 4 3840*2160 1dp =4px

因此,我们可以根据dp与px的换算关系,让UI设计师给出计算后的多套图。例如,xhdpi 级别的设备画了一张200*200px的图,那么hdpi150*150pxmdpi100*100pxldpi75*75px....然后,将这些文件放入相应的drawable资源目录中,当引用@drawable/image时系统会根据屏幕的分辨率选择恰当的bitmap。

  res/
        drawable-xhdpi/
              image.png
        drawable-hdpi/
               image.png
        drawable-mdpi/
              image.png
        drawable-ldpi/
               image.png

另外,解释一下为什么上面表格有两行标位红色,原因是2倍图和3倍图是主流占比,在友盟统计中显示如下:

Android 适配语言、图片、横竖屏、不同版本_第2张图片

2、XML布局适配

Layout适配尺寸有4种:小(small),普通(normal),大(large),超大(xLarge)

我们在资源文件layout目录创建不同尺寸布局文件,系统会根据运行的设备屏幕尺寸,选择在与之对应的layout目录中加载layout。如下:

res/
        layout(-normal)/默认
            main.xml
        layout-large/大
            main.xml
        layout-xlarge/超大
            main.xml
        layout-small/小
            main.xml

注意:记得在AndroidManifest.xml文件中设置多分辨率支持!!!


其他屏幕适配常用适配方法

  1. 尽量使用线性布局(LinearLayout)和相对布局(RelateLayout),尽量不使用绝对布局(AbsoluteLayout)和帧布局(FrameLayout)。
  2. 尽量使用wrap_content、mach_parent让view自适应或最大化,尽量不要写宽高的值。
  3. 使用线下布局的百分比weight权重时,要把宽度写成“0dp“,如果写成wrap_coent会使布局效果不佳等问题。
  4. 尽量使用android的Shape自定义view背景,这样会随之自适应。
  5. ImageView的ScaleType有五种方式(center,centerCrop,centerInside,fieCenter,fieXY),尽量使用fieCenter按比例扩大至view宽度,能取得较好适配和显示效果。
  6. 获取屏幕分辨率信息,进行动态适配:DisplayMetrics metrics =newDisplayMetrics();  getWindowManager().getDefaultDisplay().getMetrics(metrics);

3、横竖屏适配

在AndroidMaifest.xml中activity中的属性 android:screenOrientation="",可以设置屏幕为固定横屏或竖屏。值有三种类型:属性landscape是横向,portrait是纵向,"sensor"是由物理的感应器来决定。

如果用户手动旋转设备,此时不仅要注意Activity会经过销毁到重建的问题,还要注意布局兼容问题。 适配横向屏幕,首先再创建一份layout-land布局文件,系统会根据运行的设备屏幕方向情况自动加载对应的layout。如下:

    res/
        layout-port/     竖屏
            main.xml
        layout-land/     横屏
            main.xml
       layout-large-land/     也是可以与不同屏幕大小一起使用
            main.xml
 

也可以只在layout文件夹下创建不同xml布局,通过Configuration().orientation来判断当前是横屏landscape还是竖屏portrait,然后加载相对应的布局文件即可。

重建问题:

如果不需要重新走一遍Activity的生命周期,则在AndroidManifest.xml中activity标签下设置android: configChanges="orientation|keybordHidden|screenSize",这样的话就不会重复调用activity的生命周期方法,切换时只会调用 onConfigurationChanged(Configuration newconfig)方法。

如果一切让它销毁在重建,只不过这过程中把需重要的值保存起来。重建后在取出来就行了。

	//onResume之后调用,onPause()之前执行
    @Override
	protected void onSaveInstanceState(Bundle outBundle) {
		super.onSaveInstanceState(outBundle);
 		outBundle.putBoolean("RoadChange", mChange);
	}
	

    //onResume之前调用 ,onStart之后执行
	@Override 
	protected void onRestoreInstanceState(Bundle savedInstanceState) {
		super.onRestoreInstanceState(savedInstanceState);
		mChange = savedInstanceState.getBoolean("RoadChange");
	}

三、适配不同系统版本

新的Android版本会为我们的app提供更棒的API,但我们的app仍应支持旧版本的Android,直到更多的设备升级到新版本为止。Android 5.0、6.0、7.0、8.0、9.0 新特性,DownloadManager踩坑记

首先,在项目清单文件中指定最小和目标API级别。具体来说,元素中的minSdkVersion和targetSdkVersion 属性,标明在设计和测试app时,最低兼容API的级别和最高适用的API级别(这个最高的级别是需要通过我们的测试的)。例如:


    
    ...

其次,是在代码中判断检查版本信息。Android在Build常量类中提供了对每一个版本的唯一代号,在我们的app中使用这些代号可以建立条件,保证依赖于高级别的API的代码,只会在这些API在当前系统中可用时,才会执行。

private void setUpActionBar() {
    // Make sure we're running on Honeycomb or higher to use ActionBar APIs
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        ActionBar actionBar = getActionBar();
        actionBar.setDisplayHomeAsUpEnabled(true);
    }
}

最后,使用项目的风格和主题跟随系统版本改变外观。Android提供了用户体验主题,为app提供基础操作系统的外观和体验。这些主题可以在manifest文件中被应用于app中。通过使用内置的风格和主题,我们的app自然地随着Android新版本的发布,自动适配最新的外观和体验.

使activity看起来像对话框:


使activity有一个透明背景:


应用在/res/values/styles.xml中定义的自定义主题:


使整个app应用一个主题(全部activities)在元素中添加android:theme属性:


更多关于创建和使用主题,详见Styles and Themes。


 

你可能感兴趣的:(Android)