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)
详细内容请参考: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应用列表修改透明背景的方法
-
Android开发中Launcher3常见默认配置修改方法总结
-
Android7.0开发实现Launcher3去掉应用抽屉的方法详解
-
android 9.0 launcher3 去掉抽屉式显示所有 app(代码详解)
-
Android开发实现Launcher3应用列表修改透明背景的方法
-
Android开发中Launcher3常见默认配置修改方法总结
-
【Android】用Cubism 2制作自己的Live2D——官方App样例源码学习(1)!
-
android 9.0 Launcher3 去掉抽屉式,显示所有 app
-
Android自定义View2--onMeasure,onLayout源码分析和自定义流式布局
-
Android8.1 Launcher3 去掉抽屉方法