屏幕适配

原因:Android设备碎片化,导致APP的界面元素在不同的屏幕尺寸上显示不一致。
目的:让布局,布局组件,资源,用户界面流程,匹配不同的屏幕尺寸。

屏幕适配常见方式
  • 布局适配
    1、避免写死控件尺寸,使用match_parent,wrap_content。
    2、LinearLayout使用android:layout_weight=“1”,android:weightSum="4"等等。
    3、RelativeLayout的android:layout_centerInParent=“true”,
    android:layout_centerVertical=“true”,android:layout_centerHorizontal=“true”
    4、ConstraintLayout(RelativeLayout的加强版,更强大的功能)
    5、百分比库

  • 图片资源适配
    1、使用.9或者svg图实现缩放
    2、使用多套位图匹配不同的屏幕分辨率

  • 用户流程适配
    1、根据业务逻辑执行不同的跳转逻辑
    2、根据别名展示不同的界面

  • 限定符适配
    1、分辨率限定符mipmap-hdpi,drawable-hdpi等等
    2、尺寸限定符:layout-small,layout-large等
    3、最小宽度限定符:values-sw360dp,values-sw480dp等
    4、屏幕方向限定符:layout-land,layout-port等

  • 刘海屏适配
    Android 9.0官方适配
    华为、OPPO、VIVO,、小米等等

一、像素适配

自定义像素适配,自定义View来适配
以一个特定宽度尺寸的设备为参考,在View的加载过程中,根据当前设备的实际像素换算出目标像素,再作用在控件上。

  • 工具类,计算屏幕宽高,求出目标View和参考图的缩放比
public class ScreenAdapterUtils {    //设计稿参考宽高    private static final float STANDARD_WIDTH = 1080;    private static final float STANDARD_HEIGHT = 1920;    //屏幕显示宽高    private int mScreenWidth;    private int mScreenHeight;    private static ScreenAdapterUtils mInstance;    public static ScreenAdapterUtils getInstance(Context context) {        if (mInstance == null) {            synchronized (ScreenAdapterUtils.class) {                if (mInstance == null) {                    mInstance = new ScreenAdapterUtils(context.getApplicationContext());                }            }        }        return mInstance;    }    private ScreenAdapterUtils(Context context) {        if (mScreenHeight == 0 || mScreenWidth == 0) {            WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);            if (wm != null) {                DisplayMetrics metrics = new DisplayMetrics();                wm.getDefaultDisplay().getMetrics(metrics);                if (metrics.widthPixels > metrics.heightPixels) {                    // 横屏                    mScreenWidth = metrics.heightPixels;                    mScreenHeight = metrics.widthPixels;                } else {                    // 竖屏                    mScreenWidth = metrics.widthPixels;                    mScreenHeight = metrics.heightPixels - getStatusBarHeight(context);                }            }        }    }    public int getStatusBarHeight(Context context) {        int resId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");        if (resId > 0) {            return context.getResources().getDimensionPixelSize(resId);        }        return 0;    }    //获取水平方向的缩放比例    public float getHorizontalScale(){        return mScreenWidth / STANDARD_WIDTH;    }    //获取垂直方向的缩放比例    public float getVerticalScale(){        return mScreenHeight / STANDARD_HEIGHT;    }}
  • 适配的ViewGroup,在onMeasure中根据缩放比,重新去计算目标View的宽高
public class ScreenAdapterLayout extends LinearLayout {    /**     * 是否被测量     */    private boolean isMeasure;    public ScreenAdapterLayout(Context context) {        super(context);    }    public ScreenAdapterLayout(Context context, @Nullable AttributeSet attrs) {        super(context, attrs);    }    public ScreenAdapterLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        if (!isMeasure) {            // 获取横向缩放比            float horizontalScale = ScreenAdapterUtils.getInstance(getContext()).getHorizontalScale();            // 获取纵向缩放比            float verticalScale = ScreenAdapterUtils.getInstance(getContext()).getVerticalScale();            // 重新计算所有子View的尺寸            int childCount = getChildCount();            for (int i = 0; i < childCount; i++) {                // 获取子View重新进行测量                View child = getChildAt(i);                LayoutParams params = (LayoutParams) child.getLayoutParams();                // 根据宽高的缩放比,重新计算目标View的真实宽高                params.width = (int) (params.width * horizontalScale);                // 这样缩放,如果我们设置的宽高是一样的,你会发现在水平和数值方向上的缩放比不一样的时候                // 控件会被拉伸,不能达到我们想要的正确的相同宽高                // params.height = (int) (params.height * verticalScale);                // 如果改成都使用水平的缩放比,就刚好正确                params.height = (int) (params.height * horizontalScale);                // 计算目标View四周的间距                params.leftMargin = (int) (params.leftMargin * horizontalScale);                params.rightMargin = (int) (params.rightMargin * horizontalScale);                params.topMargin = (int) (params.topMargin * verticalScale);                params.bottomMargin = (int) (params.bottomMargin * verticalScale);            }        }        super.onMeasure(widthMeasureSpec, heightMeasureSpec);    }}

布局文件

<com.dh.summarize.view.ScreenAdapterLayout xmlns:android="http://schemas.android.com/apk/res/android"        android:orientation="vertical"        android:layout_width="match_parent"        android:layout_height="match_parent">    <TextView            android:layout_width="540px"            android:layout_height="540px"            android:background="@color/colorAccent"/></com.dh.summarize.view.ScreenAdapterLayout>

自定义View像素适配,不能穿透适配,也就是当前容器是像素适配容器,它其中如果还有容器需要适配,也依然要使用像素适配容器。造成的结果就是如果需求更改,会改的很惨。O(∩_∩)O哈哈~。

二、百分比布局适配

自定义百分比适配,继承对应的ViewGroup,在使用百分比适配的情况下,不影响ViewGroup本身的属性的使用。

Google本身提供了百分比库,我们正常情况下需要使用直接导入Google的百分比库就好。

以下例子我们直接继承RelativeLayout,在

