android开发学习笔记系列(4)--android动态布局

前言

在作一个有关苏果APP的项目中,可是fuck的是,我彻底使用相对布局以后及线性布局以后发现坑爹的事情了,屏幕不能适配,这是多大的痛,意味着,必须使用相应的代码实现动态布局!呵呵,不作项目不知道,只有真正地下手去作某些事情的时候,才会发觉各类问题,本来打算先写view与framgent实现tabhost功能的博客的,可是碰到了这个棘手问题必须先把他解决了!同时不知道各位网友有什么好的方法来适配全部的安卓手机屏幕android

问题

  • 在xml文件中使用px以后出现了各类不适应屏幕的状况,控件不是大了就是小了,要知道在android世界里面有太对的屏幕尺寸了,真羡慕搞苹果开发的人!
  • UI变得奇丑无比
  • 控件太多的误差了!

解决之道

其实解决之道有不少,我选用的是使用代码计算等比例高宽,让其在相应的屏幕上显示相应的比例高度就能够了!固然网上有不少都是给的建议,却没有实实在在解决问题的博客!(但愿集思广益,可以获得一个适合所有屏幕类型的架包,方便全部的安卓开发人员)工具

关于网上的建议

网上的建议,我进行了概括:布局

1、关于布局适配

  1. 不要使用绝对布局
  2. 尽可能使用match_parent 而不是fill_parent 。
  3. 可以使用权重的地方尽可能使用权重(android:layout_weight)
  4. 若是是纯色背景,尽可能使用android的shape 自定义。
  5. 若是须要在特定分辨率下适配,能够在res目录上新建layout-HxW.xml的文件夹。好比要适配1080x1800的屏幕(魅族MX3采用此分辨率)则新建layout-1800x1080.xml的文件夹,而后在下面定义布局。Android系统会优先查找分辨率相同的布局,若是不存在则换使用默认的layout下的布局。

2、术语和概念

  • 四种屏幕尺寸分类:: small, normal, large, and xlarge
  • 四种密度分类: ldpi (low), mdpi (medium), hdpi (high), and xhdpi (extra high)
  • 须要注意的是: xhdpi是从 Android 2.2 (API Level 8)才开始增长的分类.
  • xlarge是从Android 2.3 (API Level 9)才开始增长的分类.
  • DPI是“dot per inch”的缩写,每英寸像素数。

通常状况下的普通屏幕:ldpi是120,mdpi是160,hdpi是240,xhdpi是320。字体

3、如何作到自适应屏幕大小呢?

一、界面布局方面

须要根据物理尺寸的大小准备5套布局,layout(放一些通用布局xml文件,好比界面中顶部和底部的布局,不会随着屏幕大小变化,相似windos窗口的title bar),layout-small(屏幕尺寸小于3英寸左右的布局),layout-normal(屏幕尺寸小于4.5英寸左右),layout-large(4英寸-7英寸之间),layout-xlarge(7-10英寸之间)this

二、图片资源方面

须要根据dpi值准备5套图片资源,drawable,drawalbe-ldpi,drawable-mdpi,drawable-hdpi,drawable-xhdpi设计

Android有个自动匹配机制去选择对应的布局和图片资源code

4、两种获取屏幕分辨率信息的方法:

DisplayMetrics metrics = new DisplayMetrics();
Display display = activity.getWindowManager().getDefaultDisplay();
display.getMetrics(metrics);//这里获得的像素值是设备独立像素dp
//DisplayMetrics metrics=activity.getResources().getDisplayMetrics(); 这样得到的参数信息不正确,不要使用这种方式。

不能使用android.content.res.Resources.getSystem().getDisplayMetrics()。这个获得的宽和高是空的。orm

5、关于图片制做

关于设计

设计图先定下一个要设计的尺寸,并且尽可能采用在目前最流行的屏幕尺寸(好比目前占屏幕比重比较多的是480系列,也便是480x800或者400x854,下面的图标制做也在次基础上进行比例的换算)上设计。
先了解一下屏幕的级别:xml

