Andorid 屏幕适配

Andorid 屏幕适配

本文链接:https://blog.csdn.net/feather_wch/article/details/131672378

参考文章:Android 适配归纳总结

1、dpi是什么?

  1. 屏幕像素密度
  2. 每英寸内160个像素点,160dpi
  3. dpi = px / in

2、dp和px转换

  1. px = dp * (dpi / 160)
  2. density: dpi / 160

3、适配策略(宽度百分比,高度长宽比)

  1. 控件宽度按照UI设计的大小
  2. 控件高度按照样张百分比算出来

头条适配方案

1、让dp具有百分比的效果

  1. px = dp * density
  2. 修改density(存储在DisplayMetrics)
  3. Activity启动时调用相关适配方法,传入activity、application(应对两者的DisplayMetrics不同的情况)
  4. 非常轻量级

2、DisplayMetrics有哪些重要的属性和方法?

  • widthPixels:显示设备的宽度,以像素为单位。
  • heightPixels:显示设备的高度,以像素为单位。
  • density:显示设备的逻辑密度,即每英寸点数(dpi)除以160的比值。
  • densityDpi:显示设备的物理密度,即每英寸点数(dpi)。
  • scaledDensity:显示设备的缩放密度,用于文字缩放,通常与density相同,除非用户修改了字体大小。

3、需要重新计算density,就以样张360dp为标准

  1. 计算出density、densityDpi、scaledDensity
  2. 分配设置给Application和Activity的DisplayMetrics
公式:px = dp * density, density = px / dp
新density = DisplayMetrics.widthPixels / 360
公式:density = dpi / 160,dpi = density * 160
新densityDpi = 160 * 新density

// 设置DisplayMetrics
displayDensity.density = 新density
displayDensity.densityDpi = 新densityDpi

4、字体缩放有问题,要么偏大要么偏小,如何处理?scaledDensity

  1. scaledDensity需要将density密度按照等比例进行缩放
  2. 系统修改字体大小,会触发接口,接口触发后要重新算字体的scaledDensity

百分比方案

5、百分比方案如何实现的?

  1. 算出生成xml文件,不同分辨率不同xml文件,
  2. dp、px用x1、y1等参数,内部会自己换算

DisplayMetrics源码

1、DisplayMetrics什么时候设置的?

  • DisplayMetrics是在WindowManagerService类中设置的。
SystemServer.java】
private void startOtherServices() {
    
    
    final Context context = mSystemContext;
    WindowManagerService wm = null;
    InputManagerService inputManager = null;
    ...
    //创建WindowManagerService对象
    wm = WindowManagerService.main(context, inputManager,
                mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
                !mFirstBoot, mOnlyCore, new PhoneWindowManager());
    //添加到服务管理器
    ServiceManager.addService(Context.WINDOW_SERVICE, wm);
    ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
    ...
    //调用displayReady方法
    wm.displayReady();
    ...
}WMSpublic void displayReady() {
    
    
    synchronized (mWindowMap) {
    
    
        //初始化显示设备
        for (Display display : mDisplays) {
    
    
            DisplayContent displayContent = mRoot.getDisplayContentOrCreate(display.getDisplayId());
            //配置显示策略
            configureDisplayPolicyLocked(displayContent);
            //设置布局标志
            displayContent.layoutNeeded = true;
            //更新方向
            boolean configChanged = updateOrientationFromAppTokensLocked(false);
            //设置临时配置
            mTempConfiguration.setToDefaults();
            mTempConfiguration.fontScale = 1;
            //更新资源配置
            if (configChanged) {
    
    
                mWaitingForConfig = true;
                startFreezingDisplayLocked(false, 0, 0, displayContent);
                //发送配置变化广播
                sendNewConfiguration(display.getDisplayId());
            }
        }
        //初始化输入设备
        mInputMonitor.setUpdateInputWindowsNeededLw();
        performLayoutAndPlaceSurfacesLocked();
        mInputMonitor.updateInputWindowsLw(false /*force*/);
    }
}PhoneWindowManager- WindowManagerPolicy的实现类
private void configureDisplayPolicyLocked(DisplayContent displayContent) {
    
    
    //设置显示设备的初始尺寸和密度
    mPolicy.setInitialDisplaySize(displayContent.getDisplay(),
            displayContent.mBaseDisplayWidth, displayContent.mBaseDisplayHeight,
            displayContent.mBaseDisplayDensity);
    //设置显示设备的overscan区域
    DisplayInfo displayInfo = displayContent.getDisplayInfo();
    mPolicy.setDisplayOverscan(displayContent.getDisplay(),
            displayInfo.overscanLeft, displayInfo.overscanTop,
            displayInfo.overscanRight, displayInfo.overscanBottom);
}PhoneWindowManager- WindowManagerPolicy的实现类
public void setInitialDisplaySize(Display display, int width, int height, int density) {
    
    
    if (display.getDisplayId() == Display.DEFAULT_DISPLAY) {
    
    
        synchronized (mLock) {
    
    
            //初始化真实屏幕大小
            mOverscanScreenWidth = mOverscanScreenHeight = 0;
            mUnrestrictedScreenWidth = width;
            mUnrestrictedScreenHeight = height;
            //初始化DisplayMetrics
            mDisplayWidth = width;
            mDisplayHeight = height;
            mDisplayDensity = density;
            mSystemGestures.screenWidth = width;
            mSystemGestures.screenHeight = height;
        }
        //更新显示区域
        updateOrientationListenerLp();
        updateRotation(true);
    }
}

猜你喜欢

转载自blog.csdn.net/feather_wch/article/details/131672378
今日推荐