美文网首页
屏幕适配

屏幕适配

作者: 会飞的羽天羽 | 来源:发表于2019-04-12 17:30 被阅读0次

    屏幕适配的方式

    • 限定符适配

    App会根据当前的分辨率自动选择对应分辨率的资源
    限定符适配有以下优势

    • 使用简单,无需开发者手动指定
    • Google推荐使用方式,有系统自己判断
    • 适配通过不同的xml布局完成,无需在代码中额外再写

    缺点
    需要很多xml资源
    增大了包体积

    • 百分比适配

      • google 有一个库
      • 只能使用第三方的百分比的父布局所以可扩展性较差
    • 动态代码适配

    这个就是手动在java层来做处理有三方式

    • 第一个跟百分比布局一样自己手写ViewGroup
    public class UIRelativeLayout extends RelativeLayout {
    
        private boolean flag = false;
    
        public UIRelativeLayout(Context context) {
            super(context);
        }
    
        public UIRelativeLayout(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public UIRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            if(flag) {
                //获取水平方向的缩放比
                float scaleX = UIUtils.getInstance(getContext()).getHorizontalScaleValue();
                //获取垂直方向的缩放比
                float scaleY = UIUtils.getInstance(getContext()).getVerticalScaleValue();
                int count = getChildCount();
                for (int i = 0; i < count; i++) {
                    View view = getChildAt(i);
                    LayoutParams params = (LayoutParams) view.getLayoutParams();
                    params.width *= scaleX;
                    params.height *= params.height * scaleY;
                    params.bottomMargin *= scaleY;
                    params.leftMargin *=scaleX;
                    //可以设置padding margin等值
                }
                flag = true;
            }
        }
    }
    

    上述方式需要跟百分比布局一样,需要使用自己手写的ViewGroup,子控件就可以跟平常一样了,而且不能预览

    • 第二种方式将ViewGroup的操作,抽象成一个工具类中的方法,自己手动触发
    public void updateSize(View view){
    
     //获取水平方向的缩放比
                float scaleX = UIUtils.getInstance(view.getContext()).getHorizontalScaleValue();
                //获取垂直方向的缩放比
                float scaleY = UIUtils.getInstance(view.getContext()).getVerticalScaleValue();
    
                Layoutparams params = view.getLayoutParams();
                if(params.width>0){
                     params.width*=scaleX;
                }
                if(params.height>0){
                    params.height*=scaleY;
                }
    }
    

    这种方式最为麻烦,因为每个View都需要自己手动修改

    • 第三种方式自己手动改activity的density属性
    public class Density {
        //UI图尺寸
        private static final float WIDTH = 720;
        
        private static float appDensity;
    
        private static float appScaleDensity;
    
        public static void setDensity(Application application, Activity activity) {
            DisplayMetrics metrics = application.getResources().getDisplayMetrics();
            if (appDensity == 0) {
                appDensity = metrics.density;
                appScaleDensity = metrics.scaledDensity;
                //注册的监听器主要是监听系统设置改变字体大小的。
                application.registerComponentCallbacks(new ComponentCallbacks() {
                    @Override
                    public void onConfigurationChanged(Configuration newConfig) {
                        if (newConfig != null && newConfig.fontScale != 0) {
                            appScaleDensity = newConfig.fontScale;
                        }
                    }
                    @Override
                    public void onLowMemory() {
    
                    }
                });
            }
            //根据当前屏幕宽度和UI设计图的宽相除获得density
            float targetDensity = metrics.widthPixels / WIDTH;
            float targetScaleDensity = targetDensity * (appScaleDensity / appDensity);
            int targetDensityDpi = (int) (targetDensity * 160);
    
            //将自己的desity给activity
            DisplayMetrics dm = activity.getResources().getDisplayMetrics();
            dm.density = targetDensity;
            dm.scaledDensity = targetScaleDensity;
            dm.densityDpi = targetDensityDpi;
        }
    
    }
    

    然后再需要的Activity的setContentView()之前调用即可,这种方式非常简单,而且高效,推荐使用。
    缺点暂未发现

    顺便附上UIUtils的源码
    public class UIUtils {

    public static final float STANDARD_WIDTH = 1080f;
    
    public static final float STANDARD_HEIGHT = 1980f;
    
    private static UIUtils instance;
    
    private float displayMetricsHeight ;
    
    private float displayMetricsWidth ;
    
    private float  systemBarHeight;
    
    //为了防止内存泄漏,请使用application
    public static UIUtils getInstance(Context context) {
    
        if (instance == null) {
            instance = new UIUtils(context);
        }
    
        return instance;
    }
    
    public static UIUtils getInstance() {
    
        if (instance != null) {
            return instance;
        }
        return null;
    }
    private UIUtils(Context context){
        DisplayMetrics metrics = context.getResources().getDisplayMetrics();
        systemBarHeight = getSystemBarHeight(context);
        if(metrics.widthPixels>metrics.heightPixels){
    
            displayMetricsHeight = metrics.widthPixels- systemBarHeight;
            displayMetricsWidth = metrics.heightPixels;
        }else {
            displayMetricsHeight = metrics.heightPixels-systemBarHeight;
            displayMetricsWidth = metrics.widthPixels;
        }
    
    
    
    }
    
    //获取宽度缩放比
    public float getHorizontalScaleValue(){
    
        return displayMetricsWidth/STANDARD_WIDTH;
    
    }
    
    public float getVerticalScaleValue(){
        return displayMetricsHeight/STANDARD_HEIGHT;
    }
    
    
    
    private int getSystemBarHeight(Context context){
        return getValue(context,"com.android.internal.R$dimen","system_bar_height",48);
    
    
    
    }
    
    private int getValue(Context context,String dimeClass,String system_bar_height ,int defaultVaule){
        try {
            Class<?> clz = Class.forName(dimeClass);
            Object object = clz.newInstance();
            Field field = clz.getField(system_bar_height);
            int id = Integer.parseInt(field.get(object).toString());
            return context.getResources().getDimensionPixelSize(id);
        }catch (Exception e){
            e.printStackTrace();
        }
        return 0;
    }
    

    相关文章

      网友评论

          本文标题:屏幕适配

          本文链接:https://www.haomeiwen.com/subject/athhwqtx.html