说明:htm

  • 屏幕级别:
    注意屏幕级别是按照密度分级,和像素没有关系。若是非要让密度和像素扯上关系,则须要一个参照系,android使用mdpi级别做为标准参照屏幕,也就是说在320x480分辨率的手机上一个密度能够容纳一个像素。而后其余密度级别则在此基础上进行对比。若是理想状况下,480x800的屏幕一个密度能够容纳1.5个像素。

  • 物理大小:
    单位是英寸而不是像素,也就说一个英寸在任何分辨率下显示的大小都是同样的,可是像素在密度不一样的手机里面显示的实际的大小是不同的(这就是为何android手机须要适配的缘由)。
    而后就是重点。

    假设1像素在160密度下显示1英寸,则1像素在240密度基础上显示大约0.67英寸,在320密度下显示0.5英寸。因而就出现一种状况,在电脑上的一个像素,在不一样的手机上看实际的大小不同。那么怎么让“设计效果”在不一样的手机上看起来显示的区域同样呢?

仍是假设一个像素在160密度下的显示在一个密度内,也假设就是一英寸。那么须要几个像素才能在240密度级别下显示在一英寸范围内呢?答案是1.5个像素(根据上图的比率换算)。
了解了这个关系,接下来就是图标的制做。

关于切图

关于切图有几个建议:

  1. 长宽最好是3的倍数(根据android的推荐logo图标的大小是48(mdpi),72(hdpi),96(xhdpi)得出的最小公约数)。
  2. 长宽最好是偶数。由于奇数在进行等比压缩的时候可能有问题。
  3. 根据上面两条,若是长宽是6的倍数最理想。
  4. 若是能够拉伸而不改变设计意图的状况下,好比纯色背景,则使用android的9path工具制做成.9的图片。

关于图标的适配。

而后接下来的一切就和设计稿没什么关系。在切好图的基础上,根据屏幕密度、像素和实际大小的比例关系。假如设计司在480x800的分辨率下作好了设计图,而且切好图,若是你须要适配720x1280屏幕,该怎么作?根据比例,他们的关系是2:3,因而你须要按照1.5倍比例制做图标,好比你在480x800的设计稿上切下来一个20*20像素的图,那么你就须要制做一个等比放大成30x30像素的图标,这样同一个图标在480x800的屏幕和720x1280的屏幕上显示的实际大小才同样。同理,若是你须要适配xxhdpi则须要在20x20的基础上制做一个等比放大成40x40像素的图标。

关于图标的目录

480*800切下来的图咱们放在drawable-hdpi目录下,按照2:3放大的图标放在drawable-xhdpi目录下,按照2倍放大的图标放在drawable-xxhdpi目录下。

android会根据手机的密度优先查找对应的目录的资源,
好比408800分辨率下的手机若是密度是160,则自动加载drawable-hdpi这个目录下的图标,
若是720
1280密度是240的手机自动加载drawable-xhdpi这个目录下的图标。若是没有这个文件夹,则查找和240最接近的对应密度文件夹。

有关我的的解决方法

我我的获得的启示就是我在设计过程当中尽可能使控件不是使用数值,也就是说我在xml文件所使用的基本都是layout_weight\android:gravity="center"等,若是迫不得得以使用的话,就先写着,而后经过相应的代码来适配动态布局

代码实现动态布局

目前我所使用的方法呢就是本身写个类,将view传进去进行适配,同时注意了个人方案是能够更改你原来所假设的屏幕宽度,而后一次性地进行适配!

package com.samuel.demosuguo;

import android.content.Context;
import android.util.DisplayMetrics;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
/**
 * Created by samuelwnb on 2015/3/14.
 */
public class Autosize {

    int screenwidth = 640;//默认屏幕宽度为640

    /***
     * 获得默认屏幕宽度
     * @return
     */
    public int getScreenwidth() {
        return screenwidth;
    }

    /***
     * 更改默认屏幕宽度
     * @param screenwidth
     */
    public void setScreenwidth(int screenwidth) {
        this.screenwidth = screenwidth;
    }

    //实际屏幕大小
    static int screensize = 0;
    public static void setScreensize(int screensize) {
        Autosize.screensize = screensize;
    }