  • onMeasure()中去重新计算我们的宽高。
  • 继承RelativeLayout的LayoutParams,实现以下构造方法LayoutParams(Context c, AttributeSet attrs),在构造方法中去获取我们自定义属性,这个可以参考RelativeLayout本身的实现。
  • 实现generateLayoutParams,将我们自己的LayoutParams返回
public class PercentRelativeLayout extends RelativeLayout {    public PercentRelativeLayout(Context context) {        super(context);    }    public PercentRelativeLayout(Context context, AttributeSet attrs) {        super(context, attrs);    }    public PercentRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        // 获取父容器的宽高        int parentWidth = MeasureSpec.getSize(widthMeasureSpec);        int parentHeight = MeasureSpec.getSize(heightMeasureSpec);        final int childCount = getChildCount();        for (int i = 0; i < childCount; i++) {            View child = getChildAt(i);            ViewGroup.LayoutParams layoutParams = child.getLayoutParams();            // 判断LayoutParams是否是百分比属性            if (layoutParams instanceof LayoutParams) {                LayoutParams params = (LayoutParams) layoutParams;                float widthPercent = params.widthPercent;                float heightPercent = params.heightPercent;                float marginLeftPercent = params.marginLeftPercent;                float marginRightPercent = params.marginRightPercent;                float marginTopPercent = params.marginTopPercent;                float marginBottomPercent = params.marginBottomPercent;                if (widthPercent > 0) {                    params.width = (int) (parentWidth * widthPercent);                }                if (heightPercent > 0) {                    params.height = (int) (parentHeight * heightPercent);                }                if (marginLeftPercent > 0) {                    params.leftMargin = (int) (parentWidth * marginLeftPercent);                }                if (marginRightPercent > 0) {                    params.rightMargin = (int) (parentWidth * marginRightPercent);                }                if (marginTopPercent > 0) {                    params.topMargin = (int) (parentHeight * marginTopPercent);                }                if (marginBottomPercent > 0) {                    params.bottomMargin = (int) (parentHeight * marginBottomPercent);                }            }        }        super.onMeasure(widthMeasureSpec, heightMeasureSpec);    }    @Override    public LayoutParams generateLayoutParams(AttributeSet attrs) {        return new LayoutParams(getContext(), attrs);    }    @Override    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {        return p instanceof LayoutParams;    }    public static class LayoutParams extends RelativeLayout.LayoutParams {        private float widthPercent;        private float heightPercent;        private float marginLeftPercent;        private float marginRightPercent;        private float marginTopPercent;        private float marginBottomPercent;        public LayoutParams(Context c, AttributeSet attrs) {            super(c, attrs);            @SuppressLint("CustomViewStyleable")            TypedArray typedArray = c.obtainStyledAttributes(attrs, R.styleable.PercentRelativeLayout);            widthPercent = typedArray.getFloat(R.styleable.PercentRelativeLayout_widthPercent, 0);            heightPercent = typedArray.getFloat(R.styleable.PercentRelativeLayout_heightPercent, 0);            marginLeftPercent = typedArray.getFloat(R.styleable.PercentRelativeLayout_marginLeftPercent, 0);            marginRightPercent = typedArray.getFloat(R.styleable.PercentRelativeLayout_marginRightPercent, 0);            marginTopPercent = typedArray.getFloat(R.styleable.PercentRelativeLayout_marginTopPercent, 0);            marginBottomPercent = typedArray.getFloat(R.styleable.PercentRelativeLayout_marginBottomPercent, 0);            typedArray.recycle();        }    }}

具体使用

<com.dh.summarize.view.PercentRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"        xmlns:tools="http://schemas.android.com/tools"        xmlns:app="http://schemas.android.com/apk/res-auto"        android:orientation="vertical"        android:layout_width="match_parent"        android:layout_height="match_parent">    <TextView            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:background="@color/colorAccent"            android:textSize="20sp"            android:text="宽:33%,高:50%"            app:widthPercent = "0.33"            app:heightPercent = "0.5"            android:gravity="center_vertical"/></com.dh.summarize.view.PercentRelativeLayout>

我们设置的百分比都是相对于父容器的,相对于父容器的宽度百分比,高度百分比
Android常用屏幕适配方式_第1张图片

三、修改像素密度

我最早知道是今日头条开放出来的,具体可以参考
字节跳动:一种极低成本的Android屏幕适配方式

修改density(屏幕密度),scaleDensity(一般用于字体,通常情况下与density相等),densityDpi(屏幕上每一英寸的像素点)的值,直接更改系统内部对于目标尺寸而言的像素密度。


android中的dp在渲染前会将dp转为px,计算公式:
  • px = density * dp;
  • density = dpi / 160;
  • px = dp * (dpi / 160);
    而dpi是根据屏幕真实的分辨率和尺寸来计算的,每个设备都可能不一样的。

具体工具类

就是根据设计稿去修改目标Activity的Density等值

public class DensityUtils {    /**     * 设计稿宽度(dp)     */    private static final float DEFAULT_WIDTH = 360;    // 屏幕密度    private static float appDensity;    // 字体缩放比,默认就是appDensity    private static float appScaleDensity;    public static void setCustomDensity(Application application, Activity activity) {        DisplayMetrics displayMetrics = application.getResources().getDisplayMetrics();        if (appDensity == 0) {            // 初始化值            appDensity = displayMetrics.density;            appScaleDensity = displayMetrics.scaledDensity;            // 由于我们在系统设置中切换了文字大小,需要改变应用本身的文字大小            application.registerComponentCallbacks(new ComponentCallbacks() {                // 监听系统配置切换                @Override                public void onConfigurationChanged(@NonNull Configuration newConfig) {                    if (newConfig != null && newConfig.fontScale > 0) {                        // 重新获取scaleDensity                        appScaleDensity = application.getResources().getDisplayMetrics().scaledDensity;                    }                }                @Override                public void onLowMemory() {                }            });        }        // 计算所有的目标值        float targetDensity = displayMetrics.widthPixels / DEFAULT_WIDTH;        float targetScaleDensity = targetDensity * (appScaleDensity / appDensity);        // density = dpi / 160        int targetDensityDpi = (int) (targetDensity * 160);        // 将Activity的Density,ScaleDensity,DensityDpi        DisplayMetrics dm = activity.getResources().getDisplayMetrics();        dm.density = targetDensity;        dm.scaledDensity = targetScaleDensity;        dm.densityDpi = targetDensityDpi;    }}

工具类具体调用在Activity的onCreate()的setContentView()方法之前。可以在每个Activity单独设置,也可以在BaseActivity中设置,或者在Application实现Activity的监听。

Application的onCreate()中监听,自己实现一个BaseApplication继承Application。

registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {@Overridepublic void onActivityCreated(Activity activity, Bundle savedInstanceState) {DensityUtils.setCustomDensity(this, activity)}@Overridepublic void onActivityStarted(Activity activity) {}@Overridepublic void onActivityResumed(Activity activity) {}@Overridepublic void onActivityPaused(Activity activity) {}@Overridepublic void onActivityStopped(Activity activity) {}@Overridepublic void onActivitySaveInstanceState(Activity activity, Bundle outState) {}@Overridepublic void onActivityDestroyed(Activity activity) {}});

布局文件,我们适配稿给的360dp的宽度,所以我们分别对两个控件设置180dp,实际适配之后结果应该是平分屏幕宽度。

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"        xmlns:tools="http://schemas.android.com/tools"        xmlns:app="http://schemas.android.com/apk/res-auto"        android:layout_width="match_parent"        android:layout_height="match_parent">    <TextView            android:id="@+id/tvOne"            android:layout_width="180dp"            android:layout_height="100dp"            android:background="@color/colorAccent"            android:textSize="20sp"            android:text="测试1"            app:layout_constraintTop_toTopOf="parent"            app:layout_constraintStart_toStartOf="parent"            android:gravity="center"/>    <TextView            android:id="@+id/tvTwo"            android:layout_width="180dp"            android:layout_height="100dp"            android:background="@color/colorAccent"            android:textSize="20sp"            android:text="测试2"            app:layout_constraintTop_toBottomOf="@id/tvOne"            app:layout_constraintStart_toEndOf="@id/tvOne"            android:gravity="center"/></androidx.constraintlayout.widget.ConstraintLayout>

效果对比,适配前和适配后:
Android常用屏幕适配方式_第2张图片
最后,各种适配方式没有什么是最好的,合适的才是最好的,有句话怎么说的(不适配就是最好的适配),哈哈。平时的适配根据具体项目具体选择采用什么样的适配方式。还有我们可以选择对整体界面适配也可以对单独的某一块进行适配。

四、刘海屏适配

Android 9.0官方适配方式

