launcher 谷歌搜索框定制需求

时间:2020/12/29

之前公司不允许csdn,笔记写在其它地方。最近整理过来

需求描述

主界面google搜索栏显示在顶部,recentUI界面搜索栏显示在底部

需求解析:

1、google搜索栏默认的搜索栏移动到底部 https://blog.csdn.net/a396604593/article/details/129752909
2、修改google搜索栏显示在底部时的位置,隐藏掉底部的搜索栏。(这样看上去 主界面是不显示底部搜索的)
3、主界面顶部配置可卸载的默认布局google搜索栏
4、recentUI界面时位移hotseat的坐标,google搜索栏改为显示状态、recentUI界面其它view坐标调整
5、分屏模式下界面调整

需求实现

2、第二点的实现

vendor/partner_gms/apps/SearchLauncher/quickstep/src/com/android/searchlauncher/HotseatQsbWidget.java

@Override
public void setContentVisibility(int visibleElements, PropertySetter setter,
                                 Interpolator interpolator) {
    android.util.Log.d("setContentVisibility", "setContentVisibility visibleElements"+visibleElements);
    boolean showAllAppsMode = (visibleElements & ALL_APPS_CONTENT) != 0;
    //setter.setViewAlpha(mSearchWrapperView, showAllAppsMode ? 0 : 1, LINEAR);
    setter.setViewAlpha(mFallbackSearchView, showAllAppsMode ? 1 : 0, LINEAR);
    //通过判断launcher当前的状态 设置view的显示和隐藏
    boolean showRecent = (visibleElements & (LauncherState.RECENTS_CLEAR_ALL_BUTTON)) != 0;
    setter.setViewAlpha(mSearchWrapperView, showRecent ? 1 : 0, LINEAR);
}

由于主界面隐藏掉了搜索,我们需要修改<dimen name="dynamic_grid_hotseat_top_padding">0dp</dimen> 让hotseat底部看上去不会很大空隙
3、第三点的实现

默认布局文件添加

<appwidget
    container="-100"
    screen="0"
    x="0"
    y="0"
    spanX="5"
    spanY="1"
    packageName="com.google.android.googlequicksearchbox"
    className="com.google.android.googlequicksearchbox.SearchWidgetProvider"/>

关掉首页qsb

public static final boolean QSB_ON_FIRST_SCREEN = false;
4、第四点的实现

底边栏图标recentUI界面需要改变坐标的

4.1 需要位移的偏移量,在dimens.xml添加
<dimen name="dynamic_grid_hotseat_search_widget_height">30dp</dimen>
4.2 Java代码读取配置 , 添加变量

packages/apps/Launcher3/src/com/android/launcher3/DeviceProfile.java

public boolean isShowHotSeatSearchWidget = false;
public int hotSeatSearchWidgetHeightPx = 0;
...
hotSeatSearchWidgetHeightPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_search_widget_height);
4.3

读取配置之后,我们需要在恰当的时机改变 isShowHotSeatSearchWidget这个值,来判断是否需要添加偏移量
因为主要是对底边栏图标的偏移量,isShowHotSeatSearchWidget的控制我们放在packages/apps/Launcher3/src/com/android/launcher3/Hotseat.java

//Hotseat添加launcher状态改变监听
public class Hotseat extends CellLayout implements LogContainerProvider, Insettable, Transposable, LauncherStateManager.StateListener
...
//构造方法添加监听
//初始化位移坐标到内部变量,方便下面动画调用
public Hotseat(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    Launcher.getLauncher(getContext()).getStateManager().addStateListener(this);
    mTranslationY = getTranslationY();
    DeviceProfile grid = mActivity.getWallpaperDeviceProfile();
    mTranslationYInRecentUi = mTranslationY - grid.hotSeatSearchWidgetHeightPx;
    Log.d("Hotseat","mTranslationY: "+mTranslationY + " mTranslationYInRecentUi: "+mTranslationYInRecentUi);
}

