欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android launcher3 -- launcher3源码2

程序员文章站 2022-06-30 16:36:06
...

Android launcher3 – launcher3源码2

去除首次进入提示框

Android launcher3 -- launcher3源码2

布局

longpress_cling.xml “欢迎使用”界面的背景和容器
longpress_cling_welcome_content.xml “欢迎使用”界面的描述,首次启动调用
longpress_cling_content.xml 数据迁移时提醒

相关字符串:

<string name="first_run_cling_title" msgid="2459738000155917941">"欢迎使用"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"复制应用图标"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"要导入旧的主屏幕中的图标和文件夹吗?"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"复制图标"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"使用全新配置"</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"壁纸、小部件和设置"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"触摸并按住背景,即可进行个性化设置"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"知道了"</string>

调用“欢迎使用”界面

Launcher.java:protected void onCreate(Bundle savedInstanceState)
Launcher.java:void showFirstRunClings()
LauncherClings.java:public void showLongPressCling(boolean showWelcome)

public void showLongPressCling(boolean showWelcome) {
    mIsVisible = true;
    ViewGroup root = (ViewGroup) mLauncher.findViewById(R.id.launcher);
    View cling = mInflater.inflate(R.layout.longpress_cling, root, false);

    cling.setOnLongClickListener(new OnLongClickListener() {

        @Override
        public boolean onLongClick(View v) {
            mLauncher.showOverviewMode(true);
            dismissLongPressCling();
            return true;
        }
    });

    final ViewGroup content = (ViewGroup) cling.findViewById(R.id.cling_content);
    mInflater.inflate(showWelcome ? R.layout.longpress_cling_welcome_content
            : R.layout.longpress_cling_content, content);
    content.findViewById(R.id.cling_dismiss_longpress_info).setOnClickListener(this);

    if (TAG_CROP_TOP_AND_SIDES.equals(content.getTag())) {
        Drawable bg = new BorderCropDrawable(mLauncher.getResources().getDrawable(R.drawable.cling_bg),
                true, true, true, false);
        content.setBackground(bg);
    }

    root.addView(cling);

    if (showWelcome) {
        // This is the first cling being shown. No need to animate.
        return;
    }

    // Animate
    content.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

        @Override
        public void onGlobalLayout() {
            content.getViewTreeObserver().removeOnGlobalLayoutListener(this);

            ObjectAnimator anim;
            if (TAG_CROP_TOP_AND_SIDES.equals(content.getTag())) {
                content.setTranslationY(-content.getMeasuredHeight());
                anim = LauncherAnimUtils.ofFloat(content, "translationY", 0);
            } else {
                content.setScaleX(0);
                content.setScaleY(0);
                PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1);
                PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 1);
                anim = LauncherAnimUtils.ofPropertyValuesHolder(content, scaleX, scaleY);
            }

            anim.setDuration(SHOW_CLING_DURATION);
            anim.setInterpolator(new LogDecelerateInterpolator(100, 0));
            anim.start();
        }
    });
}

状态栏和导航栏透明

透明设置

Android 4.4 沉浸式透明状态栏与导航栏。
Android 系统自4.2 开始 UI 上就没多大改变,4.4 也只是增加了透明状态栏与导航栏的功能;而Material Design的普及,很多开发人员都会面临App的Material适配。如果你的App不只是针对5.0以上设备的话,多数情况也必须做兼容

代码设置:

if(VERSION.SDK_INT >= VERSION_CODES.KITKAT) {
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
}

在values、values-v19、values-v21的style.xml设置:
values/style.xml

<style name="BaseWallpaperTheme" parent="@android:style/Theme.DeviceDefault.Light.NoActionBar">
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:colorBackgroundCacheHint">@null</item>
    <item name="android:windowShowWallpaper">true</item>
    <item name="android:windowNoTitle">true</item>
</style>

<style name="Theme" parent="@style/BaseWallpaperTheme"></style>

values-v19/style.xml

