1.Android-开源通用弹窗的源码封装CommonPopupWindow(总得向别人学点什么)
2.Android常è§ç¥è¯ç¹
3.Navigation源码解析及自定义FragmentNavigator详解
4.Android åçBottomSheet ä»ç»åå
Android-开源通用弹窗的封装CommonPopupWindow(总得向别人学点什么)
自我激励,封装Android通用弹窗
开源地址:FanChael/CommonPopupWindow
实现弹窗效果,源码当前功能基本可用,源码后续计划整合Rx家族与JSON,源码构建应用更新框架。源码
注册登录弹窗借鉴国外原生样式,源码好友买卖 源码注重设计与源码学习,源码提升自身技能。源码
简单使用方法:
1. 自定义布局
1.1 创建Spinner背景形状布局
1.2 替换为通用弹窗
1.3 调用弹窗
1.4 显示效果参照FanChael/CommonPopupWindow
2. 分享弹窗
提供两种常用分享样式,源码支持四种常规平台按钮与复制链接,源码提供两种出场方式。源码
分享图标多时,源码支持水平滑动或网格展示,源码少于五个图标均匀分布。源码
默认分享调用,源码提供仿腾讯样式调用。
更新弹窗参考相关文档。网页颜色搭配源码
其他学习资源
比较Dialog, DialogFragment, PopupWindow,了解DialogFragment创建对话框的官方推荐。
学习声明周期管理,提高适配性,但不一定完全替代旧有方法。
通用弹窗需进一步完善,例如横竖屏切换等功能。
持续关注相关资料,量推公式源码持续学习与实践。
Android常è§ç¥è¯ç¹
跳槽æ éå°±æ¯é±å°äºæä¸ç½äºï¼æ 论æä¹æ ·ï¼è®°ä½ï¼ä¸è¦è£¸è¾ï¼
ä¸è¦è£¸è¾ï¼
ä¸è¦è£¸è¾ï¼
为ä»ä¹å¢ï¼
1ã裸è¾å°±æ²¡æé±æ¿äºï¼è¿ä¸å¦éªé©´æ¾é©¬ã
2ã裸è¾ä¹åå¦æä¸ä¸ªæå 没ææ¾å°å·¥ä½ï¼é£ä¹ç¤¾ä¿å°±ä¼æäºï¼é¤éä½ èªå·±æ¾æ¸ é交äºã
3ã裸è¾ä¹åççä¼å¾é¢åºï¼
å½åè¿å¨ä¸ççæ¶åå°±æ³çï¼è£¸è¾äºï¼é¦å è±å 天æ¶é´å§ç®åå®åä¸ä¸ï¼æç¥è¯ç¹æ¶è¡¥ä¸ä¸ï¼ç¶åæç®åï¼é¢è¯ï¼å¦¥å¦¥ç妥妥ã
ç»æå¢ï¼æ¯æ¬¡è£¸è¾ä¹åé½æ¯ï¼
é¦å 躺尸ä¸ä¸ªææï¼
ç¶åç¨äºä¸ä¸ªææææ ¢ååçæ¹å®ç®åï¼
ç¶åæµ·æï¼æ²¡åå¤ï¼ä¿®æ¹ç®åï¼
å次海æï¼é¢è¯ï¼è¢«èå¾ä½æ å®è¤ï¼æç人çï¼
åæ¹ç®åï¼åæµ·æï¼ä¸ä¸å°å¿ä¸äºã
å½ç¶æµ·æä¹æ¯æ个ç®æ èå´çã
å¦æä¸æ¯è£¸è¾ï¼é£ä¹ç°å¨åºè¯¥è¿æ¯å¨å ¬å¸ä¸çï¼å¨å®æå·¥ä½ä¹ä½ï¼å°±ä¼é¼çèªå·±å¤ä¹ ç¥è¯ç¹äºï¼èµ·ç ä¸ä¼å¨å®¶å è½ãå¨å®¶ä¸ä¸çå°±æ¯ç¡è§ãççµå½±ï¼æ¨¯æ©¹ç°é£ççï¼æ以ä¸è¦è£¸è¾ã
ç¶å¹¶åµï¼æä¾ç¶è£¸è¾äºã请åé¢è¯ççå¾ç¦ã
onPauseï¼åå¦ä»ActivityAå¯å¨Bï¼å¦æBæ¯éæçï¼åä¸ä¼åè°AçonStopæ¹æ³ã
æ¹æ³ä¸ï¼
æ¹æ³äºï¼
1ãå好å¨ç»æ件 R.anim.enter ã R.anim.exit
2ãè°ç¨ overridePendingTransition 设置å¨ç»
å¼ç³ï¼å¦Activity设置为singleInstanceï¼ååºè¯¥æä¹è®¾ç½®è·³è½¬å¨ç»ï¼
1ãstartServiceå¯å¨æ¹ä¸Service并没æå ³èï¼åªæå½Serviceè°ç¨ stopSelf æè å ¶å®ç»ä»¶è°ç¨ stopService çæ¶åæå¡æä¼ç»æ¢ã
2ãbindServiceå¯å¨æ¹ç»å®Serviceï¼å¹¶ä¸å¯ä»¥éè¿Binderä¸ä¹äº¤äºï¼å½å¯å¨æ¹éæ¯æ¶ï¼ä¹ä¼èªå¨unbindServiceï¼å½ææå¯å¨æ¹é½unbindServiceä¹åï¼Serviceä¹å°±èªå¨éæ¯äºã
为ä»ä¹å¢ï¼å®æ¹ææ¡£æ¯è¿æ ·åçï¼
大æ¦æææ¯ onReceive() æ§è¡å®æ¯ä¹åï¼å®æå¨çè¿ç¨å°±ä¼åæä½ä¼å 级è¿ç¨ï¼ææ被系ç»ææ»ã
å两ç§æ åµåæä¸ä¸ï¼
ä¸ãæ¶å°å¹¿æçæ¶åï¼åºç¨æ£å¨è¿è¡ï¼
æ¤æ¶å¦æ没æå¨Manifestä¸è®¾ç½®äºç¬ç«è¿ç¨ï¼å onReceive() å°±ç´æ¥å¨ä¸»è¿ç¨ä¸»çº¿ç¨æ§è¡ï¼è¿éå¾ææ¾ä¸è½æ§è¡èæ¶æä½ã
äºãæ¶å°å¹¿æçæ¶åï¼åºç¨æ²¡æå¯å¨ï¼
è¿æ¶åç³»ç»ä¼å¯å¨ä¸ä¸ªè¿ç¨å»æ§è¡ onReceive() ï¼ï¼å¦æManifestä¸æ²¡æ设置è¿ç¨åï¼åè¿ç¨å为å åï¼ï¼(æä¸å¥ï¼ææè¿ç¨é½ä¼å建ä¸ä¸ªApplicationå®ä¾)ï¼å½onReceiveæ§è¡å®æ¯ä¹åï¼æ¤è¿ç¨å°±åæä½ä¼å 级äºï¼éæ¶æå¯è½è¢«ç³»ç»ææ»ï¼å¦æä½ å¨onReceiveéé¢å¯å¨äºçº¿ç¨æ§è¡èæ¶ä»»å¡ï¼é£å¾æå¯è½å线ç¨æ²¡æ§è¡å®æ¯ï¼è¿ç¨å°±è¢«ææ»äºï¼è¿ç¨æ²¡äºï¼çº¿ç¨èªç¶å°±æäºã
é£ä¹ç¡®å®è¦æ§è¡èæ¶æä½å¢ï¼æä¹åï¼
æ¹æ³ä¸ï¼goAsync()
æ¹æ³äºï¼schedule a JobService from the receiver using the JobScheduler
ä¸ç§å®ç°æ¹æ³
1ã继æ¿ç°æçç»ä»¶ï¼å¦TextViewçï¼è¿è¡æå±ã
2ã继æ¿ViewGroupï¼èªå®ä¹å¸å±ã
3ã继æ¿Viewï¼å¨onDraw()ä¸æç»ã
onMeasure()
onLayout()
onDraw()
å ¶å®
attachToRoot ä»åé¢ç解就æ¯æ¯å¦ç»å®å° root ä¸é¢å»äºã
1ã attachToRoot=true ï¼åè¿åçview为rootçåviewï¼
2ã attachToRoot=false ï¼åè¿åçviewæ¯ä¸ªåç¬çviewï¼ä¼ å ¥çrootåªæ¯æä¾ä¸äºåæ°ç»view使ç¨èå·²ã
é£ä¹è¿éä¸ä¼ å ¥ attachToRoot å¢ï¼é£å°±çrootæ¯å¦ä¸ºç©ºäºï¼å¦æä¼ å ¥rootä¸ä¸ºç©ºï¼åé»è®¤ç»å®å°rootï¼ä½ä¸ºrootçåviewè¿åã
ä¹å°±æ¯æè°çFrameå¨ç»ãæéè¿æå®æ¯ä¸å¸§çå¾çåææ¾æ¶é´ï¼æåºçè¿è¡ææ¾èå½¢æå¨ç»ææã
å¯ä»¥éè¿æå ¥å¨ Interpolator æ§å¶å¨ç»çååé度ã
ä¹å°±æ¯æè°è¡¥é´å¨ç»ãæéè¿æå®Viewçåå§ç¶æãååæ¶é´ãæ¹å¼ï¼éè¿ä¸ç³»åçç®æ³å»è¿è¡å¾å½¢åæ¢ï¼ä»èå½¢æå¨ç»ææï¼ä¸»è¦æ AlphaAnimation ã TranslateAnimation ã ScaleAnimation ã RotateAnimation åç§ã
注æï¼åªæ¯å¨è§å¾å±å®ç°äºå¨ç»ææï¼å¹¶æ²¡æçæ£æ¹åViewçå±æ§ã
å±æ§å¨ç»ï¼éè¿ä¸æçæ¹åViewçå±æ§ï¼ä¸æçéç»èå½¢æå¨ç»ææãç¸æ¯äºè§å¾å¨ç»ï¼Viewçå±æ§æ¯çæ£æ¹åäºã
注æï¼Android 3.0(API )以ä¸ææ¯æã
æ常ç¨çç±»æ ObjectAnimator
P.S. æä¸æç½cancelåå¨çæä¹ã
å¦å¤ï¼ DialogFragment æ¯æ²¡æcancelçã
ping
å å大è´å为ä¸ä¸ªåºï¼æ åºãå åºãæ¹æ³åºã
æ åº
å åº
æ¹æ³åº
JAVAä¸å 许æå¨éæ¾å åï¼åªè½éè¿åå¾åæ¶ç¨åºä¸å®æ对é£äºä¸å被å¼ç¨ç对象è¿è¡åæ¶ã
é£ä¹æä¹å¤æåªäºå¯¹è±¡éè¦åæ¶ï¼
1ãå¼ç¨è®¡æ°æ³
å°±æ¯ç»å¯¹è±¡æ·»å ä¸ä¸ªå¼ç¨è®¡æ°å¨ï¼å¼ç¨å¯¹è±¡æ¶+1ï¼å¼ç¨å¤±ææ¶-1ãä½æ¯è¿ç§æ¹æ³è§£å³ä¸äºå¯¹è±¡ç¸äºå¼ç¨çæ åµã
2ãå¯è¾¾æ§åææ³
éè¿ä¸ç³»åâGCRootsâ对象ä½ä¸ºèµ·ç¹è¿è¡æç´¢ï¼å½GCRootsåä¸ä¸ªå¯¹è±¡ä¹é´æ²¡æå¯è¾¾è·¯å¾ï¼å认为æ¤å¯¹è±¡ä¸å¯ç¨ï¼ä½æ¯ä¸å¯ç¨ä¸ä¸å®ä¼æ为å¯åæ¶å¯¹è±¡ã
ç¼åAIDLæ件ï¼å®ä¹æ¥å£ã
ç¼è¯çæJAVAæ件ã
å®ä¹è¿ç¨çº§Serviceï¼onBindä¸è¿åInterface.Stub()ã
onServiceConnectedä¸Interface aidl = Interface.Stub.asInterface(service);
æ已修å¤çclassæ件æå ædexæ件ï¼ç½ç»ä¼ è¾å°ç¨æ·ææºä¸ï¼å©ç¨ç±»å è½½å¨æè¿äºç±»å è½½å°ç±»éåçåé¢å³å¯ã
ãæªå®å¾ ç»ã
å¦æå ¬å¸å½ç¨æï¼ä¸ç®¡æ¯ä¸å¹´è¿æ¯äºå¹´ï¼é¦å æé½ä¼å æå ¬å¸çä»»å¡å好ï¼ç¶åä¸ææ·±å ¥ç 究Androidçç¸å ³ææ¯ï¼ç¹å«æ¯Androidæºç ï¼äºè§£Androidåºå±åçï¼ä»¥ä¾¿æ´å¥½çä¼åæ§è½ï¼é¿å ä¸äºä¸å¿ è¦çå¥è©é®é¢ï¼è¿æå°±æ¯ç 究ä¸äºæ°çæ¡æ¶çåçï¼å¦ä¹ å«äººçæç»´ãæåå°±æ¯å¦ä¹ å¨è¾¹è¯è¨ï¼æ¯å¦åå°ï¼å端ççã
Navigation源码解析及自定义FragmentNavigator详解
谷歌推出的Navigation主要目标是统一应用内页面跳转行为。使用方法简单,新项目选择Bottom Navigation Activity,系统自动生成页面逻辑。
Navigation源码设计简洁,包含多个关键类。其中,自建邮箱系统源码NavHostFragment是直接在XML文件中定义的,其生命周期方法onCreate中直接创建了NavHostController,并通过findNavController暴露给外部调用者。NavHostController继承自NavController。在此过程中,通过navController获取NavigatorProvider并添加了两个Navigator:DialogFragmentNavigator和FragmentNavigator。NavController构造方法中还额外添加了两个Navigator,分别对应DialogFragment、git怎么扒源码Fragment和Activity的页面跳转。NavGraphNavigator用于在XML配置的navGraph与根节点文件中的startDestination之间实现跳转,功能单一。
各个Navigator通过重写navigate方法实现各自的跳转逻辑。FragmentNavigator的关键实现在于注释1处,使用replace加载Fragment,这不符合实际开发需求。文章后续将解释如何自定义FragmentNavigator以避免Fragment在切换时执行生命周期。
NavigatorProvider内部维护了一个HashMap存储相关Navigator信息,通过获取Navigator的注解Name作为键和getClass作为值进行存储。在onCreate方法中,mNavController调用了setGraph,解析XML配置的mobile_navigation节点信息文件,根据不同的节点各自解析。通过获取NavInflater进行解析,返回NavGraph,NavGraph继承自NavDestination,保存了所有解析出的节点信息。
总结,通过NavHostFragment获取到NavContorl并存储了相关Navigator信息。通过各自navigate方法进行页面跳转,通过setGraph解析配置的页面节点信息并封装为NavGraph对象。其中,通过SparseArray存储Destination信息。
自定义Navigator实现思路主要在于继承现有FragmentNavigator并重写其navigate方法,将replace方法替换为show和hide方法,完成Fragment切换。通过@Navigator.Name(value)注解标记自定义类为Navigator,加入NavigatorProvider中即可识别。自定义Navigator核心代码实现后,需调整mobile_navigation节点中的fragment为fixFragment,并删除布局文件中NavHostFragment节点信息,手动关联FixFragmentNavigator与NavControl,完成Fragment切换时生命周期不会重新执行。
Android åçBottomSheet ä»ç»åå
Android Support Library .2 æ¨åºä¹åï¼å¢å äºå 个åè½ï¼ä¾å¦æ¯æVector Drawables åAnimated Vector Drawablesï¼å¢å AppCompat DayNight 主é¢ï¼Design åºä¸å¢å Bottom Sheetsï¼RecyclerView æ¯æ auto-measurementï¼ä¹åçwrap_content ,match_parent é½å°å¯ä»¥åæ¥ä½ç¨çç
å ¬å¸çApp ä¹å使ç¨è¿ç¬¬ä¸æ¹ç[BottomSheet] ï¼ /BottomSheet ï¼ï¼ç°å¨Android æèªå·±çBottomSheet é£è¿ä¸èµ¶ç´§æ¢æåççãç¶è好äºå¤ç£¨ï¼Android åçBottomSheet èµæ太å°ï¼æ·±ç ä¸å»åç°BottomSheet å°±æ¯ä¸ªå¤§åï¼
BottomSheet 使ç¨éè¦CoordinatorLayoutä½ä¸ºç¶å¸å±ï¼BottomSheet çå¸å±ä½ä¸ºCoordinatorLayout çåå¸å±ï¼å¹¶ä¸BottomSheetBehaviorï¼æ¯å¦å ä¸app:layout_behavior=âandroid.support.design.widget.BottomSheetBehaviorâï¼
å®é 使ç¨è¿ç¨ä¸ä¸»è¦ä¾é BottomSheetBehavioræ¥æ§å¶BottomSheetçå±ç¤ºååè°ã
BottomSheetBehavior å ·æäºç§ç¶æï¼
设置ç¶æï¼
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
åè°ï¼
强è°ï¼
BottomSheetBehaviorå°è½å¸®ä½ å®ç° 常驻bottom sheetï¼ persistent bottom sheetï¼ çåºæ¯, ä½è¿ä¸ªçæ¬è¿æä¾äºBottomSheetDialog å BottomSheetDialogFragment æ¥å®ç° modal bottom sheets çåºæ¯ãåªéè¦å°AppCompatDialog æè AppCompatDialogFragmentåå«æ¿æ¢æä¸è¿°ç两个æ§ä»¶ï¼ä½ å°±æ¥æäº bottom sheet é£æ ¼ç对è¯æ¡
ç¶èæ们å®é æ们éè¦BottomSheetDialog æ¯å±å¼çï¼èBottomSheetDialogåªå±ç¤ºä¸é¨å
åå ï¼BottomSheetDialogé»è®¤æ¯STATE_COLLAPSEDï¼ææBottomSheetDialog ä¾é peekHightæ¥è®¾ç½®é«åº¦ï¼ç³»ç»BottomSheetDialog é»è®¤é«åº¦ä¸ºdpï¼æ¥æºç å¾ç¥ï¼,é£æçæ¥è¯´æ们çBottomSheetDialog é«åº¦è¯¥æ¯dpï¼ä½æ¯æ们å®é åç°BottomSheetDialogé«åº¦ä¹ä¸çäºdpãæ们ç 究ä¸BottomSheetBehaviorçä¸æ§å¶BottomSheetDialogé«åº¦æºç :
éè¿æºç æ们å¯ä»¥å¾ç¥BottomSheetBehavioréè¿æ¹åchildçå移éèæ§å¶BottomSheetDialogçé«åº¦ï¼é»è®¤ç¶æ为STATE_COLLAPSED,childåä¸ç§»å¨mMaxOffseté«åº¦ï¼ä»èæ§å¶childæ¾ç¤ºé«åº¦ä¸ºmPeekHeight,è¿å°±éè¦childä¸parent 顶é¨å¯¹é½ï¼childçgetTop 为0ï¼
ç¶èæ们åå»æ¥çAndroidçBottomSheetDialog å ä¸å¸å±R.layout.design_bottom_sheet_dialog,åç°æ们èªå®ä¹ççBottomSheetDialog çcontentView æ¯æ¾ç½®å¨FrameLayout ä¸çï¼ç¶èFrameLayoutåºäºæäºåå 为åç´å± ä¸çï¼èä¸æ¯é¡¶é¨å¯¹é½ï¼ä»è导è´BottomSheetDialogå¨dpçåºç¡ä¸åä¸å移,åªå±ç¤ºä¸é¨åã
æ以æ们å¯ä»¥éè¿ä¸é¢æ¹æ³è§£å³BottomSheetDialog çæ¾ç¤ºé®é¢
解å³æ¹æ³å¦ä¸ï¼
å½æ们设置bottomSheetDialogæ¯æ¬¡ç¹å»åä¸new,èæ¯ç´æ¥showçè¯ï¼ç¶èå½æ们ä¼bottomSheetDialog å±å¼åï¼æ们å°BottomSheetDialogåä¸éèåï¼ åç¹å»å±ç¤ºBottomSheetDialogåï¼ä¼åç°é¡µé¢åªæ¯åæï¼BottomsheetDialogæªå±å¼ï¼è¿æ¯ç±äºä¹åæ们åä¸æ¶ç¼©éèBottomSheetDialogåï¼bottomSheetDialogBehaviorçç¶æ为éèï¼å次showä¹åï¼ç³»ç»æªæ¢å¤bottomSheetDialogBehaviorçç¶æï¼è¿æ¯éèï¼æ以å次ç¹å»å页é¢åªæ¯åæã