//实现回调
@Override
public void onStateTransitionStart(LauncherState toState) {
    //根据要切换到的状态,控制isShowHotSeatSearchWidget的改变
    DeviceProfile grid = mActivity.getWallpaperDeviceProfile();
    boolean oldBoolean = grid.isShowHotSeatSearchWidget;
    if(toState == LauncherState.OVERVIEW){
        grid.isShowHotSeatSearchWidget = true;
    }else{
        grid.isShowHotSeatSearchWidget = false;
    }
    //过滤掉不必要的状态,只有主界面和recentUI界面启动动画
    if(toState !=LauncherState.OVERVIEW && toState != LauncherState.NORMAL){
        return;
    }
    Log.d("Hotseat","oldBoolean: "+oldBoolean +" grid.isShowHotSeatSearchWidget: "+grid.isShowHotSeatSearchWidget);
    //状态改变动画开始的时候,启动hotseat位移动画
    if(oldBoolean != grid.isShowHotSeatSearchWidget){
        AnimatorSet aSet = new AnimatorSet();
        Animator a = getAnimator(grid.isShowHotSeatSearchWidget,Hotseat.this,View.TRANSLATION_Y);
        View scrimView = Launcher.cast(mActivity).getScrimView();
        Animator b = getAnimator(grid.isShowHotSeatSearchWidget,scrimView,View.TRANSLATION_Y);
        aSet.setDuration(180);
        aSet.play(a);
        aSet.play(b);
        startAnimation(aSet);
    }
}
@Override
public void onStateTransitionComplete(LauncherState finalState) {
    //类似于状态开始改变的逻辑,由于这里是装填改变完成的回调,不回去做动画,只是强制设置坐标点
    //根据最终状态控制isShowHotSeatSearchWidget
    DeviceProfile grid = mActivity.getWallpaperDeviceProfile();
    if(finalState == LauncherState.OVERVIEW){
        grid.isShowHotSeatSearchWidget = true;
    }else{
        grid.isShowHotSeatSearchWidget = false;
    }
    //过滤掉不必要的状态
    if(finalState !=LauncherState.OVERVIEW && finalState != LauncherState.NORMAL){
        return;
    }
    //setTranslationY
    Log.d("Hotseat"," grid.isShowHotSeatSearchWidget: "+grid.isShowHotSeatSearchWidget);
    Hotseat.this.setTranslationY(grid.isShowHotSeatSearchWidget?mTranslationYInRecentUi:mTranslationY);
    //这个是主菜单界面的小箭头
    View scrimView = Launcher.cast(mActivity).getScrimView();
    scrimView.setTranslationY(grid.isShowHotSeatSearchWidget?mTranslationYInRecentUi:mTranslationY);
    //适应分屏模式,调整间距
    Rect padding = grid.getHotseatLayoutPadding();
    if(!grid.isVerticalBarLayout()
            && grid.isMultiWindowMode
            && Launcher.getLauncher(getContext()).isInState(OVERVIEW)
    ){
        padding.bottom = grid.hotSeatSearchWidgetHeightPx;
        setPadding(padding.left, padding.top, padding.right, padding.bottom);
    }
}

private float mTranslationY;
private float mTranslationYInRecentUi;
private AnimatorSet mCurrentAnimator;
private Animator getAnimator(boolean isShow,View view, Property property) {
    return isShow
            ? ObjectAnimator.ofFloat(view, property, getTranslationY(), mTranslationYInRecentUi)
            : ObjectAnimator.ofFloat(view, property, getTranslationY(), mTranslationY);
}

private void startAnimation(final AnimatorSet a) {
    if (mCurrentAnimator != null && mCurrentAnimator.isRunning()) {
        mCurrentAnimator.cancel();
    }
    a.addListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationStart(Animator animation) {
            mCurrentAnimator = a;
        }


        @Override
        public void onAnimationEnd(Animator animation) {
            mCurrentAnimator = null;
        }
    });
    a.start();
}

@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.MATCH_PARENT;
        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();
    if(!grid.isVerticalBarLayout()
            && grid.isMultiWindowMode
            && Launcher.getLauncher(getContext()).isInState(OVERVIEW)
    ){
        padding.bottom = grid.hotSeatSearchWidgetHeightPx;
    }
    setPadding(padding.left, padding.top, padding.right, padding.bottom);
    setLayoutParams(lp);
    rect.set(insets);
    InsettableFrameLayout.dispatchInsets(this, insets);
}
4.4 其它view的坐标控制

