Android launcher3 – launcher3源码2

去除首次进入提示框

android launcher3下载 com.android.launcher3下载_源码

布局

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)

详细内容请参考: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下载 com.android.launcher3下载_launcher_02