    /**
     * 获取屏幕的大小
     * @param context//为activity
     * @return 实际屏幕的打下
     */
    public int Metricwidth(Context context){
        DisplayMetrics metric = new DisplayMetrics();
        metric = context.getResources().getDisplayMetrics();
        return metric.widthPixels;
    }
    //获取直接获取屏幕的实际宽度
    public void GetrealScreenwidth(Context context){
        DisplayMetrics metric = new DisplayMetrics();
        metric = context.getResources().getDisplayMetrics();
        setScreensize(metric.widthPixels);
    }
    //设置线性布局下的线性高度
    public void llinearlayoutheight(int px, LinearLayout linearLayout) {
        LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) linearLayout.getLayoutParams();
        if(screensize != 0) {
            layoutParams.height = px * screensize / screenwidth;
            linearLayout.setLayoutParams(layoutParams);
        }
    }

    /***********************
    控件设置
     */
    //自动设置设置字体的大小
    public int autosettextsize(int sp){
        if(screensize != 0) {
            return sp * screensize / screenwidth;
        }
        else {
            return sp;
        }

    }
    /**
     * 相对布局中的不一样设置高度
     */
    //设置相对布局下的相对布局高度
    public void relativeLayoutheight(int px, RelativeLayout relativeLayout) {
        RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) relativeLayout.getLayoutParams();
        if(screensize != 0) {
            layoutParams.height = px * screensize / screenwidth;
            relativeLayout.setLayoutParams(layoutParams);
        }
    }
    //设置相对布局中的相对高度带Margintop设置
    public void relativeLayoutheightwithmargintop(int px,int margintop, RelativeLayout relativeLayout){
        RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) relativeLayout.getLayoutParams();
        if(screensize != 0) {
            layoutParams.height = px * screensize / screenwidth;
            layoutParams.topMargin = margintop * screensize / screenwidth;
            relativeLayout.setLayoutParams(layoutParams);
        }
    }
    public void relativeLayoutheightmargintop(int margintop, RelativeLayout relativeLayout){
        RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) relativeLayout.getLayoutParams();
        if(screensize != 0) {
            layoutParams.topMargin = margintop * screensize / screenwidth;
            relativeLayout.setLayoutParams(layoutParams);
        }
    }
    //设置相对布局下的线性布局高度
    public void rlinearlayoutheight(int px, LinearLayout linearLayout) {
        RelativeLayout.LayoutParams relativelayout = (RelativeLayout.LayoutParams) linearLayout.getLayoutParams();
        if(screensize != 0) {
            relativelayout.height = px * screensize / screenwidth;
            linearLayout.setLayoutParams(relativelayout);
        }
    }
    public void rlinearlayoutheightwithmargintop(int px,int margintop,LinearLayout linearLayout) {
        RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) linearLayout.getLayoutParams();
        if(screensize != 0) {
            layoutParams.height = px * screensize / screenwidth;
            layoutParams.topMargin = margintop * screensize / screenwidth;
            linearLayout.setLayoutParams(layoutParams);
        }
    }
    public void rlinearlayoutheightmargintop(int margintop,LinearLayout linearLayout) {
        RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) linearLayout.getLayoutParams();
        if(screensize != 0) {
            layoutParams.topMargin = margintop * screensize / screenwidth;
            linearLayout.setLayoutParams(layoutParams);
        }
    }
   }

在这里我来举个例子:

Autosize autosize = new Autosize();
        autosize.GetrealScreenwidth(getActivity());
        RelativeLayout tophome = (RelativeLayout) findViewById(R.id.tophome);
        autosize.relativeLayoutheight(88,tophome);

步骤:

  • 先实例化我写的类
  • 获取屏幕宽度
  • 获得RelativeLayout的ID
  • 直接送入适配,但注意这里要知道你想在屏幕上显示多大!

注意的地方

必定要注意你究竟是哪一个布局下的一个布局,必须找到父view才可使用!若是想知道为何的话,你们能够去找layoutparams有关的内容!

给读者的话

那个撒,你看我如此卖命地写博客,并且仍是本身在攻克难点,就来关注个人博客呗!

相关文章
相关标签/搜索