recentUI界面我们需要位移一些其它的view

//本质上如果我们配置<dimen name="dynamic_grid_hotseat_top_padding">0dp</dimen>为30dp
//会导致主界面一直显示很大空隙
//所以我们参考使用这个值的所有地方,进行针对性调整,让他们加上上面动画偏移量
<dimen name="dynamic_grid_hotseat_top_padding">0dp</dimen>

在这里插入图片描述
packages/apps/Launcher3/quickstep/src/com/android/quickstep/util/LayoutUtils.java

使用dp.hotseatBarSizePx的地方, 减去dp.hotSeatSearchWidgetHeightPx
这里是recentUI界面,taskview相关的宽高测量计算,会影响recentUI界面view的位置和缩放比例

页面指示器位置调整
packages/apps/Launcher3/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java

setWorkspaceProperty中
//修改hotseat动画的Y坐标
if(state == LauncherState.OVERVIEW){
    DeviceProfile grid = mLauncher.getWallpaperDeviceProfile();
    hotseatScaleAndTranslation.translationY -= grid.hotSeatSearchWidgetHeightPx;
}
...
//hotseat和页面指示器的动画,这里按道理可以不改,双层模式已经不现实页面指示器了,单层才显示小圆点
propertySetter.setFloat(hotseat, View.TRANSLATION_Y,
        hotseatScaleAndTranslation.translationY, hotseatTranslationInterpolator);
propertySetter.setFloat(mWorkspace.getPageIndicator(), View.TRANSLATION_Y,
        hotseatScaleAndTranslation.translationY, hotseatTranslationInterpolator);

ScrimView 上滑箭头默认位置和动画过程中位置调整
packages/apps/Launcher3/src/com/android/launcher3/views/ScrimView.java

//因为之前客户需求,要这个指示器小箭头始终显示
//所以需要调整一下ScrimView的大小
//ScrimView是一个全屏的view,重写的ondraw方法自己画了一个箭头, 在上滑的时候,会有白色透明背景切换到allapps界面
//只在hotseat修改坐标, 上滑的时候底部会漏出来,界面显示异常.
//这里我们需要把ScrimView改成全屏+动画偏移量*2高度,保证它随手滑出allapps界面效果
//改变了整体高度,view的绘制位置也需要调整

//构造方法读取动画偏移量,方便内部使用
public ScrimView(Context context, AttributeSet attrs) {
    super(context, attrs);
    ...
    DeviceProfile grid = mLauncher.getWallpaperDeviceProfile();
    mTranslationY = getTranslationY();
    mTranslationYInRecentUi = mTranslationY - grid.hotSeatSearchWidgetHeightPx;
    Log.d("ScrimView","setInsets mTranslationY: "+mTranslationY + " mTranslationYInRecentUi: "+mTranslationYInRecentUi);
}
//测量方法中,重新设置view的高度,保证只走一次
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    updateDragHandleBounds();
    Log.d("ScrimView","mTranslationY: "+mTranslationY + " mTranslationYInRecentUi: "+mTranslationYInRecentUi);
    int width  = getMeasuredWidth();
    int height = getMeasuredHeight();
    Log.d("ScrimView"," height: "+height+" width: "+width);
    ViewGroup.LayoutParams lp = getLayoutParams();
    if(lp.height < height){
        lp.height = height - (int)mTranslationYInRecentUi*2;
        lp.width = width;
        setLayoutParams(lp);
        invalidate();
    }
    Log.d("ScrimView","lp : "+lp.height+" x "+lp.width+ " height: "+height+" width: "+width);
}

updateDragHandleBounds中更新绘制箭头的位置

             left = (width - mDragHandleSize) / 2;
-            topMargin = grid.hotseatBarSizePx;
+            topMargin = grid.hotseatBarSizePx - (int)mTranslationYInRecentUi*2;
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值