  • 如果非全屏模式(有状态栏),则APP不受刘海屏影响,刘海屏的高度就是状态栏的高度。
  • 如果是全屏模式,APP未适配刘海屏,系统会对界面做特殊处理,竖屏向下移动,横屏向右移动。

其他手机厂商的适配:

  • 华为:https://devcenter-test.huawei.com/consumer/cn/devservice/doc/50114,打不开。华为开放平台也没有找到相应的文档。
  • 小米:https://dev.mi.com/console/doc/detail?pId=1293
  • OPPO:https://open.oppomobile.com/wiki/doc#id=10159
  • VIVO:https://dev.vivo.com.cn/documentCenter/doc/103
官方适配方案

日常适配刘海屏,我们需要对厂商的版本单独处理,很多厂商都有他们自己的适配方式。比如华为,小米,OPPO等。

1、取消标题栏,设置全屏
2、判断手机厂商
3、判断手机是否有刘海
4、设置是否让内容区域延伸进刘海
5、设置控件是否避开刘海区域
6、获取刘海的高度(一般就是状态栏的高度)

设置全屏,设置内容延伸至刘海等操作都是在setContentView()方法之前

class ShapedScreenActivity : AppCompatActivity() {    override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        // 1.设置全屏        // 取消标题栏        requestWindowFeature(Window.FEATURE_NO_TITLE)        window?.setFlags(            WindowManager.LayoutParams.FLAG_FULLSCREEN,            WindowManager.LayoutParams.FLAG_FULLSCREEN        )        // 手机厂商:华为,小米,OPPO等        // 1.判断手机厂商,        // 2,判断手机是否有刘海,        // 3,设置是否让内容区域延伸进刘海        // 4,设置控件是否避开刘海区域        // 5,获取刘海的高度        // 2.判断是否是刘海屏        if (hasDisplayCutout(window)) {            // 将内容区域延伸进刘海            val attributes = window?.attributes            /*             * LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT 全屏模式,内容下移,非全屏不受影响             * LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES 允许内容去延伸进刘海区             * LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER 不允许内容延伸进刘海区             */            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {                attributes?.layoutInDisplayCutoutMode =                    WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES                window?.attributes = attributes            }            //3.设置成沉浸式            val flags =                View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN            var systemUiVisibility = window?.decorView?.systemUiVisibility            systemUiVisibility = systemUiVisibility?.or(flags)            window?.decorView?.systemUiVisibility = systemUiVisibility ?: 0        }        setContentView(R.layout.activity_shaped_screen)        // 4,设置控件是否避开刘海区域        val layoutParams: ConstraintLayout.LayoutParams =            tvShape.layoutParams as ConstraintLayout.LayoutParams        layoutParams.topMargin = getStatusBarHeight()        tvShape.layoutParams = layoutParams    }    /**     * 判断是否是刘海屏     */    private fun hasDisplayCutout(window: Window?): Boolean {        val displayCutout: DisplayCutout?        val decorView = window?.decorView        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {            val rootWindowInsets = decorView?.rootWindowInsets            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && rootWindowInsets != null) {                displayCutout = rootWindowInsets.displayCutout                if (displayCutout != null) {                    // 判断刘海屏区域数量,判断刘海区域是否高度大于0                    if (displayCutout.boundingRects.size > 0 && displayCutout.safeInsetBottom > 0) {                        return true                    }                }            }        }        return false    }    /**     * 获取状态栏高度(通常情况下,刘海的高度等于状态栏的高度)     */    private fun getStatusBarHeight(): Int {        val resId = resources.getIdentifier("status_bar_height", "dimen", "android")        if (resId > 0) {            return resources.getDimensionPixelSize(resId)        }        return 0    }}

五、单独适配

对需要适配的布局进行单独适配,相对来说更麻烦,但是效果也是最好的。

