【源码剖析】Launcher 8.0 源码 (4) --- Launcher 启动流程 第一步(3)之获取布局参数(续)

本文深入剖析Android Launcher的启动流程,重点讲解DeviceProfile的构造过程,如何根据不同屏幕方向计算布局参数,包括横竖屏的差异化设置,以及如何根据硬件参数定制显示细节,如图标大小、间距等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第一步重点是找准模型,而后还是更多细节上面的工作,首先,对于真正的桌面,我们需要提供两套显示方案,分别是横屏方案和竖屏方案。两套方案的重点区别是长宽的区别。

竖屏是上下距离大,而左右距离小。  而横屏则是左右距离大,上下距离小。

于是通过将距离大的放在作为宽度还是作为长度就可以设定好布局。

其代码如下:


    int smallSide = Math.min(realSize.x, realSize.y);
    int largeSide = Math.max(realSize.x, realSize.y);

    landscapeProfile = new DeviceProfile(context, this, smallestSize, largestSize,
            largeSide, smallSide, true /* isLandscape */);
    portraitProfile = new DeviceProfile(context, this, smallestSize, largestSize,
            smallSide, largeSide, false /* isLandscape */);

这里要创建DeviceProfile对象。 创建DeviceProfile对象,也就是实际的硬件模型了,初始模型是部分横竖屏的,而通过创建DeviceProfile可以得出更加详细的一些内容。

其构造器如下:

public DeviceProfile(Context context, InvariantDeviceProfile inv,
        Point minSize, Point maxSize,
        int width, int height, boolean isLandscape) {
    this.inv = inv;
    this.isLandscape = isLandscape;
    Resources res = context.getResources();
    DisplayMetrics dm = res.getDisplayMetrics();


//确定手机硬件的大类型,是平板,电视,手机。
    isTablet = res.getBoolean(R.bool.is_tablet);
    isLargeTablet = res.getBoolean(R.bool.is_large_tablet);
    isPhone = !isTablet && !isLargeTablet;
//判断hotseat的位置,横屏和竖屏,hotseat和workspace的位置关系不一致。
    transposeLayoutWithOrientation =
            res.getBoolean(R.bool.hotseat_transpose_layout_with_orientation);

//准备各种px值
    ComponentName cn = new ComponentName(context.getPackageName(),
            this.getClass().getName());
    defaultWidgetPadding = AppWidgetHostView.getDefaultPaddingForWidget(context, cn, null);
    edgeMarginPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_edge_margin);
    desiredWorkspaceLeftRightMarginPx = edgeMarginPx;
    pageIndicatorHeightPx =
            res.getDimensionPixelSize(R.dimen.dynamic_grid_page_indicator_height);
    pageIndicatorLandGutterLeftNavBarPx = res.getDimensionPixelSize(
            R.dimen.dynamic_grid_page_indicator_gutter_width_left_nav_bar);
    pageIndicatorLandWorkspaceOffsetPx =
            res.getDimensionPixelSize(R.dimen.all_apps_caret_workspace_offset);
    pageIndicatorLandGutterRightNavBarPx = res.getDimensionPixelSize(
            R.dimen.dynamic_grid_page_indicator_gutter_width_right_nav_bar);
    defaultPageSpacingPx =
            res.getDimensionPixelSize(R.dimen.dynamic_grid_workspace_page_spacing);
    topWorkspacePadding =
            res.getDimensionPixelSize(R.dimen.dynamic_grid_workspace_top_padding);
    overviewModeMinIconZoneHeightPx =
            res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_min_icon_zone_height);
    overviewModeMaxIconZoneHeightPx =
            res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_max_icon_zone_height);
    overviewModeBarItemWidthPx =
            res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_bar_item_width);
    overviewModeBarSpacerWidthPx =
            res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_bar_spacer_width);
    overviewModeIconZoneRatio =
            res.getInteger(R.integer.config_dynamic_grid_overview_icon_zone_percentage) / 100f;
    iconDrawablePaddingOriginalPx =
            res.getDimensionPixelSize(R.dimen.dynamic_grid_icon_drawable_padding);
    dropTargetBarSizePx = res.getDimensionPixelSize(R.dimen.dynamic_grid_drop_target_size);
    workspaceSpringLoadedBottomSpace =
            res.getDimensionPixelSize(R.dimen.dynamic_grid_min_spring_loaded_space);
    hotseatBarHeightPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_height);
    hotseatBarTopPaddingPx =
            res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_top_padding);
    hotseatBarBottomPaddingPx = 0;
    hotseatLandGutterPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_gutter_width);

    widthPx = width;
    heightPx = height;
    if (isLandscape) {
        availableWidthPx = maxSize.x;
        availableHeightPx = minSize.y;
    } else {
        availableWidthPx = minSize.x;
        availableHeightPx = maxSize.y;
    }

    updateAvailableDimensions(dm, res);
    computeAllAppsButtonSize(context);
    mBadgeRenderer = new BadgeRenderer(context, iconSizePx);
}

 

这里的代码是计算出了各个参数的详细数据。InvariantDeviceProfile 类重点处理通过硬件的参数,我们软件应该怎么样选择,是一个大方向。而DeviceProfile则是根据大方向,制定每个细节。

在DeviceProfile的构造器中,我们看到关于overview等的布局详细参数已经一一给出,同时在updateAvailableDimensions(dm, res)和computeAllAppsButtonSize(context)两个方法,则对单个图标进行更详细的设计。

到此,我们可以理解,这一列构造器的深入,关于桌面显示的内容的各个尺寸就已经订好了。

到此,InvariantDeviceProfile正式构造完毕。即第一步的主要目标完成

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值