Android屏幕适配(一)--自定义View屏幕适配

为什么要屏幕适配

同一个界面需要在不同尺寸的屏幕上显示,即使屏幕的尺寸一样,密度也可能不一样。导致App的界面元素在不同屏幕尺寸上显示不一致。所以我们让布局,布局组件,资源,用户界面流程,匹配不同屏幕尺寸。

屏幕适配常见方式

布局适配

  1. 避免写死控件尺寸,使用wrap_content, match_parent
  2. LinearLayout xxx:layout_weight=“0.5” //线性布局使用权重来布局
  3. RelativeLayout xxx:layout_centerInParent=“true” //使用相对布局
  4. ContraintLayout xxx:layout_constraintLeft_toLeftOf=“parent”…//使用约束布局
  5. Percent-support-lib xxx:layout_widthPercent=“30%” …//使用百分比布局

图片资源适配

  1. .9图或者SVG图实现缩放
  2. 备用位图匹配不同分辨率

限定符适配

  1. 分辨率限定符 drawable-hdpi ,drawable-xdpi,…
  2. 尺寸限定符 layout-small,layout-large,…
  3. 最小宽度限定符 values-sw360dp,values-sw384dp, …
  4. 屏幕方向限定符 layout-land,layout-part
    特殊屏幕适配
    比如刘海屏,水滴屏幕等

自定义View屏幕适配的具体方案:

如下图:设计师给出来是720*1280尺寸的设计稿,我们需要适配不同屏幕上的尺寸,怎么适配,
android屏幕适配
如图:720 上显示350的宽,如果在1080上也显示350,我们会发现比例不对。
所以我们需要改成525,那么525是怎么计算出来。
width = 350/720 * 1080 或者是 width = 1080 / 720 * 350
但是我们不可能每次都去这么算。下面我们写一个Utils专门做这个事情,使用该Utils必须设置设计稿的参考宽高,如下代码

//这里设计稿参考宽高
    private static final float STANDARD_WIDTH = 720;
    private static final float STANDARD_HEIGHT = 1280;
public class Utils {
    private static Utils utils;

    //这里设计稿参考宽高
    private static final float STANDARD_WIDTH = 720;
    private static final float STANDARD_HEIGHT = 1280;

    //这里是屏幕显示的宽高
    private int mDisplayWidth;
    private int mDIsplayHeight;

    private Utils(Context context){
        //获取屏幕的宽高
        if (mDisplayWidth == 0 || mDIsplayHeight == 0){
            WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
            if(manager != null){
                DisplayMetrics displayMetrics = new DisplayMetrics();
                manager.getDefaultDisplay().getMetrics(displayMetrics);
                if (displayMetrics.widthPixels > displayMetrics.heightPixels){
                    //横屏
                    mDisplayWidth = displayMetrics.heightPixels;
                    mDIsplayHeight = displayMetrics.widthPixels;
                }else {
                    mDisplayWidth = displayMetrics.widthPixels;
                    mDIsplayHeight = displayMetrics.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 static Utils getInstance(Context context){
        if (utils == null){
            utils = new Utils(context.getApplicationContext());
        }
        return utils;
    }
    //获取水平方向上的缩放比例
    public float getHorizaontalScale(){
        return mDisplayWidth / STANDARD_WIDTH;
    }

    //获取垂直方向上的缩放比例
    public float getVerticalScale(){
        return mDIsplayHeight / STANDARD_HEIGHT;
    }


}

然后我们自定义一个View继承RelativeLayout,来让所有的子View都自己进行适配。根据当前设备的实际像素换算出目标像素,在作用到控件上


public class ScreenAdapterLayout extends RelativeLayout {
    private boolean flag;
    public ScreenAdapterLayout(Context context) {
        super(context);
    }

    public ScreenAdapterLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ScreenAdapterLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (!flag){
            float scalex = Utils.getInstance(getContext()).getHorizaontalScale();//获取横向缩放比例
            float scaley = Utils.getInstance(getContext()).getVerticalScale();//获取竖向缩放比例

            for (int i = 0; i < getChildCount(); i++){
                View child = getChildAt(i);//重新设置子View的布局属性,再进行View的测量
                LayoutParams lp = (LayoutParams)child.getLayoutParams();
                lp.width = (int) (lp.width * scalex);//换算宽度目标值
                lp.height = (int) (lp.height * scaley);//换算高度目标值
                lp.topMargin = (int) (lp.topMargin * scaley);//换算四周间距的目标值
                lp.bottomMargin = (int) (lp.bottomMargin * scaley);//换算四周间距的目标值
                lp.leftMargin = (int) (lp.leftMargin * scalex);//换算四周间距的目标值
                lp.rightMargin = (int) (lp.rightMargin * scalex);//换算四周间距的目标值

            }
            flag = true;
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

使用我们自定义的View做为布局的根View就能实现屏幕适配。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值