<style name="Theme" parent="@style/BaseWallpaperTheme">
    <item name="android:windowTranslucentStatus">true</item>
    <item name="android:windowTranslucentNavigation">true</item>
</style>

values-v21/style.xml

<style name="Theme" parent="@style/BaseWallpaperTheme">
    <item name="android:windowTranslucentStatus">true</item>
    <item name="android:windowTranslucentNavigation">true</item>
    <item name="android:colorControlActivated">@color/launcher_accent_color</item>
    <item name="android:colorAccent">@color/launcher_accent_color</item>
    <item name="android:colorPrimary">@color/launcher_accent_color</item>
</style>

values-sw720dp\styles.xml

<style name="Theme" parent="@android:style/Theme.DeviceDefault.Wallpaper.NoTitleBar">
    <item name="android:windowActionModeOverlay">true</item>
</style>

values-sw720dp-v19\styles.xml

<style name="Theme" parent="@android:style/Theme.DeviceDefault.Wallpaper.NoTitleBar">
    <item name="android:windowActionModeOverlay">true</item>
    <item name="android:windowTranslucentStatus">true</item>
    <item name="android:windowTranslucentNavigation">true</item>
</style>

Launcher3设置全屏显示

mLauncherView.setSystemUiVisibility(
        View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);

Launcher3为什么还要设置全屏显示?状态栏和导航栏透明存在各种问题。

导航栏UI重叠问题
android:fitsSystemWindows="true"

通过前面的两种方式所实现 Translucent System Bar 效果的Activity,都需要在根布局里设置 android:fitsSystemWindows=”true” 。设置了该属性的作用在于,不会让系统导航栏和我们app的UI重叠,导致交互问题。

ActionBar上菜单显示三个方块

保持Activity调起,使用android:windowActionModeOverlay属性。
看似让ActionMode浮在了ActionBar上,但其实存在很大问题。
这种方式在4.4以下会使用Holo风格(overflow图标可以看出来,不是三个原点,是三个方块),且ActionMode比ActionBar小一些(可以看到蓝色底边是ActionBar)
Android launcher3 -- launcher3源码2

详细内容请参考:Material适配详解

布局空出状态栏和导航栏区域

上面设置状态栏和导航栏透明后,在Launcher3源码处理:

public class LauncherRootView extends InsettableFrameLayout {
    public LauncherRootView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected boolean fitSystemWindows(Rect insets) {
        setInsets(insets);
        return true; // I'll take it from here
    }
}

父类InsettableFrameLayout.java回调:

public void setInsets(Rect insets) {
    final int n = getChildCount();
    for (int i = 0; i < n; i++) {
        final View child = getChildAt(i);
        setFrameLayoutChildInsets(child, insets, mInsets);
    }
    mInsets.set(insets);
}

最终处理布局Margin:

public void setFrameLayoutChildInsets(View child, Rect newInsets, Rect oldInsets) {
    final LayoutParams lp = (LayoutParams) child.getLayoutParams();

    if (child instanceof Insettable) {
        ((Insettable) child).setInsets(newInsets);
    } else if (!lp.ignoreInsets) {
        lp.topMargin += (newInsets.top - oldInsets.top);
        lp.leftMargin += (newInsets.left - oldInsets.left);
        lp.rightMargin += (newInsets.right - oldInsets.right);
        lp.bottomMargin += (newInsets.bottom - oldInsets.bottom);
    }
    child.setLayoutParams(lp);
}

还可使用Google提供CoordinatorLayout布局对fitsSystemWindows处理。参考:令人困惑的fitsSystemWindows属性

测试屏蔽:

lp.topMargin += (newInsets.top - oldInsets.top);
lp.leftMargin += (newInsets.left - oldInsets.left);
lp.rightMargin += (newInsets.right - oldInsets.right);
lp.bottomMargin += (newInsets.bottom - oldInsets.bottom);

Android launcher3 -- launcher3源码2