1.怎样查看网页源代码
2.Androidä¸Viewçå建è¿ç¨
3.跑马灯带你深入浅出TextView的源码源码世界
4.èªå®ä¹View(1)
5.scrolltoåscrollbyçåºå«
6.最简最全,一文搞定Android WebView编译+AOSP集成
怎样查看网页源代码
要查看网页源代码,有两种简单的源码方法可供选择:
首先,如果你使用的源码是IE浏览器,可以在地址栏输入特定的源码命令。只需键入"view-source:网址",源码dubbo源码教程视频例如"view-source:"。源码这会直接显示出新浪网首页的源码源代码,而非实际加载的源码页面。这种方法尤其适合对HTML有一定了解的源码用户,它可以帮助你检查网站的源码安全性,识别是源码否存在恶意代码。在访问陌生网站之前,源码先通过查看源代码来确认其安全性是源码明智的做法。
其次,源码更为直观的方式是使用鼠标操作。在网页上,只需右键点击,然后选择"查看源文件"或"查看网页源代码",电表小程序源码这将直接显示页面的原始HTML和CSS代码,方便你快速检查其结构和内容。
通过这两种方法,你可以轻松地检查网页的原始信息,确保在线浏览的安全和隐私。在进行任何交互或分享之前,了解网页的源代码是现代网络用户必备的技能之一。
Androidä¸Viewçå建è¿ç¨
æ们ç¥éå¨onCreateéé¢Viewè¿æ¯æ²¡ææµç»å®æçãé£ä¹ä»ä¹æ¶åæµç»å®æäºï¼çæ¡æ¯onResumeãéè¿æ¥çæºç æ们å¯ä»¥çå°å¨onCreateæ¹æ³éé¢è°ç¨äºgetWindow()æ¹æ³ç¶åå¨å°æ们ç页é¢å¡å°è¿ä¸ªwindowéé¢ãè¿ä¸ªwindowä¹å°±æ¯PhonwWindow.
é£PhoneWindowæ¯ä»ä¹æ¶å被å建çï¼
è¿å°±å¼åºäºActivityçå建æµç¨ã
é£Activityæ¯æä¹è¢«å建çå¢ï¼
ç±äºActivityæ¯ä¸ä¸ªç»ä»¶ä»æ¯ç±ç³»ç»ä½¿ç¨ActivityThreadæ¹æ³å»å建çã
ç°å¨ææ¥åæä¸ï¼
å æ¥å°ActivityThreadç±»çhandleLaunchActivityæ¹æ³ã
å¯ä»¥çå°ä»å»è°ç¨äºActivityçperformCreateæ¹æ³ã
ç°å¨æ们ç»äºçå°onCreateæ¹æ³è¢«è°ç¨äºã
è¿éè¿æ个éç¹ï¼å¨performLaunchActivityéé¢å»è°ç¨ActivityçonCreateæ¹æ³ä¹åè¿å»åäºä¸ä»¶å¾éè¦çäºæ ï¼è¿ä¸ªäºæ å¨ç¬¬è¡ï¼è°ç¨äºActivityçattachæ¹æ³ã
ç°å¨è·å°Activityçattachæ¹æ³ï¼æ¾å°äºæ们ä¸ç´æ¾çPhoneWindowçå建ã
跑马灯带你深入浅出TextView的源码世界
本文将深入浅出地解析Android系统中TextView的跑马灯动画源码,以解决开发者在实际开发中遇到的问题。文章将通过一个具体问题作为出发点,引导读者从源码的角度分析和解决问题。 首先,面临的问题是Android 6.0及以上系统中点击“添加购物车”按钮时,TextView的跑马灯动画会出现跳动现象(动画重置,滚动从头开始)。面对这一现象,开发者往往需要从源码层面进行深入分析。 为了解决问题,vrc矿机源码文章建议采用以下步骤进行源码分析: 搜索“Android TextView 跑马灯原理”,找到关键代码实现,特别是与跑马灯启动相关的startMarquee()方法。 使用Android Studio搜索TextView并查看类接口图,找到startMarquee()方法的实现,对其进行初步分析。 确定找到的方法正确后,继续了解整个框架的实现流程,绘制主流程图。 接下来,文章将深入分析跑马灯动画的实现机制,包括TextView、Marquee内部类以及Choreographer系统。 在分析中,文章指出Choreographer是一个用于管理动画、输入和绘制的系统类,它通过监听DisplayEventReceiver来接收系统信号,并在每一帧中回调以确保动画的新源代源码社区平滑性。在Choreographer中,Marquee会计算偏向值,然后触发TextView的刷新来实现动画效果。 文章进一步解析了Choreographer的实现原理以及Marquee在postFrameCallback中的具体操作,包括计算时间差、移动位移以及触发TextView刷新的过程。 最后,文章对问题进行了详细分析,揭示了导致跑马灯动画重置的根源在于“购物车”按钮的setText方法触发了requestLayout,从而导致了视图重绘。通过修改按钮的布局属性,问题得以解决。 总结而言,文章通过问题分析和源码解析,为开发者提供了一条清晰的路径,从现象出发,深入源码,最终找到问题的最大源码分享根本原因并解决,从而提升对Android系统内核的理解和应用能力。èªå®ä¹View(1)
ç»åè¿åé¢ä¸ç¯å°å°å¦å¦çåºç¡ç¯ä¹åï¼ç»äºå°äºè¿é¶ç¯ï¼æ£å¼è¿å ¥è§£æèªå®ä¹Viewçé¶æ®µãè³äºæ¬ç« è为ä»ä¹è¦å«è¿é¶ç¯(è½ç¶è®²çæ¯åºç¡çå 容)ï¼å 为ä»æ¬ç¯å¼å§ï¼å°ä¼éæ¸æå¼èªå®ä¹Viewçç¥ç§é¢çº±ï¼æ¯ä¸ç¯é½å°æ¯ä¸ä¸ç¯å 容æ´å æ·±å ¥ï¼å©ç¨æå¦çç¥è¯è½å¤å¶ä½æ´å ç«é ·èªå®ä¹Viewï¼å°±åå¨å°é¶ä¸ä¸æ ·ï¼æ¯ä¸ç¯é½æ´ä¸ä¸å±ï¼ 帮å©å¤§å®¶ä¸æ¥æ¥èµ°å人çå· å³°ï¼åºä»»CEOï¼èµ¢åç½å¯ç¾ã 误ï¼æ¯å¸®å©å¤§å®¶æ´å äºè§£é£äºç«é ·çèªå®ä¹Viewæ¯å¦ä½å¶ä½çï¼è¾¾å°ä¸¾ä¸åä¸çææã
ä½ä¸ºä¸ä¸ª<b>æ(hui)追(zhuang)æ±(B)</b>çç¨åºåï¼è¯å®æ³åä¸äºè®©äººç¼åä¸äº®çç¨åºææï¼ä½æ¯ç³»ç»æä¾çé£äºä¸è¬å¾é¾æ»¡è¶³ï¼ä¸ºäº<b>梦(zhuang)æ³(B)</b>å°±å¿ é¡»è¦å¦ä¹ ä¸äºèªå®ä¹Viewãä¸é¢æ们就äºè§£ä¸äºèªå®ä¹Viewç¸å ³çä¸è¥¿ã
èªå®ä¹ViewGroupä¸è¬æ¯å©ç¨ç°æçç»ä»¶æ ¹æ®ç¹å®çå¸å±æ¹å¼æ¥ç»ææ°çç»ä»¶ï¼å¤§å¤ç»§æ¿èªViewGroupæåç§Layoutï¼å å«æåViewã
ä¾å¦ï¼ä¸ä¸ªåºç¨å çåºé¨å¯¼èªæ¡ä¸çæ¡ç®ï¼ä¸è¬é½æ¯ä¸é¢ä¸ºå¾æ ï¼ä¸é¢æ¯æåï¼é£ä¹è¿ä¸¤ä¸ªå°±å¯ä»¥ç¨èªå®ä¹ViewGroupç»åæ为ä¸ä¸ªVeiwï¼æä¾ä¸¤ä¸ªå±æ§åå«ç¨æ¥è®¾ç½®æååå¾çå³å¯ï¼è¿æ ·ä½¿ç¨èµ·æ¥ä¼æ¹ä¾¿å¾å¤ã
å¨æ²¡æç°æçViewï¼éè¦èªå·±å®ç°çæ¶åï¼å°±ä½¿ç¨èªå®ä¹Viewï¼ä¸è¬ç»§æ¿èªViewï¼SurfaceViewæå ¶ä»çViewï¼ä¸å å«åViewã
ä¾å¦ï¼å®ä¹ä¸ä¸ªæ¯æèªå¨å è½½ç½ç»å¾ççImageViewï¼æå¶ä½ä¸ç§ç¹æ®çå¨ç»ææã
<b>ä¸è¬æ¥è¯´ï¼èªå®ä¹Viewå¨å¤§å¤æ°æ åµä¸é½ææ¿ä»£æ¹æ¡ï¼å©ç¨å¾çæè ç»åå¨ç»æ¥å®ç°ï¼ä½æ¯ä½¿ç¨åè å¯è½ä¼é¢ä¸´å åèè´¹è¿å¤§ï¼å¶ä½éº»ç¦æ´è¯¸å¤é®é¢ã</b>
Viewçæé å½æ°æåç§éè½½åå«å¦ä¸
å¯ä»¥çåºï¼å ³äºViewæé å½æ°çåæ°æå¤æå°ï¼å æé¤å 个ä¸å¸¸ç¨çï¼çä¸å¸¸ç¨çåç 究ã
<b>æå个åæ°çæé å½æ°å¨APIçæ¶åææ·»å ä¸ï¼æä¸è¬ä¸ä½¿ç¨ï¼æä¸èèã</b>
æä¸ä¸ªåæ°çæé å½æ°ä¸ç¬¬ä¸ä¸ªåæ°æ¯é»è®¤çStyleï¼è¿éçé»è®¤çStyleæ¯æå®å¨å½åApplicationæActivityæç¨çThemeä¸çé»è®¤Styleï¼ä¸åªæå¨æç¡®è°ç¨çæ¶åæä¼çæï¼ä»¥ç³»ç»ä¸çImageButton为ä¾è¯´æï¼
<b>注æï¼å³ä½¿ä½ å¨Viewä¸ä½¿ç¨äºStyleè¿ä¸ªå±æ§ä¹ä¸ä¼è°ç¨ä¸ä¸ªåæ°çæé å½æ°ï¼æè°ç¨çä¾æ§æ¯ä¸¤ä¸ªåæ°çæé å½æ°ã</b>
<b>ç±äºä¸ä¸ªåæ°çæé å½æ°ç¬¬ä¸ä¸ªåæ°ä¸è¬ä¸ç¨ï¼æä¸èèï¼ç¬¬ä¸ä¸ªåæ°çå ·ä½ç¨æ³ä¼å¨ä»¥åç¨å°çæ¶å详ç»ä»ç»ã</b>
æé¤äºä¸¤ä¸ªä¹åï¼åªå©ä¸ä¸ä¸ªåæ°å两个åæ°çæé å½æ°ï¼ä»ä»¬ç详æ å¦ä¸ï¼
以ä¸æ¹æ³è°ç¨çæ¯<b>ä¸ä¸ªåæ°</b>çæé å½æ°ï¼
以ä¸æ¹æ³è°ç¨çæ¯<b>两个åæ°</b>çæé å½æ°ï¼
å ³äºæé å½æ°å 讲è¿ä¹å¤ï¼å ³äºå¦ä½èªå®ä¹å±æ§å使ç¨attrsä¸çå 容ï¼å¨åé¢ä¼è¯¦ç»è®²è§£ï¼ç®ååªéè¦ç¥éè¿ä¸¤ä¸ªæé å½æ°å¨ä½æ¶è°ç¨å³å¯ã
========
æµéView大å°ä½¿ç¨çæ¯onMeasureå½æ°ï¼æ们å¯ä»¥ä»è¿ä¸¤ä¸ªåæ°ååºå®½é«çç¸å ³æ°æ®ï¼
ä»ä¸é¢å¯ä»¥çåº onMeasure å½æ°ä¸æ widthMeasureSpec å heightMeasureSpec è¿ä¸¤ä¸ª int ç±»åçåæ°ï¼ 毫æ çé®ä»ä»¬æ¯å宽é«ç¸å ³çï¼ <b>ä½å®ä»¬å ¶å®ä¸æ¯å®½åé«ï¼ èæ¯ç±å®½ãé«ååèªæ¹åä¸å¯¹åºç模å¼æ¥åæçä¸ä¸ªå¼ï¼</b>
å¨intç±»åçä½äºè¿å¶ä½ä¸ï¼-è¿ä¸¤ä½è¡¨ç¤ºæ¨¡å¼,~0è¿ä¸åä½è¡¨ç¤ºå®½åé«çå®é å¼ã
以æ°å¼(äºè¿å¶ä¸º: )为ä¾(å ¶ä¸æ¨¡å¼åå®é æ°å¼æ¯è¿å¨ä¸èµ·çï¼ä¸ºäºå±ç¤ºæå°ä»ä»¬åå¼äº)ï¼
å®é ä¸å ³äºä¸é¢çä¸è¥¿äºè§£å³å¯ï¼å¨å®é è¿ç¨ä¹ä¸åªéè¦è®°ä½æä¸ç§æ¨¡å¼ï¼ç¨ MeasureSpec ç getSizeæ¯è·åæ°å¼ï¼ getModeæ¯è·å模å¼å³å¯ã
å¦æ对Viewç宽é«è¿è¡ä¿®æ¹äºï¼<b>ä¸è¦è°ç¨super.onMeasure(widthMeasureSpec,heightMeasureSpec);</b>
è¦è°ç¨<b>setMeasuredDimension(widthsize,heightsize);</b> è¿ä¸ªå½æ°ã
======
è¿ä¸ªå½æ°å¨è§å¾å¤§å°åçæ¹åæ¶è°ç¨ï¼
onSizeChangedå¦ä¸ï¼
å¯ä»¥çåºï¼å®åå个åæ°ï¼åå«ä¸º 宽度ï¼é«åº¦ï¼ä¸ä¸æ¬¡å®½åº¦ï¼ä¸ä¸æ¬¡é«åº¦ã
è¿ä¸ªå½æ°æ¯è¾ç®åï¼æ们åªéå ³æ³¨ 宽度(w), é«åº¦(h) å³å¯ï¼è¿ä¸¤ä¸ªåæ°å°±æ¯Viewæç»ç大å°ã
=========
<b>ç¡®å®å¸å±çå½æ°æ¯onLayoutï¼å®ç¨äºç¡®å®åViewçä½ç½®ï¼å¨èªå®ä¹ViewGroupä¸ä¼ç¨å°ï¼ä»è°ç¨çæ¯åViewçlayoutå½æ°ã</b>
ä¸è¿å ³äºViewçlayoutå½æ°æ们ä¸è¬æ éå ³æ³¨ï¼å 为å¨ä¸è¬æ åµä¸æ们åªéå ³æ³¨Viewèªèº«çåæ ç³»å³å¯ï¼é¤éViewç¶æä¸å¨ç¶VIewæå¤ä½ç½®ç¸å ³ã
å¨èªå®ä¹ViewGroupä¸ï¼onLayoutä¸è¬æ¯å¾ªç¯ååºåViewï¼ç¶åç»è¿è®¡ç®å¾åºå个åViewä½ç½®çåæ å¼ï¼ç¶åç¨ä»¥ä¸å½æ°è®¾ç½®åViewä½ç½®ã
å个åæ°åå«ä¸ºï¼
å ·ä½å¯ä»¥åè åæ ç³» è¿ç¯æç« :
PSï¼å ³äºonLayoutè¿ä¸ªå½æ°å¨è®²è§£èªå®ä¹ViewGroupçæ¶åä¼è¯¦ç»è®²è§£ã
========
onDrawæ¯å®é ç»å¶çé¨åï¼ä¹å°±æ¯æ们çæ£å ³å¿çé¨åï¼ä½¿ç¨çæ¯Canvasç»å¾ã
å ³äºCanvasç»å¾å¦åä¸ç« å§ï¼æ¬æ¥æ³åä¸äºå ³äºCanvasåºæ¬æä½ççï¼å¯æ¯ç¯å¹ 太é¿äºQAQï¼ ç个尾巴ä¸ä¸ç¯ååå§ï¼æ¯ç«Canvasç»å¾ä¹æ¯ä¸ä¸ªæ¯è¾åºå¤§çä¸è¥¿ï¼ä¹ä¸æ¯ä¸è¨ä¸¤è¯å°±è½è®²æç½çï¼å°±å°è¿éå§ã
======
èªå®ä¹å®Viewä¹åï¼ä¸è¬ä¼å¯¹å¤æ´é²ä¸äºæ¥å£ï¼ç¨äºæä½Viewçç¸å ³å±æ§ï¼æ§å¶Viewçç¶æçï¼æè éè¦çå¬Viewçååï¼å ·ä½è¿æ¯ç¨åå讲å§(继ç»æå)ã
PS ï¼å®é ä¸ViewGroupæ¯Viewçä¸ä¸ªåç±»ã
View
ViewGroup
View.MeasureSpec
onMeasureï¼MeasureSpecæºç æµç¨ æ路详解
Androidä¸èªå®ä¹æ ·å¼ä¸Viewçæé å½æ°ä¸ç第ä¸ä¸ªåæ°defStyleçæä¹
android viewæé å½æ°ç 究
Android Viewæé æ¹æ³ç¬¬ä¸åæ°ä½¿ç¨æ¹æ³è¯¦è§£
Android èªå®ä¹View onMeasureæ¹æ³çå®ç°
Android APIæå(äº)èªå®ä¹æ§ä»¶ä¹ onMeasure
Androidä¸Viewçç»å¶è¿ç¨ onMeasureæ¹æ³ç®è¿°
scrolltoåscrollbyçåºå«
ããViewç±»çæºä»£ç å¦ä¸æ示ï¼mScrollXè®°å½çæ¯å½åViewé对å±å¹åæ å¨æ°´å¹³æ¹åä¸çå移éï¼èmScrollYåæ¯è®°å½çæ¶å½åViewé对å±å¹å¨ç«å¼æ¹åä¸çå移éã
ããä»ä»¥ä¸ä»£ç å¯ä»¥å¾ç¥ï¼scrollToå°±æ¯æView移å¨å°å±å¹çXåYä½ç½®ï¼ä¹å°±æ¯ç»å¯¹ä½ç½®ãèscrollByå ¶å®å°±æ¯è°ç¨çscrollToï¼ä½æ¯åæ°æ¯å½åmScrollXåmScrollYå ä¸XåYçä½ç½®ï¼æ以ScrollByè°ç¨çæ¯ç¸å¯¹äºmScrollXåmScrollYçä½ç½®ãå¨ä¸é¢ç代ç ä¸å¯ä»¥çå°å½ææä¸æ¾ç§»å¨å±å¹æ¶ï¼å°±ä¼è°ç¨scrollByæ¥ç§»å¨ä¸æ®µç¸å¯¹çè·ç¦»ãèå½æ们æææ¾å¼åï¼ä¼è°ç¨ mScroller.startScroll(mUnboundedScrollX, 0, delta, 0, duration);æ¥äº§çä¸æ®µå¨ç»æ¥ç§»å¨å°ç¸åºç页é¢ï¼å¨è¿ä¸ªè¿ç¨ä¸ç³»ç»åä¸æè°ç¨computeScroll()ï¼å使ç¨scrollToæ¥æView移å¨å°å½åScrolleræå¨çç»å¯¹ä½ç½®ã
ãã/
*** Set the scrolled position of your view. This will cause a call to
* { @link #onScrollChanged(int, int, int, int)} and the view will be
* invalidated.
* @param x the x position to scroll to
* @param y the y position to scroll to
*/
public void scrollTo(int x, int y) {
if (mScrollX != x || mScrollY != y) {
int oldX = mScrollX;
int oldY = mScrollY;
mScrollX = x;
mScrollY = y;
invalidateParentCaches();
onScrollChanged(mScrollX, mScrollY, oldX, oldY);
if (!awakenScrollBars()) {
invalidate(true);
}
}
}
/
*** Move the scrolled position of your view. This will cause a call to
* { @link #onScrollChanged(int, int, int, int)} and the view will be
* invalidated.
* @param x the amount of pixels to scroll by horizontally
* @param y the amount of pixels to scroll by vertically
*/
public void scrollBy(int x, int y) {
scrollTo(mScrollX + x, mScrollY + y);
}
最简最全,一文搞定Android WebView编译+AOSP集成
对于Android开发者来说,Android WebView是不可或缺的内置组件,它提供了一键可用的网页浏览功能。然而,WebView作为系统组件,其版本更新受限于系统级别的开发,可能导致HTML5、ES、CSS特性支持不足。本文将详细介绍如何从Chromium源码编译定制WebView,以及如何集成到AOSP系统中。
首先,确保你已经下载并配置好Chromium源码。编译时,使用gn命令生成args.gn文件,其中需新增system_webview_package_name选项来设置自定义APK包名,特别注意不同Android版本的WebView包名差异。编译目标有三种:system_webview_apk(适用于5.0及以上,独立APK)、monochrome_public_apk(包含WebView和Chrome,适用于自开发系统)和trichrome_webview_apk(适用于Android +,采用aab拆分)。
编译完成后,根据目标选择对应的APK,如system_webview_apk将生成一个SystemWebview.apk,包内包含WebView DevTools,用于调试。通过修改args.gn文件中的包名,确保与系统预装WebView的版本一致。如果在非AOSP系统中,可能需要使用adb或其他工具检查并修改包名。
在编译过程中,还需注意在系统中卸载预装的WebView以避免签名冲突。使用adb脚本进行一键卸载,然后将编译好的APK安装到设备,可能还需修改WebView提供者以指向新安装的版本。
对于AOSP集成,虽然预编译的WebView在AOSP中可用,但建议使用自编译的最新稳定版。根据目标Android版本选择合适的Chromium稳定版代码,并注意兼容性问题。编译正式发布版本时,需设置is_official_build和proprietary_codecs等选项,同时考虑视频编解码的许可证问题。
最后,对于私有签名、包名修改、系统镜像集成以及Android框架的修改,都有详细的步骤和注意事项。编译WebView并成功集成到AOSP后,可以确保为用户提供最新、定制化的浏览器体验。
Android UIç»å¶ä¹Viewç»å¶çå·¥ä½åç
è¿æ¯AndroidUIç»å¶æµç¨åæç第äºç¯æç« ï¼ä¸»è¦åæçé¢ä¸Viewæ¯å¦ä½ç»å¶å°çé¢ä¸çå ·ä½è¿ç¨ãViewRoot 对åºäº ViewRootImpl ç±»ï¼å®æ¯è¿æ¥ WindowManager å DecorView ç纽带ï¼Viewçä¸å¤§æµç¨åæ¯éè¿ ViewRoot æ¥å®æçãå¨ ActivityThread ä¸ï¼å½ Activity 对象被å建å®æ¯åï¼ä¼å° DecorView æ·»å å° Window ä¸,åæ¶ä¼å建 ViewRootImpl 对象ï¼å¹¶å° ViewRootImpl 对象å DecorView 建ç«å ³èã
measure è¿ç¨å³å®äº View ç宽/é«ï¼ Measure å®æ以åï¼å¯ä»¥éè¿ getMeasuredWidth å getMeasuredHeight æ¹æ³æ¥è·å View æµéåç宽/é«ï¼å¨å ä¹ææçæ åµä¸ï¼å®çåäºViewçæç»ç宽/é«ï¼ä½æ¯ç¹æ®æ åµé¤å¤ã Layout è¿ç¨å³å®äº View çå个顶ç¹çåæ åå®é ç宽/é«ï¼å®æ以åï¼å¯ä»¥éè¿ getTopãgetBottomãgetLeft å getRight æ¥æ¿å°Viewçå个顶ç¹çä½ç½®ï¼å¯ä»¥éè¿ getWidth å getHeight æ¹æ³æ¿å°Viewçæç»å®½/é«ã Draw è¿ç¨å³å®äº View çæ¾ç¤ºï¼åªæ draw æ¹æ³å®æå View çå 容æè½åç°å¨å±å¹ä¸ã
DecorView ä½ä¸ºé¡¶çº§ View ï¼ä¸è¬æ åµä¸ï¼å®å é¨ä¼å å«ä¸ä¸ªç«ç´æ¹åç LinearLayout ï¼å¨è¿ä¸ª LinearLayout éé¢æä¸ä¸ä¸¤ä¸ªé¨åï¼ä¸é¢æ¯æ é¢æ ï¼ä¸é¢æ¯å 容æ ãå¨Activityä¸ï¼æ们éè¿ setContentView æ设置çå¸å±æä»¶å ¶å®å°±æ¯è¢«å å°å 容æ ä¸çï¼èå 容æ id为 content ãå¯ä»¥éè¿ä¸é¢æ¹æ³å¾å° content:ViewGroup content = findViewById(R.android.id.content) ãéè¿ content.getChildAt(0) å¯ä»¥å¾å°è®¾ç½®ç view ã DecorView å ¶å®æ¯ä¸ä¸ª FrameLayout , View å±çäºä»¶é½å ç»è¿ DecorView ï¼ç¶åæä¼ éç»æ们ç View ã
MeasureSpec 代表ä¸ä¸ªä½çintå¼ï¼é«2ä½ä»£è¡¨ SpecMode ,ä½ä½ä»£è¡¨ SpecSize , SpecMode æ¯ææµé模å¼ï¼è SpecSize æ¯æå¨æç§æµé模å¼ä¸çè§æ ¼å¤§å°ã
SpecMode æä¸ç±»ï¼å¦ä¸æ示ï¼
UNSPECIFIED
EXACTLY
AT_MOST
LayoutParamséè¦åç¶å®¹å¨ä¸èµ·æè½å³å®ViewçMeasureSpecï¼ä»èè¿ä¸æ¥å³å®Viewç宽/é«ã
对äºé¡¶çº§Viewï¼å³DecorViewåæ®éViewæ¥è¯´ï¼MeasureSpecç转æ¢è¿ç¨ç¥æä¸åã对äºDecorViewï¼å ¶MeasureSpecç±çªå£ç尺寸åå ¶èªèº«çLayoutParamså ±åç¡®å®ï¼
对äºæ®éViewï¼å ¶MeasureSpecç±ç¶å®¹å¨çMeasureSpecåèªèº«çLayoutparamså ±åå³å®ï¼
MeasureSpecä¸æ¦ç¡®å®ï¼onMeasureå°±å¯ä»¥ç¡®å®Viewçæµé宽/é«ã
å°ç»ä¸ä¸
å½å View ç宽é«éç¨ wrap_content æ¶ï¼ä¸ç®¡ç¶å®¹å¨ç模å¼æ¯ç²¾ç¡®æ¨¡å¼è¿æ¯æ大模å¼ï¼å View ç模å¼æ»æ¯æ大模å¼+ç¶å®¹å¨çå©ä½ç©ºé´ã
View çå·¥ä½æµç¨ä¸»è¦æ¯æ measure ã layout ã draw ä¸å¤§æµç¨ï¼å³æµéãå¸å±ãç»å¶ãå ¶ä¸ measure ç¡®å® View çæµé宽/é«ï¼ layout ç¡®å® view çæç»å®½/é«åå个顶ç¹çä½ç½®ï¼è draw åå° View ç»å¶å¨å±å¹ä¸ã
measure è¿ç¨è¦åæ åµï¼å¦æåªæ¯ä¸ä¸ªåå§ç view ï¼åéè¿ measure æ¹æ³å°±å®æäºå ¶æµéè¿ç¨ï¼å¦ææ¯ä¸ä¸ª ViewGroup ï¼é¤äºå®æèªå·±çæµéè¿ç¨å¤ï¼è¿ä¼éåè°ç¨ææåå ç´ ç measure æ¹æ³ï¼å个åå ç´ åéå½å»æ§è¡è¿ä¸ªæµç¨ã
å¦ææ¯ä¸ä¸ªåå§ç Viewï¼é£ä¹éè¿ measure æ¹æ³å°±å®æäºæµéè¿ç¨ï¼å¨ measure æ¹æ³ä¸ä¼å»è°ç¨ View ç onMeasure æ¹æ³ï¼View ç±»éé¢å®ä¹äº onMeasure æ¹æ³çé»è®¤å®ç°:
å çä¸ä¸ getSuggestedMinimumWidth å getSuggestedMinimumHeight æ¹æ³çæºç ï¼
å¯ä»¥çå°ï¼ getMinimumWidth æ¹æ³è·åçæ¯ Drawable çåå§å®½åº¦ãå¦æåå¨åå§å®½åº¦ï¼å³æ»¡è¶³ intrinsicWidth > 0ï¼ï¼é£ä¹ç´æ¥è¿ååå§å®½åº¦å³å¯ï¼å¦æä¸åå¨åå§å®½åº¦ï¼å³ä¸æ»¡è¶³ intrinsicWidth > 0ï¼ï¼é£ä¹å°±è¿å 0ã
æ¥ççæéè¦ç getDefaultSize æ¹æ³ï¼
å¦æ specMode 为 MeasureSpec.UNSPECIFIED å³æªæå®æ¨¡å¼ï¼é£ä¹è¿åç±æ¹æ³åæ°ä¼ éè¿æ¥ç尺寸ä½ä¸º View çæµé宽度åé«åº¦ï¼
å¦æ specMode ä¸æ¯ MeasureSpec.UNSPECIFIED å³æ¯æ大模å¼æè 精确模å¼ï¼é£ä¹è¿åä» measureSpec ä¸ååºç specSize ä½ä¸º View æµéåç宽度åé«åº¦ã
çä¸ä¸åæçè¡¨æ ¼ï¼
å½ specMode 为 EXACTLY æè AT_MOST æ¶ï¼View çå¸å±åæ°ä¸º wrap_content æè match_parent æ¶ï¼ç» View ç specSize é½æ¯ parentSize ãè¿ä¼æ¯å»ºè®®çæå°å®½é«è¦å¤§ãè¿æ¯ä¸ç¬¦åæ们çé¢æçãå 为æä»¬ç» View 设置 wrap_content æ¯å¸æViewç大å°å好å¯ä»¥å 裹å®çå 容ã
å æ¤ï¼
å¦ææ¯ä¸ä¸ª ViewGroupï¼é¤äºå®æèªå·±ç measure è¿ç¨ä»¥å¤ï¼è¿ä¼éåå»è°ç¨ææåå ç´ ç measure æ¹æ³ï¼å个åå ç´ åéå½å»æ§è¡ measure è¿ç¨ã
ViewGroup 并没æéå View ç onMeasure æ¹æ³ï¼ä½æ¯å®æä¾äº measureChildrenãmeasureChildãmeasureChildWithMargins è¿å 个æ¹æ³ä¸é¨ç¨äºæµéåå ç´ ã
å¦ææ¯ View çè¯ï¼é£ä¹å¨å®ç layout æ¹æ³ä¸å°±ç¡®å®äºèªèº«çä½ç½®ï¼å ·ä½æ¥è¯´æ¯éè¿ setFrame æ¹æ³æ¥è®¾å® View çå个顶ç¹çä½ç½®ï¼å³åå§å mLeft ï¼ mRight ï¼ mTop ï¼ mBottom è¿å个å¼ï¼ï¼ layout è¿ç¨å°±ç»æäºã
å¦ææ¯ ViewGroup çè¯ï¼é£ä¹å¨å®ç layout æ¹æ³ä¸åªæ¯ç¡®å®äº ViewGroup èªèº«çä½ç½®ï¼è¦ç¡®å®åå ç´ çä½ç½®ï¼å°±éè¦éå onLayout æ¹æ³ï¼å¨ onLayout æ¹æ³ä¸ï¼ä¼è°ç¨åå ç´ ç layout æ¹æ³ï¼åå ç´ å¨å®ç layout æ¹æ³ä¸ç¡®å®èªå·±çä½ç½®ï¼è¿æ ·ä¸å±ä¸å±å°ä¼ éä¸å»å®ææ´ä¸ª View æ ç layout è¿ç¨ã
layout æ¹æ³çä½ç¨æ¯ç¡®å® View æ¬èº«çä½ç½®ï¼å³è®¾å® View çå个顶ç¹çä½ç½®ï¼è¿æ ·å°±ç¡®å®äº View å¨ç¶å®¹å¨ä¸çä½ç½®ï¼
onLayout æ¹æ³çä½ç¨æ¯ç¶å®¹å¨ç¡®å®åå ç´ çä½ç½®ï¼è¿ä¸ªæ¹æ³å¨ View ä¸æ¯ç©ºå®ç°ï¼å 为 View 没æåå ç´ äºï¼å¨ ViewGroup ä¸åè¿è¡æ½è±¡åï¼å®çåç±»å¿ é¡»å®ç°è¿ä¸ªæ¹æ³ã
1.ç»å¶èæ¯ï¼ background.draw(canvas); ï¼ï¼
2.ç»å¶èªå·±ï¼ onDraw ï¼ï¼
3.ç»å¶ childrenï¼ dispatchDraw(canvas) ï¼ï¼
4.ç»å¶è£ é¥°ï¼ onDrawScrollBars ï¼ã
dispatchDraw æ¹æ³çè°ç¨æ¯å¨ onDraw æ¹æ³ä¹åï¼ä¹å°±æ¯è¯´ï¼æ»æ¯å ç»å¶èªå·±åç»å¶å View ã
å¯¹äº View ç±»æ¥è¯´ï¼ dispatchDraw æ¹æ³æ¯ç©ºå®ç°çï¼å¯¹äº ViewGroup ç±»æ¥è¯´ï¼ dispatchDraw æ¹æ³æ¯æå ·ä½å®ç°çã
éè¿ dispatchDraw æ¥ä¼ éçã dispatchDraw ä¼éåè°ç¨åå ç´ ç draw æ¹æ³ï¼å¦æ¤ draw äºä»¶å°±ä¸å±ä¸å±ä¼ éäºä¸å»ãdispatchDraw å¨ View ç±»ä¸æ¯ç©ºå®ç°çï¼å¨ ViewGroup ç±»ä¸æ¯çæ£å®ç°çã
å¦æä¸ä¸ª View ä¸éè¦ç»å¶ä»»ä½å 容ï¼é£ä¹å°±è®¾ç½®è¿ä¸ªæ 记为 trueï¼ç³»ç»ä¼è¿è¡è¿ä¸æ¥çä¼åã
å½å建çèªå®ä¹æ§ä»¶ç»§æ¿äº ViewGroup 并ä¸ä¸å ·å¤ç»å¶åè½æ¶ï¼å°±å¯ä»¥å¼å¯è¿ä¸ªæ è®°ï¼ä¾¿äºç³»ç»è¿è¡åç»çä¼åï¼å½æç¡®ç¥éä¸ä¸ª ViewGroup éè¦éè¿ onDraw ç»å¶å 容æ¶ï¼éè¦å ³éè¿ä¸ªæ è®°ã
åèï¼ãAndroidå¼åèºæ¯æ¢ç´¢ã
View 绘制流程源码分析
在View的绘制流程中,ViewRootImpl的setView主流程涉及的关键步骤包括设置PFLAG_FORCE_LAYOUT和PFLAG_INVALIDATED。这一步骤在执行时,触发了View的重绘逻辑。
接下来,当View收到需要重绘的信号后,会执行invalidate方法。这个方法首先计算出需要重绘的dirty区域,然后从下向上,最终调用到ViewRootImpl的scheduleTraversals方法。这个过程中,脏区域的范围逐步扩大,直至整个View需要进行重绘。
在View的绘制流程中,PFLAG_FORCE_LAYOUT和PFLAG_INVALIDATED的使用至关重要。它们的设置触发了视图的重绘和布局过程,保证了UI在用户操作或其他事件触发时能够及时响应和更新。通过这种方式,系统确保了用户界面的实时性和交互性。
具体来说,当View收到布局或尺寸变化的信号时,会调用requestLayout方法,同时设置PFLAG_FORCE_LAYOUT标志。这个标志告诉系统,当前布局需要强制执行,即使布局尚未完成,也应立即进行更新。同时,invalidate方法的调用,会触发PFLAG_INVALIDATED标志的设置,表明视图需要重绘。
在ViewRootImpl中,scheduleTraversals方法是负责组织和执行视图层级中所有视图的重绘和布局的。它会根据脏区域和布局标志的设置,合理安排视图的更新顺序,确保系统的性能和用户体验。
总结整个流程,View的绘制和布局机制通过一系列的标志(如PFLAG_FORCE_LAYOUT和PFLAG_INVALIDATED)和方法(如requestLayout和invalidate)来协调和控制。这些机制使得系统能够高效地响应用户操作,实现流畅的UI交互。通过深入理解这些源码细节,开发者能够更好地优化UI性能,提高用户体验。