1.前言
在10.0的系统rom定制化开发中,在对于launcher3的一些开发定制中,在对hotseat的一些开发中,需要实现动态hotseat居中
的功能,就是在拖拽图标进入和拖出hotseat,都可以保持hotseat居中的功能,接下来分析下相关功能实现
具体如图:
2.Launcher3拖拽图标进入hotseat自适应布局功能实现一的核心类
packages\apps\Launcher3\src\com\android\launcher3\Hotseat.java
3.Launcher3拖拽图标进入hotseat自适应布局功能实现一的核心功能分析和实现
Launcher顾名思义,就是桌面的意思,也是android系统启动后第一个启动的应用程序,
:Launcher3负责管理和展示用户手机桌面上的各个应用程序图标。它通过GridView或者LinearLayout等布局管理器将
图标进行排列,并支持滑动、放大缩小等手势操作
Hotseat也是属于在导航栏底部的BubbleTextView的布局,只是不显示app图标
3.1 Hotseat.java相关添加背景功能分析
在实现Launcher3拖拽图标进入hotseat自适应布局功能实现一的核心功能中,通过上述的分析得知,
首选需要给Hotseat添加背景功能,然后需要根据hotseat的数量多少来设置hotseat的宽度高度等
相关参数,这样就实现了第一步的hotseat的居中显示功能,
public class Hotseat extends CellLayout implements LogContainerProvider, Insettable, Transposable { @ViewDebug.ExportedProperty(category = "launcher") public boolean mHasVerticalHotseat; private final HotseatController mController; public Hotseat(Context context) { this(context, null); } public Hotseat(Context context, AttributeSet attrs) { this(context, attrs, 0); } public Hotseat(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mController = LauncherAppMonitor.getInstance(context).getHotseatController(); } public HotseatController getController() { return mController; } /* Get the orientation specific coordinates given an invariant order in the hotseat. */ public int getCellXFromOrder(int rank) { return mHasVerticalHotseat ? 0 : rank; } public int getCellYFromOrder(int rank) { return mHasVerticalHotseat ? (getCountY() - (rank + 1)) : 0; } public void resetLayout(boolean hasVerticalHotseat) { removeAllViewsInLayout(); mHasVerticalHotseat = hasVerticalHotseat; InvariantDeviceProfile idp = mActivity.getDeviceProfile().inv; if (hasVerticalHotseat) { setGridSize(1, idp.numHotseatIcons); } else { setGridSize(idp.numHotseatIcons, 1); } //add core start // 添加背景 if(idp.numHotseatIcons>0){ setBackgroundResource(R.drawable.shape_corner); } //add core end } @Override public void fillInLogContainerData(View v, ItemInfo info, Target target, Target targetParent) { target.gridX = info.cellX; target.gridY = info.cellY; targetParent.containerType = LauncherLogProto.ContainerType.HOTSEAT; } @Override public void setInsets(Rect insets) { FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams(); DeviceProfile grid = mActivity.getWallpaperDeviceProfile(); insets = grid.getInsets(); if (grid.isVerticalBarLayout()) { lp.height = ViewGroup.LayoutParams.WRAP_CONTENT; if (grid.isSeascape()) { lp.gravity = Gravity.LEFT; lp.width = grid.hotseatBarSizePx + insets.left; } else { lp.gravity = Gravity.RIGHT; lp.width = grid.hotseatBarSizePx + insets.right; } } else { lp.gravity = Gravity.BOTTOM; lp.width = ViewGroup.LayoutParams.MATCH_PARENT; lp.height = grid.hotseatBarSizePx + insets.bottom; } Rect padding = grid.getHotseatLayoutPadding(); setPadding(padding.left, padding.top, padding.right, padding.bottom); setLayoutParams(lp); InsettableFrameLayout.dispatchInsets(this, insets); } @Override public boolean onTouchEvent(MotionEvent event) { // Don't let if follow through to workspace return true; } @Override public RotationMode getRotationMode() { return Launcher.getLauncher(getContext()).getRotationMode(); } }
在实现Launcher3拖拽图标进入hotseat自适应布局功能实现一的核心功能中,通过上述的分析得知,
在Hotseat中相关源码分析,可以发现由
resetLayout 就是负责布局的 当hotseat 增加减少时都会重新布局
所以在setBackgroundResource(R.drawable.shape_corner);添加背景就可以了
public void resetLayout(boolean hasVerticalHotseat) { removeAllViewsInLayout(); mHasVerticalHotseat = hasVerticalHotseat; InvariantDeviceProfile idp = mActivity.getDeviceProfile().inv; if (hasVerticalHotseat) { setGridSize(1, idp.numHotseatIcons); } else { setGridSize(idp.numHotseatIcons, 1); } // 添加背景 if(idp.numHotseatIcons>0){ setBackgroundResource(R.drawable.shape_corner); } } shape_corner.xml <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <!--背景颜色--> <solid android:color="#FFFAFA" /> <!--角的半径--> <corners android:radius="10dp"/> <!--边框颜色--> <stroke android:width="1dp" android:color="#00000000" /> </shape> public void setInsets(Rect insets) { FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams(); DeviceProfile grid = mActivity.getWallpaperDeviceProfile(); insets = grid.getInsets(); //竖屏布局 if (grid.isVerticalBarLayout()) { lp.height = ViewGroup.LayoutParams.WRAP_CONTENT; if (grid.isSeascape()) { lp.gravity = Gravity.LEFT; lp.width = grid.hotseatBarSizePx + insets.left; } else { lp.gravity = Gravity.RIGHT; lp.width = grid.hotseatBarSizePx + insets.right; } } else { //modify core start // 横屏布局 // 平板开发项目 固定横屏,所以要在这里设置参数 // 设置宽高 左边底部的间距 InvariantDeviceProfile idp = mActivity.getDeviceProfile().inv; int hotseatNums = idp.numHotseatIcons; lp.width = hotseatNums*grid.hotseatBarSizePx+(hotseatNums+1)*dip2px(15.0f); lp.height = grid.hotseatBarSizePx + insets.bottom; if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT){ lp.leftMargin = (int)((1080-lp.width)/2); }else{ lp.leftMargin = (int)((1920-lp.width)/2); } lp.gravity = Gravity.BOTTOM; //modify core end } Rect padding = grid.getHotseatLayoutPadding(); // 设置padding 布局 setPadding(0, padding.top, 0,0); setLayoutParams(lp); InsettableFrameLayout.dispatchInsets(this, insets); }
在实现Launcher3拖拽图标进入hotseat自适应布局功能实现一的核心功能中,通过上述的分析得知,
在Hotseat中相关源码分析,
而setInset() 负责设置绘制布局 的参数 这里设置hotseat的宽高等参数布局
其实只需要修改lp的参数就行了 然后hotseat 会根据长宽等参数 来具体布局每一个hotseat的具体坐标
根据横竖屏来确定lp.leftMargin的值,就可以保证居中显示