Android屏幕适配之--自定义像素的缩放比例来实现屏幕适配

Android屏幕适配之--自定义像素的缩放比例来实现屏幕适配

在Android的适配中,可以采用自定义布局的形式,来通过计算像素的缩放比例来实现适配。大致思路就是,通过拿到设备实际的长宽像素值来除以参考设备的长宽值,得到这一个比例值,在设置控件的长宽值得时候,拿到开发者指定的长宽值乘以这个比例值,就能得到控件的实际显示大小了,公式大致如下:

scaleX = 设备实际像素值 / 参考设计图的像素值

控件实际像素值 = 开发者设置的像素值 * scaleX

实现方案如下:

首先我们通过一个工具类来获取设备在X方向和Y方向上的像素值比例
public class PixelUtils {

    private Context mContext;
    private static PixelUtils mUtils;

    //屏幕宽高
    private float mWidth;
    private float mHeight;

    //参考设备的屏幕尺寸,单位都是像素值px
    private float STANDARD_WIDTH = 720;
    private float STANDARD_HEIGHT = 1080;
    public PixelUtils(Context context) {
        mContext = context;
        WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        if(manager != null){
            DisplayMetrics metrics = new DisplayMetrics();
            manager.getDefaultDisplay().getMetrics(metrics);    //获取屏幕的显示Metrics对象
            if(metrics.widthPixels > metrics.heightPixels){
                //横屏,宽高进行交换
                mWidth = metrics.heightPixels;
                mHeight = metrics.widthPixels;
            }else{
                //竖屏
                mWidth = metrics.widthPixels;
                mHeight = metrics.heightPixels;
            }
        }
    }

    public static PixelUtils getInstance(Context context){
        if(mUtils == null){
            mUtils = new PixelUtils(context.getApplicationContext());
        }
        return mUtils;
    }

    private int getStatusBarHeight(){
        int resId = mContext.getResources().getIdentifier("status_bar_height","dimen","android");
        if(resId > 0){
            return mContext.getResources().getDimensionPixelSize(resId);
        }
        return 0;
    }

    /**
     * 获取水平方向上的缩放比例
     */
    public float getXScal(){
        return mWidth / STANDARD_WIDTH;
    }

    /**
     * 获取竖直方向上的缩放比例
     */
    public float getYScal(){
        return mHeight / STANDARD_HEIGHT;
    }
}
接下来我们通过实现自定义控件(可以继承RelativeLayout或者LinearLayout等之类的),在onMeasure中,先拿到开发者设置的像素值,然后通过公式来乘以相应的比例,在把算出来的实际像素值设置给控件进行显示
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

    if (!flag) {
        float scalX = PixelUtils.getInstance(getContext()).getXScal();
        float scalY = PixelUtils.getInstance(getContext()).getYScal();
        int childCount = getChildCount();

        for (int index = 0; index < childCount; index++) {
            View child = getChildAt(index);

            LayoutParams layoutParams = (LayoutParams) child.getLayoutParams();
            layoutParams.width = (int) (layoutParams.width * scalX);
            layoutParams.height = (int) (layoutParams.height * scalY);

            layoutParams.leftMargin = (int) (layoutParams.leftMargin * scalX);
            layoutParams.rightMargin = (int) (layoutParams.rightMargin * scalX);
            layoutParams.topMargin = (int) (layoutParams.topMargin * scalY);
            layoutParams.bottomMargin = (int) (layoutParams.bottomMargin * scalY);

        }
        flag = true;
    }

    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

在上面的代码中,我们定义了一个flag值来进行标记,主要是控件在进行二次绘制的时候,会在第一次绘制时设置的值得基础上在进行一次比例的计算,相当于实际值 = 设置的值 * 比例值 * 比例值,所以为了计算结果的准确,这里用一个flag值进行了标记

最后在自己的布局中就可以使用自己的自定义控件了,但是这里要注意的一点是,这里给控件设置的值应该是以目标尺寸为依据的像素值,所以单位应该是px
<com.example.fizzer.splashview.screen.ScreenAdapterLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
tools:context=".screen.PixelActivity">
    

    <com.example.fizzer.splashview.screen.ScreenAdapterLayout
        android:layout_width="360px"
        android:layout_height="540px"
        android:orientation="horizontal"
        android:background="#ff0000">

        <TextView
            android:layout_width="180px"
            android:layout_height="270px"
            android:text="Fizzer"
            android:background="#0f0"/>
    </com.example.fizzer.splashview.screen.ScreenAdapterLayout>
</com.example.fizzer.splashview.screen.ScreenAdapterLayout>

这样的话就实现了整个的适配小效果,但是这种方案在实际操作上来说,局限性比较的大,在小范围的使用没问题,但是如果想要在整个项目中进行操作的话,建议还是采用通过修改系统的Density和DensityDpi的方案来进行适配。可实际参考我的另一篇文章Android屏幕适配之--通过修改系统的屏幕像素比来实现屏幕的适配效果

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,658评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,482评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,213评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,395评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,487评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,523评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,525评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,300评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,753评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,048评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,223评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,905评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,541评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,168评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,417评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,094评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,088评论 2 352

推荐阅读更多精彩内容