首页 文章 精选 留言 我的

精选列表

搜索[计费相关],共10000篇文章
优秀的个人博客,低调大师

Android面试,View绘制流程以及invalidate()等相关方法分析

整个View树的绘图流程是在ViewRoot.java类的performTraversals()函数展开的,该函数做的执行过程可简单概况为 根据之前设置的状态,判断是否需要重新计算视图大小(measure)、是否重新需要安置视图的位置(layout)、以及是否需要重绘 (draw),其框架过程如下: measure()过程 主要作用:为整个View树计算实际的大小,即设置实际的高(对应属性:mMeasuredHeight)和宽(对应属性:mMeasureWidth),每个View的控件的实际宽高都是由父视图和本身视图决定的。 具体的调用链如下: ViewRoot根对象地属性mView(其类型一般为ViewGroup类型)调用measure()方法去计算View树的大小,回调View/ViewGroup对象的onMeasure()方法,该方法实现的功能如下: 1、设置本View视图的最终大小,该功能的实现通过调用setMeasuredDimension()方法去设置实际的高(对应属性:mMeasuredHeight)和宽(对应属性:mMeasureWidth) ; 2 、如果该View对象是个ViewGroup类型,需要重写该onMeasure()方法,对其子视图进行遍历的measure()过程。 2.1 对每个子视图的measure()过程,是通过调用父类ViewGroup.java类里的measureChildWithMargins()方法去实现,该方法内部只是简单地调用了View对象的measure()方法。(由于measureChildWithMargins()方法只是一个过渡层更简单的做法是直接调用View对象的measure()方法)。 整个measure调用流程就是个树形的递归过程 measure函数原型为 View.java 该函数不能被重载 public final void measure(int widthMeasureSpec, int heightMeasureSpec) { //.... //回调onMeasure()方法 onMeasure(widthMeasureSpec, heightMeasureSpec); //more } 为了大家更好的理解,采用“二B程序员”的方式利用伪代码描述该measure流程 //回调View视图里的onMeasure过程 private void onMeasure(int height , int width){ //设置该view的实际宽(mMeasuredWidth)高(mMeasuredHeight) //1、该方法必须在onMeasure调用,否者报异常。 setMeasuredDimension(h , l) ; //2、如果该View是ViewGroup类型,则对它的每个子View进行measure()过程 int childCount = getChildCount() ; for(int i=0 ;i<childCount ;i++){ //2.1、获得每个子View对象引用 View child = getChildAt(i) ; //整个measure()过程就是个递归过程 //该方法只是一个过滤器,最后会调用measure()过程 ;或者 measureChild(child , h, i)方法都 measureChildWithMargins(child , h, i) ; //其实,对于我们自己写的应用来说,最好的办法是去掉框架里的该方法,直接调用view.measure(),如下: //child.measure(h, l) } } //该方法具体实现在ViewGroup.java里 。 protected void measureChildWithMargins(View v, int height , int width){ v.measure(h,l) } layout布局过程 主要作用 :为将整个根据子视图的大小以及布局参数将View树放到合适的位置上 具体的调用链如下: host.layout()开始View树的布局,继而回调给View/ViewGroup类中的layout()方法。具体流程如下 1 、layout方法会设置该View视图位于父视图的坐标轴,即mLeft,mTop,mLeft,mBottom(调用setFrame()函数去实现)接下来回调onLayout()方法(如果该View是ViewGroup对象,需要实现该方法,对每个子视图进行布局) ; 2、如果该View是个ViewGroup类型,需要遍历每个子视图chiildView,调用该子视图的layout()方法去设置它的坐标值。 layout函数原型为 ,位于View.java /* final 标识符 , 不能被重载 , 参数为每个视图位于父视图的坐标轴 * @param l Left position, relative to parent * @param t Top position, relative to parent * @param r Right position, relative to parent * @param b Bottom position, relative to parent */ public final void layout(int l, int t, int r, int b) { boolean changed = setFrame(l, t, r, b); //设置每个视图位于父视图的坐标轴 if (changed || (mPrivateFlags & LAYOUT_REQUIRED) == LAYOUT_REQUIRED) { if (ViewDebug.TRACE_HIERARCHY) { ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_LAYOUT); } onLayout(changed, l, t, r, b);//回调onLayout函数 ,设置每个子视图的布局 mPrivateFlags &= ~LAYOUT_REQUIRED; } mPrivateFlags &= ~FORCE_LAYOUT; } 同样地, 将上面layout调用流程,用伪代码描述如下: // layout()过程 ViewRoot.java // 发起layout()的"发号者"在ViewRoot.java里的performTraversals()方法, mView.layout() private void performTraversals(){ //... View mView ; mView.layout(left,top,right,bottom) ; //.... } //回调View视图里的onLayout过程 ,该方法只由ViewGroup类型实现 private void onLayout(int left , int top , right , bottom){ //如果该View不是ViewGroup类型 //调用setFrame()方法设置该控件的在父视图上的坐标轴 setFrame(l ,t , r ,b) ; //-------------------------- //如果该View是ViewGroup类型,则对它的每个子View进行layout()过程 int childCount = getChildCount() ; for(int i=0 ;i<childCount ;i++){ //2.1、获得每个子View对象引用 View child = getChildAt(i) ; //整个layout()过程就是个递归过程 child.layout(l, t, r, b) ; } } draw()绘图过程 由ViewRoot对象的performTraversals()方法调用draw()方法发起绘制该View树,值得注意的是每次发起绘图时,并不会重新绘制每个View树的视图,而只会重新绘制那些“需要重绘”的视图,View类内部变量包含了一个标志位DRAWN,当该视图需要重绘时,就会为该View添加该标志位。 调用流程 : mView.draw()开始绘制,draw()方法实现的功能如下: 1 、绘制该View的背景 2 、为显示渐变框做一些准备操作(大多数情况下,不需要改渐变框) 3、调用onDraw()方法绘制视图本身 (每个View都需要重载该方法,ViewGroup不需要实现该方法) 4、调用dispatchDraw ()方法绘制子视图(如果该View类型不为ViewGroup,即不包含子视图,不需要重载该方法)值得说明的是,ViewGroup类已经为我们重写了dispatchDraw ()的功能实现,应用程序一般不需要重写该方法,但可以重载父类函数实现具体的功能。 4.1 dispatchDraw()方法内部会遍历每个子视图,调用drawChild()去重新回调每个子视图的draw()方法(注意,这个 地方“需要重绘”的视图才会调用draw()方法)。值得说明的是,ViewGroup类已经为我们重写了dispatchDraw()的功能实现,应用程序一般不需要重写该方法,但可以重载父类函数实现具体的功能。 绘制滚动条 伪代码: // draw()过程 ViewRoot.java // 发起draw()的"发号者"在ViewRoot.java里的performTraversals()方法, 该方法会继续调用draw()方法开始绘图 private void draw(){ //... View mView ; mView.draw(canvas) ; //.... } //回调View视图里的onLayout过程 ,该方法只由ViewGroup类型实现 private void draw(Canvas canvas){ //该方法会做如下事情 //1 、绘制该View的背景 //2、为绘制渐变框做一些准备操作 //3、调用onDraw()方法绘制视图本身 //4、调用dispatchDraw()方法绘制每个子视图,dispatchDraw()已经在Android框架中实现了,在ViewGroup方法中。 // 应用程序程序一般不需要重写该方法,但可以捕获该方法的发生,做一些特别的事情。 //5、绘制渐变框 } //ViewGroup.java中的dispatchDraw()方法,应用程序一般不需要重写该方法 @Override protected void dispatchDraw(Canvas canvas) { // //其实现方法类似如下: int childCount = getChildCount() ; for(int i=0 ;i<childCount ;i++){ View child = getChildAt(i) ; //调用drawChild完成 drawChild(child,canvas) ; } } //ViewGroup.java中的dispatchDraw()方法,应用程序一般不需要重写该方法 protected void drawChild(View child,Canvas canvas) { // .... //简单的回调View对象的draw()方法,递归就这么产生了。 child.draw(canvas) ; //......... } invalidate()方法 说明:请求重绘View树,即draw()过程,假如视图发生大小没有变化就不会调用layout()过程,并且只绘制那些“需要重绘的”视图,即谁(View的话,只绘制该View ;ViewGroup,则绘制整个ViewGroup)请求invalidate()方法,就绘制该视图。 一般引起invalidate()操作的函数如下: 1、直接调用invalidate()方法,请求重新draw(),但只会绘制调用者本身。 2、setSelection()方法 :请求重新draw(),但只会绘制调用者本身。 3、setVisibility()方法 : 当View可视状态在INVISIBLE转换VISIBLE时,会间接调用invalidate()方法,继而绘制该View。 4 、setEnabled()方法 : 请求重新draw(),但不会重新绘制任何视图包括该调用者本身。 requestLayout()方法 会导致调用measure()过程 和 layout()过程 。 说明:只是对View树重新布局layout过程包括measure()和layout()过程,不会调用draw()过程,但不会重新绘制任何视图包括该调用者本身。 一般引起invalidate()操作的函数如下: 1、setVisibility()方法: 当View的可视状态在INVISIBLE/ VISIBLE 转换为GONE状态时,会间接调用requestLayout() 和invalidate方法。 同时,由于整个个View树大小发生了变化,会请求measure()过程以及draw()过程,同样地,只绘制需要“重新绘制”的视图。 requestFocus() 说明:请求View树的draw()过程,但只绘制“需要重绘”的视图。 View中的draw和onDraw的区别 1.大概扫一下源码就可以明白,draw()这个函数本身会做很多事情, * 1. Draw the background * 2. If necessary, save the canvas' layers to prepare for fading * 3. Draw view's content * 4. Draw children * 5. If necessary, draw the fading edges and restore layers * 6. Draw decorations (scrollbars for instance)在第三步的时候,它就会调用onDraw()方法,来绘制view的内容。也就是draw会调用onDraw。所以看需要,一般情况下,直接用onDraw绘制view的content就可以了,如果绘制多一点的内容,可以调用draw(),不过Android官方推荐用只用onDraw就可以了。“When implementing a view, do not override this method; instead, you should implement onDraw” 2.View组件的绘制会调用draw(Canvas canvas)方法,draw过程中主要是先画Drawable背景,对drawable调用setBounds(),然后是draw(Canvas c)方法.有点注意的是背景drawable的实际大小会影响view组件的大小,drawable的实际大小通过getIntrinsicWidth()和getIntrinsicHeight()获取,当背景比较大时view组件大小等于背景drawable的大小,画完背景后,draw过程会调用onDraw(Canvas canvas)方法,然后就是dispatchDraw(Canvas canvas)方法, dispatchDraw()主要是分发给子组件进行绘制,我们通常定制组件的时候重写的是onDraw()方法。值得注意的是ViewGroup容器组件的绘制,当它没有背景时直接调用的是dispatchDraw()方法, 而绕过了draw()方法,当它有背景的时候就调用draw()方法,而draw()方法里包含了dispatchDraw()方法的调用。因此要在ViewGroup上绘制东西的时候往往重写的是dispatchDraw()方法而不是onDraw()方法,或者自定制一个Drawable,重写它的draw(Canvas c)和 getIntrinsicWidth(),getIntrinsicHeight()方法,然后设为背景。 3.ondraw() 和dispatchdraw()的区别 绘制VIew本身的内容,通过调用View.onDraw(canvas)函数实现 绘制自己的孩子通过dispatchDraw(canvas)实现 本文转自我爱物联网博客园博客,原文链接:http://www.cnblogs.com/yydcdut/p/3960826.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android开发中Eclispe相关问题及相应解决(持续更新)

1.Eclipse项目中的Android Private Libraries没有自动生成。 一般而言,在Android开发中,项目中引用到的jar包会放到项目目录中的libs中,引入库会放到Android Dependencies中,对于放置于libs中的jar包,会自动置于项目中的Android Private Libraries下,如果没有自动生成,clean项目后一般在console下会发现有相应的错误提示,修正即可。如:项目中引用了不同的v4兼容包等会出现此类情况。 2.Eclipse中一直出现“Android SDK: resolving error markers”。 此类情况网上有诸多描述以及相应尝试性的解决方法,不久前本人即出现此类情况,尝试多种方案后未能解决。最终方法如下: 删除此文件,workspace/.metadata/.plugins/org.eclipse.e4.workbench/workbench.xmi,重启Eclipse即可。 3.Eclipse 中出现的错误警示:Element xxx is unknown. 在编写xml文件时,有时候当按下alt + / 本来想进行内容辅助时,有时候会总是出现Element xxx is unknown。原因在于此xml布局文件中写入了错误的标签/控件名称(eclipse是不会直接在不能识别的标签行前显示红叉的,xml文件本身也不会出现红叉),如xml中将FrameLayout写成了FragmentLayout等。 4.Eclipse中查看libs中的第三方jar包源码(如android-support-v4.jar) 在libs目录下建个和jar名字一样的 properties 文件,内容是src:源代码路径;doc:index.html的路径。 以v4 jar包为例 创建: libs/android-support-v4.jar.properties 打开,编辑: src = ..../android-sdk/extras/android/support/v4/src 保存后重启Eclipse。 5.升级SDK Manager后引起的Android Developer ToolKit版本不一致问题 在升级Android SDK Manager后,打开Android Adt Bundle出现错误提示:"This Android SDK requires Android Developer ToolKit version xxx or above", 原因是SDK Manager与Android Developer ToolKit版本不一致。 最后导致Android Adt Bundle无法使用。已有的项目出现无法生成R文件,同时也无法新建项目或导入外部项目。按照提示其实将Android Adt Bundle升级到相应本版即可。但是检查后发现Android Adt Bundle已是最新。 最后解决办法如下: 在SDK的Tools目录的lib中,知道打plugin.prop文件,将其中的plugin.version=xxx改为Android Adt Bundle当前的版本号xxx,然后重新启动Eclipse即可继续使用。 6.Using 1.7 requires compiling with Android 4.4 (KitKat); currently using 17 项目右键 >> java Compiler >> CompilerCompliance level 选择1.6。 7.Eclipse startup hang, “Android SDK: resolving error markers” 解决方案:删除文件/workspace/.metadata/.plugins/org.eclipse.e4.workbench/workbench.xmi,具体原因未知,若谁知道原因希望告知。 8.Eclpse Logcat中显示信息一小段时间后自动消失 解决方案:Logcat中的消息显示数量默认为5000条,可以适当增加此条目。Window >> Preferences >> Android >> LogCat >>Maximum number of logcat messages to buffer设置更大的数量 9./xxProject/gen already exists but is not a source folder. Convert to a source folder or rename it. 原因:直接导入外部项目时因classpath配置问题导致。 解决方法: 右键project >> Properties >> Java Build Path >> 选择Source >> Add Folder >> 选中gen文件夹 >> ok.. yes最后右键Fix Project Properties 并 clean下项目。 --------------------------------------------------------------------------------- 笔者水平有限,若有错漏,欢迎指正,如果转载以及CV操作,请务必注明出处,谢谢! 分类: Android 本文转自Windstep博客园博客,原文链接:http://www.cnblogs.com/lwbqqyumidi/p/4165872.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

方倍工作室微信相关代码下载方法

一、微信扫描关注微信公众账号 二、购买了《微信公众平台开发最佳实践》图书的读者回复“图书代码”,将显示图书配套代码的下载地址及链接 三、免费代码下载地址如下所示。 可下载的代码内容列表及关键字如下所示。 关键字 内容 需要积分 代码1219 微信全能基础消息类型 10 代码1218 微信全能自定义菜单 50 代码1217 微信-天气预报 20 代码1216 微信-聊天机器人 10 代码1215 微信-四六级查询 50 代码1214 微信-人脸识别 99 代码1213 微信模板消息 50 代码1212 微信调数据库示例 90 代码1211 仿朋友圈效果代码 10 代码1210 PHP开发视频教程 1 代码1209 小程序贪吃蛇 1 代码1202 小程序bootstrap字体 1 代码1201 小程序上传实例 1 代码1200 小程序-修改长连接 1 代码1199 微信小程序框架图 1 代码1198 微信小程序-淘宝 1 代码1197 微信小程序-外卖demo 1 代码1196 小程序图片演示demo 1 代码1195 小程序文章信息流 1 代码1194 微信小程序-闹钟应用 1 代码1193 仿拉勾招聘小程序 1 代码1192 微信小程序-妹纸图 1 代码1191 小程序美女图片 1 代码1190 小程序环球小镇商城 1 代码1189 微信小程序-和风天气 1 代码1188 小程序仿今日头条 1 代码1187 微信小程序-电商app 1 代码1186 小程序-底部导航demo 1 代码1185 小程序百思不得骑姐 1 代码1184 小程序api转promise 1 代码1183 小程序XY商城 1 代码1182 小程序-sCalc(计算器) 1 代码1181 小程序-menu(菜谱) 1 代码1180 小程序-weather(微天气) 1 代码1179 小程序-taobao(仿淘宝) 1 代码1178 小程序 Redux Todolist 1 代码1177 小程序-购物车demo 1 代码1176 微信-v2ex(社区v2ex) 1 代码1175 小程序-地图定位 1 代码1174 小程序--Todo List 1 代码1173 微信-JD(京东商城) 1 代码1172 微信-chat(聊天室demo) 1 代码1171 微信-集群监控 1 代码1170 小程序信息流-热门文章 1 代码1169 小程序-仿微信APP 1 代码1168 小程序-LOL战绩查询 1 代码1167 微信小程序-番茄时钟 1 代码1166 微信小程序-音乐播放器 1 代码1165 小程序websocket实例 1 代码1164 小程序快递源码 1 代码1163 微信小程序-灵犀账本 1 代码1162 小程序-知乎日报demo 1 代码1161 小程序 阅读demo 1 代码1160 微信小程序-音乐播放器 1 代码1159 小程序-艺术类网站 1 代码1158 小程序-访问斗鱼API 1 代码1157 学习用demo:电影时光 1 代码1156 小程序-新闻客户端 1 代码1155 微信小程序-商城类 1 代码1154 小程序-面包旅行 1 代码1153 微信小程序-BearDiary 1 代码1152 微信小程序-小熊日记 1 代码1151 2048小游戏小程序 1 代码1150 小程序-新闻客户端2 1 代码1149 模仿共享单车ofo小程序 1 代码1148 淘票票-小程序 1 代码1147 微票小程序 1 代码1146 小米计算器(小程序) 1 代码1145 小程序开发教程 0 代码1144 小程序-布局组件样式 1 代码1143 小程序-城市选择器 1 代码1142 小程序-圆形菜单 1 代码1141 小程序-天猫抽奖 1 代码1140 小程序-仿漂流瓶 1 代码1139 微信小程序-简易录音机 1 代码1138 小程序-douban-demo 1 代码1137 微信小程序-芒果tv 1 代码1136 小程序php+mysql 1 代码1135 小程序【组件&接口】 1 代码1134 小程序bootstrap字体 1 代码1133 小程序简单工具封装 1 代码1132 小程序-日期分月索引 1 代码1131 小程序-视频播放器 1 代码1130 腾讯地图定位小程序 1 代码1129 微信小程序-微票demo 1 代码1128 小程序-jQuery插件 1 代码1127 小程序仿豆瓣电影 1 代码1126 小程序图片瀑布流 1 代码1125 php后台post-小程序 1 代码1124 小程序代码自动补全 1 代码1123 小程序-音乐盒 1 代码1122 小程序开发布局工具 0 代码1121 小程序未来趋势与展望 0 代码1120 小程序支付代码 1 代码1119 小程序-小米商城 1 代码1118 移动商城-小程序 1 代码1117 小程序-在线社区 1 代码1116 微信小程序-ACE模版 1 代码1115 小程序-jq控制样式 0 代码1114 PHP 入门教程视频 1 代码1113 2048小游戏源代码 1 代码1112 微信小店API手册 1 代码1111 微信小店分类列表 1 代码1110 小猪PigCms v7.1加盟版 12 代码1109 微信开发最佳实践PDF 1

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册