  1. 跟屏幕相关的缩放比,水平,竖直高度的工具类
public class UIUtils {    private static UIUtils instance;    // 设计稿尺寸,    private static final float DEFAULT_WIDTH = 1080f;    private static final float DEFAULT_HEIGHT = 1920;    private float displayMetricsWidth;    private float displayMetricsHeight;    private float mStatusBarHeight;    private UIUtils(Context context) {        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);        if (wm == null) return;        DisplayMetrics displayMetrics = new DisplayMetrics();        if (displayMetricsWidth == 0 || displayMetricsHeight == 0) {            // 忽略掉了导航栏高度            wm.getDefaultDisplay().getMetrics(displayMetrics);            // 获取真实的屏幕尺寸            //wm.getDefaultDisplay().getRealMetrics(displayMetrics);            mStatusBarHeight = getSystemBarHeight(context);            // 判断横屏还是竖屏            if (displayMetrics.widthPixels > displayMetrics.heightPixels) {                // 横屏                displayMetricsWidth = displayMetrics.heightPixels;                displayMetricsHeight = displayMetrics.widthPixels;                // 如果不是沉浸式,我们还需要减去状态栏的高度                // displayMetricsWidth = displayMetrics.heightPixels - mStatusBarHeight;            } else {                displayMetricsWidth = displayMetrics.widthPixels;                displayMetricsHeight = displayMetrics.heightPixels;            }        }    }    public static UIUtils getInstance(Context context) {        if (instance == null) {            synchronized (UIUtils.class) {                if (instance == null) {                    instance = new UIUtils(context.getApplicationContext());                }            }        }        return instance;    }    public static UIUtils getInstance() {        if (instance == null) {            throw new NullPointerException("UIUtils未被初始化");        }        return instance;    }    /**     * 水平缩放比     *     * @return     */    public float getHorizontalScaleValue() {        return displayMetricsWidth / DEFAULT_WIDTH;    }    /**     * 竖直缩放比     *     * @return     */    public float getVerticalScaleValue() {        return displayMetricsHeight / DEFAULT_HEIGHT;    }    /**     * 获取宽度     * @param width     * @return     */    public int getWidth(int width) {        return Math.round((float) width * displayMetricsWidth / DEFAULT_WIDTH);    }    /**     * 获取高度     * @param height     * @return     */    public int getHeight(int height) {        return Math.round((float) height * displayMetricsHeight / DEFAULT_HEIGHT);    }    /**     * 用于得到状态框的高度     */    public int getSystemBarHeight(Context context) {        int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");        int height = context.getResources().getDimensionPixelSize(resourceId);        if (height != -1) {            return height;        }        return getValue(context, "com.android.internal.R$dimen", "system_bar_height", 48);    }    private int getValue(Context context, String dimeClass, String system_bar_height, int defaultValue) {        try {            Class<?> clazz = Class.forName(dimeClass);            Object object = clazz.newInstance();            Field field = clazz.getField(system_bar_height);            Object obj = field.get(object);            if (obj == null) return defaultValue;            int id = Integer.parseInt(obj.toString());            return context.getResources().getDimensionPixelSize(id);        } catch (Exception e) {            e.printStackTrace();        }        return defaultValue;    }}
  1. 对单独布局进行适配的工具类
public class ViewCalculateUtils {    /**     * 设置字体大小     *     * @param textView     * @param size     */    public static void setTextSize(TextView textView, int size) {        textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, UIUtils.getInstance().getHeight(size));    }    /**     * @param view     * @param width     * @param height     * @param lefMargin     * @param topMargin     * @param rightMargin     * @param bottomMargin     * @param asWidth      true 不改变宽高的缩放比     */    public static void setViewRelativeLayoutParam(View view, int width, int height, int lefMargin, int topMargin,                                                  int rightMargin, int bottomMargin, @Nullable boolean asWidth) {        RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view.getLayoutParams();        if (layoutParams == null) return;        if (width != RelativeLayout.LayoutParams.MATCH_PARENT                && width != RelativeLayout.LayoutParams.WRAP_CONTENT) {            layoutParams.width = UIUtils.getInstance().getWidth(width);        } else {            layoutParams.width = width;        }        if (height != RelativeLayout.LayoutParams.MATCH_PARENT                && height != RelativeLayout.LayoutParams.WRAP_CONTENT) {            layoutParams.height = asWidth ? UIUtils.getInstance().getWidth(height) : UIUtils.getInstance().getHeight(height);        } else {            layoutParams.height = height;        }        layoutParams.topMargin = asWidth ? UIUtils.getInstance().getWidth(topMargin) : UIUtils.getInstance().getHeight(topMargin);        layoutParams.bottomMargin = asWidth ? UIUtils.getInstance().getWidth(bottomMargin) : UIUtils.getInstance().getHeight(bottomMargin);        layoutParams.leftMargin = UIUtils.getInstance().getWidth(lefMargin);        layoutParams.rightMargin = UIUtils.getInstance().getWidth(rightMargin);        view.setLayoutParams(layoutParams);    }    /**     * 设置view的内边距     *     * @param view     * @param topPadding     * @param bottomPadding     * @param leftPadding     * @param rightPadding     */    public static void setViewPadding(View view, int topPadding, int bottomPadding, int leftPadding, int rightPadding) {        view.setPadding(UIUtils.getInstance().getWidth(leftPadding),                UIUtils.getInstance().getHeight(topPadding),                UIUtils.getInstance().getWidth(rightPadding),                UIUtils.getInstance().getHeight(bottomPadding));    }    /**     * @param view     * @param width     * @param height     * @param topMargin     * @param bottomMargin     * @param lefMargin     * @param rightMargin     */    public static void setViewFrameLayoutParam(View view, int width, int height, int topMargin, int bottomMargin, int lefMargin,                                               int rightMargin, @Nullable boolean asWidth) {        FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) view.getLayoutParams();        if (width != RelativeLayout.LayoutParams.MATCH_PARENT                && width != RelativeLayout.LayoutParams.WRAP_CONTENT) {            layoutParams.width = UIUtils.getInstance().getWidth(width);        } else {            layoutParams.width = width;        }        if (height != RelativeLayout.LayoutParams.MATCH_PARENT                && height != RelativeLayout.LayoutParams.WRAP_CONTENT) {            layoutParams.height = asWidth ? UIUtils.getInstance().getWidth(height) : UIUtils.getInstance().getHeight(height);        } else {            layoutParams.height = height;        }        layoutParams.topMargin = asWidth ? UIUtils.getInstance().getWidth(topMargin) : UIUtils.getInstance().getHeight(topMargin);        layoutParams.bottomMargin = asWidth ? UIUtils.getInstance().getWidth(bottomMargin) : UIUtils.getInstance().getHeight(bottomMargin);        layoutParams.leftMargin = UIUtils.getInstance().getWidth(lefMargin);        layoutParams.rightMargin = UIUtils.getInstance().getWidth(rightMargin);        view.setLayoutParams(layoutParams);    }    /**     * @param view     * @param width     * @param height     * @param topMargin     * @param bottomMargin     * @param lefMargin     * @param rightMargin     * @param asWidth     */    public static void setViewLinearLayoutParam(View view, int width, int height, int topMargin, int bottomMargin, int lefMargin,                                                int rightMargin, @Nullable boolean asWidth) {        LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) view.getLayoutParams();        if (width != RelativeLayout.LayoutParams.MATCH_PARENT && width != RelativeLayout.LayoutParams.WRAP_CONTENT) {            layoutParams.width = UIUtils.getInstance().getWidth(width);        } else {            layoutParams.width = width;        }        if (height != RelativeLayout.LayoutParams.MATCH_PARENT && height != RelativeLayout.LayoutParams.WRAP_CONTENT) {            layoutParams.height = asWidth ? UIUtils.getInstance().getWidth(height) : UIUtils.getInstance().getHeight(height);        } else {            layoutParams.height = height;        }        layoutParams.topMargin = asWidth ? UIUtils.getInstance().getWidth(topMargin) : UIUtils.getInstance().getHeight(topMargin);        layoutParams.bottomMargin = asWidth ? UIUtils.getInstance().getWidth(bottomMargin) : UIUtils.getInstance().getHeight(bottomMargin);        layoutParams.leftMargin = UIUtils.getInstance().getWidth(lefMargin);        layoutParams.rightMargin = UIUtils.getInstance().getWidth(rightMargin);        view.setLayoutParams(layoutParams);    }    /**     * @param view     * @param width     * @param height     * @param asWidth     */    public static void setViewGroupLayoutParam(View view, int width, int height, @Nullable boolean asWidth) {        ViewGroup.LayoutParams layoutParams = view.getLayoutParams();        if (width != RelativeLayout.LayoutParams.MATCH_PARENT && width != RelativeLayout.LayoutParams.WRAP_CONTENT && width != RelativeLayout.LayoutParams.FILL_PARENT) {            layoutParams.width = UIUtils.getInstance().getWidth(width);        } else {            layoutParams.width = width;        }        if (height != RelativeLayout.LayoutParams.MATCH_PARENT && height != RelativeLayout.LayoutParams.WRAP_CONTENT && height != RelativeLayout.LayoutParams.FILL_PARENT) {            layoutParams.height = asWidth ? UIUtils.getInstance().getWidth(height) : UIUtils.getInstance().getHeight(height);        } else {            layoutParams.height = height;        }        view.setLayoutParams(layoutParams);    }}

加深理解的文章

  1. 骚年你的屏幕适配方式该升级了!-今日头条适配方案
  2. 骚年你的屏幕适配方式该升级了!-SmallestWidth 限定符适配方案
  3. 今日头条屏幕适配方案终极版正式发布!

更多相关文章

  1. 头条Android 屏幕适配
  2. android如何处理不同屏幕的适配
  3. android:初级 [Android] Eclipse Android中设置模拟器屏幕大小几
  4. android字体大小多屏幕适配
  5. Android 如何在屏幕切换的时候页面信息不被重置
  6. Android处理屏幕旋转时的解决方案
  7. Android手机屏幕的三种状态

随机推荐

  1. android 多分布率解决
  2. Android应用程序打包签名、加固、二次打
  3. 一个支持上下滚动动画的Android(安卓)Tex
  4. Android(安卓)Design与Holo Theme详解
  5. Android(安卓)横向布局中间填满
  6. 按着步骤来,学习Android(安卓)NDK入门很简
  7. Android(安卓)复盘——帮你彻底了解消息
  8. Android权限系统
  9. [置顶] 进击的Android注入术《五》
  10. Android之网络请求3————OkHttp的拦截