Android 源码解析之Launcher3之帮助提示的实现方案
2014-10-23 12:45
399 查看
先从Launcher.xml看view的结构:
res/launcher.xml下有
ScrimView这个类是个FrameLayout的子类,它只实现了Insettable接口,并没有扩展任何元素,可以认为它就是个FrameLayout,暂时不明白它的用意
其它几个include其实都是com.ijinshan.browser.launcher3.Cling类,作者通过这一个类包不同的子view来实现同一种能力且显示效果不同的目的,值得学习.
这里有三个帮助的具体实现:
1.first_run_cling
2.workspace_cling
3.folder_cling
我们可以通过Cling.java这个类为线索去看系统是怎么实现帮助提示的:
1.首先是一些个dismissed:
它的目的很明显,一旦被关掉的帮助以后不打开了,通过这些个key把它们存在SharedPreferences里头。
上述代码会去判断dismiss过,如果dismiss过,就不会再显示了.
接下来是这些:
这些东西和:drawIdentifier有关,在attrs里定义它为string,在first_run_cling.xml,workspace_cling.xml,folder_cling.xml里都有定义:launcher:drawIdentifier
不难理解它是用来区分Cling类里,不同的实现的一个标识。Cling就如同一个躯壳,它里面包哪种类型的显示效果,它就显示啥,但这个躯壳它也清楚它自己包的是啥,就是通过这个变量mDrawIdentifier,是字xml
告诉它的,这个躯壳知道自己包的是啥之后,就好做一些细节上的处理.
我个人感觉这个Cling.java写的不够好,它有点违反设计模式里的单一职责。它居然是各种帮助的躯壳,就不应该自己又去知道里面的东西是啥,又根据里头的东西不一样又实现不一样的细节。其中有一段代码我非
常讨厌,就是我接下来要说的:
这怎么又有hotSeat相关的代码呢?居然已经是一个躯壳就应该做它里面共有的事情,细节的不一样交给包裹里的东西实现,我是这么认为的.
Cling的初始化之init();
可以看出,都是在要显示的时候初始化
如果发显示不该显示就remove()这个细节很赞!
后面dispatchDraw就是根据它包的不同东西去显示一些不同细节,我想说的是,为啥不能交给它们的子view实现。
res/launcher.xml下有
<!-- The Workspace cling must appear under the AppsCustomizePagedView below to ensure that it is still visible during the transition to AllApps and doesn't overlay on top of that view. --> <com.ijinshan.browser.launcher3.ScrimView android:id="@+id/cling_scrim" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="gone" /> <include layout="@layout/first_run_cling" android:id="@+id/first_run_cling" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="gone" /> <include layout="@layout/workspace_cling" android:id="@+id/workspace_cling" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="gone" /> <include layout="@layout/folder_cling" android:id="@+id/folder_cling" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="gone" />
ScrimView这个类是个FrameLayout的子类,它只实现了Insettable接口,并没有扩展任何元素,可以认为它就是个FrameLayout,暂时不明白它的用意
其它几个include其实都是com.ijinshan.browser.launcher3.Cling类,作者通过这一个类包不同的子view来实现同一种能力且显示效果不同的目的,值得学习.
这里有三个帮助的具体实现:
1.first_run_cling
2.workspace_cling
3.folder_cling
我们可以通过Cling.java这个类为线索去看系统是怎么实现帮助提示的:
1.首先是一些个dismissed:
static final String FIRST_RUN_CLING_DISMISSED_KEY = "cling_gel.first_run.dismissed"; static final String WORKSPACE_CLING_DISMISSED_KEY = "cling_gel.workspace.dismissed"; static final String FOLDER_CLING_DISMISSED_KEY = "cling_gel.folder.dismissed";
它的目的很明显,一旦被关掉的帮助以后不打开了,通过这些个key把它们存在SharedPreferences里头。
public void showFirstRunCling() { if (isClingsEnabled() && !mSharedPrefs.getBoolean(Cling.FIRST_RUN_CLING_DISMISSED_KEY, false) && !skipCustomClingIfNoAccounts() ) { // If we're not using the default workspace layout, replace workspace cling // with a custom workspace cling (usually specified in an overlay) // For now, only do this on tablets if (!DISABLE_CUSTOM_CLINGS) { if (mSharedPrefs.getInt(LauncherProvider.DEFAULT_WORKSPACE_RESOURCE_ID, 0) != 0 && getResources().getBoolean(R.bool.config_useCustomClings)) { // Use a custom cling View cling = findViewById(R.id.workspace_cling); ViewGroup clingParent = (ViewGroup) cling.getParent(); int clingIndex = clingParent.indexOfChild(cling); clingParent.removeViewAt(clingIndex); View customCling = mInflater.inflate(R.layout.custom_workspace_cling, clingParent, false); clingParent.addView(customCling, clingIndex); customCling.setId(R.id.workspace_cling); } } Cling cling = (Cling) findViewById(R.id.first_run_cling); if (cling != null) { // String sbHintStr = getFirstRunClingSearchBarHint(); String ccHintStr = getFirstRunCustomContentHint(); // if (!sbHintStr.isEmpty()) { // TextView sbHint = (TextView) cling.findViewById(R.id.search_bar_hint); // sbHint.setText(sbHintStr); // sbHint.setVisibility(View.VISIBLE); // } setCustomContentHintVisibility(cling, ccHintStr, true, false); } initCling(R.id.first_run_cling, 0, false, true); } else { removeCling(R.id.first_run_cling); } } private void dismissCling(final Cling cling, final Runnable postAnimationCb, final String flag, int duration, boolean restoreNavBarVisibilty) { // To catch cases where siblings of top-level views are made invisible, just check whether // the cling is directly set to GONE before dismissing it. if (cling != null && cling.getVisibility() != View.GONE) { final Runnable cleanUpClingCb = new Runnable() { public void run() { cling.cleanup(); // We should update the shared preferences on a background thread new Thread("dismissClingThread") { public void run() { SharedPreferences.Editor editor = mSharedPrefs.edit(); editor.putBoolean(flag, true); editor.commit(); } }.start(); if (postAnimationCb != null) { postAnimationCb.run(); } } }; if (duration <= 0) { cleanUpClingCb.run(); } else { cling.hide(duration, cleanUpClingCb); } mHideFromAccessibilityHelper.restoreImportantForAccessibility(mDragLayer); if (restoreNavBarVisibilty) { cling.setSystemUiVisibility(cling.getSystemUiVisibility() & ~View.SYSTEM_UI_FLAG_LOW_PROFILE); } } }
上述代码会去判断dismiss过,如果dismiss过,就不会再显示了.
接下来是这些:
private static String FIRST_RUN_PORTRAIT = "first_run_portrait"; private static String FIRST_RUN_LANDSCAPE = "first_run_landscape"; private static String WORKSPACE_PORTRAIT = "workspace_portrait"; private static String WORKSPACE_LANDSCAPE = "workspace_landscape"; private static String WORKSPACE_LARGE = "workspace_large"; private static String WORKSPACE_CUSTOM = "workspace_custom"; private static String FOLDER_PORTRAIT = "folder_portrait"; private static String FOLDER_LANDSCAPE = "folder_landscape"; private static String FOLDER_LARGE = "folder_large";
这些东西和:drawIdentifier有关,在attrs里定义它为string,在first_run_cling.xml,workspace_cling.xml,folder_cling.xml里都有定义:launcher:drawIdentifier
不难理解它是用来区分Cling类里,不同的实现的一个标识。Cling就如同一个躯壳,它里面包哪种类型的显示效果,它就显示啥,但这个躯壳它也清楚它自己包的是啥,就是通过这个变量mDrawIdentifier,是字xml
告诉它的,这个躯壳知道自己包的是啥之后,就好做一些细节上的处理.
我个人感觉这个Cling.java写的不够好,它有点违反设计模式里的单一职责。它居然是各种帮助的躯壳,就不应该自己又去知道里面的东西是啥,又根据里头的东西不一样又实现不一样的细节。其中有一段代码我非
常讨厌,就是我接下来要说的:
private int[] mTouchDownPt = new int[2]; private Drawable mFocusedHotseatApp; private ComponentName mFocusedHotseatAppComponent; private Rect mFocusedHotseatAppBounds; //这个方法显然是FirstRunWorkspaceCling相关的东西 void setFocusedHotseatApp(int drawableId, int appRank, ComponentName cn, String title, String description) { .... }
这怎么又有hotSeat相关的代码呢?居然已经是一个躯壳就应该做它里面共有的事情,细节的不一样交给包裹里的东西实现,我是这么认为的.
Cling的初始化之init();
1.first_run_cling:Launcher.onCreate()->Launcher.showFirstRunCling()->Launcher.initCling(); 2.workspace_cling:Cling.onClick()->Launcher.dismissFirstRunCling()->showFirstRunWorkspaceCling()->Launcher.initCling() 3.folder_cling:Folder.animateOpen->Launcher.showFirstRunFoldersCling()->Launcher.initCling();
可以看出,都是在要显示的时候初始化
if (isClingsEnabled() && !mSharedPrefs.getBoolean(Cling.FOLDER_CLING_DISMISSED_KEY, false)) { Cling cling = initCling(R.id.folder_cling, R.id.cling_scrim, true, true); return cling; } else { removeCling(R.id.folder_cling); return null; }
如果发显示不该显示就remove()这个细节很赞!
后面dispatchDraw就是根据它包的不同东西去显示一些不同细节,我想说的是,为啥不能交给它们的子view实现。
相关文章推荐
- 使用Android自带Gallery组件实现CoverFlow,源码+解析
- Android 带你从源码的角度解析Scroller的滚动实现原理
- android Launcher源码解析07:Workspace 02——设置壁纸
- 【Android】带你从源码的角度解析Scroller的滚动实现原理
- Android 属性动画 源码解析 深入了解其内部实现
- 使用Android自带Gallery组件实现CoverFlow,源码+解析
- AbstractQueuedSynchronizer实现Android版源码解析(一)
- Android 带你从源码的角度解析Scroller的滚动实现原理
- AbstractQueuedSynchronizer实现Android版源码解析(三)
- Android下拉刷新完全解析,教你如何一分钟实现下拉刷新功能(附源码)
- Android下拉刷新完全解析,教你如何一分钟实现下拉刷新功能(附源码)
- android,viewpage实现应用程序员宝典;扩展包不管什么android版本都可以用;第一次安装使用从封面到提示帮助界面
- Android 带你从源码的角度解析Scroller的滚动实现原理
- Android 带你从源码的角度解析Scroller的滚动实现原理
- 使用Android自带Gallery组件实现CoverFlow,源码+解析
- Android中launcherMode="singleTask"详解【android源码解析六】
- [Android源码分析]蓝牙文件传输过程解析之UI实现
- Android 带你从源码的角度解析Scroller的滚动实现原理
- Android 属性动画 源码解析 深入了解其内部实现
- Android自定义控件:进度条的四种实现方式(Progress Wheel的解析)(源码 + Demo)