为什么新四军骑兵团六分区没有团以上的

:转载时请以超链接形式标明文章原始出处和作者信息及本声明
android的Drawing Cache机制是文档中除了函数说明就几乎没提过的东西,网上各种文章和论坛讨论也是语焉不详、胡乱猜测。而这一机制却决定着android是否能真正打造高级用户体验。花了一整天研究源码后,下面我将讨论这个问题,对界面效率并不执着者请绕行。
1、Drawing Cache的作用
答:每个ViewGroup在DispatchDraw它的child时,会先getDrawingCache(位图)。如果DrawingCache存在,则直接使用cache来绘制,反之才调用child的draw方法。这样就牺牲了一定的内存,但减少了draw方法的开销。对于复杂的View,这一代价是相当值得的。
2、该使用Drawing Cache的哪些API?
答:实际只有两个API是我推荐使用的:setDrawingCacheEnabled和setDrawingCacheBackgroundColor。其实有很多方法来操纵甚至自己实现Drawing Cache机制,但这里节省时间,我只谈论个人认为的最佳实践。
setDrawingCacheEnabled是用于打开或关闭自动的cahce机制。这个自动是啥意思呢?就是绘制时总是会取得cache,如果cache不存在或者invalid了,那么就更新生成cache。
setDrawingCacheBackgroundColor在我们手中的用途是设置一个背景颜色缓存(必须是非0值),从而可以使用RGB_565的格式来生成cache,省略透明通道从而减少cache占用的空间和运算量。这一函数不一定符合你的需求,但在能够调用的时候尽量记得去调用。
我推荐的做法如下:
(1)对于每一个不是经常变化的view,使用setDrawingCacheEnabled(true),并尽量使用setDrawingCacheBackgroundColor。什么是经常变化的View呢?EditText因为光标闪烁就是个例子。任何经常定时调用invalid方法的view都不要去cache。
(2)要注意避免多余的cache,比如说一个ViewGroup中包含多个比较静态的child,那么你要么打开ViewGroup的cache,要么一一打开child的cache,将两者都打开是多余的。同时你要理解这两种做法的优劣区别:打开parent的cache,可以进一步减少parent绘制的代价(否则每次都要把child的cache重新绘制到一起并进行重叠计算);打开child的cache,可以在单个child发生改变时以更小的代价重建cache。但是最重要的区别在于对ViewGroup使用animation时,animation开始时必然要重建其绑定View的cache(会调用invalidate设置~DRAWING_CACHE_VALID标志位),这时候如果ViewGroup打开了cache则需要全部重建,如果child打开了cache那么只是parent额外进行一次绘制而已(每个child的cache不变)。因此,第二种做法是经常更加推荐的。
(3)对于setDrawingCacheEnabled(true)的view,在进行连续变化时,手动在变化开始前设置setDrawingCacheEnabled(false),在变化结束后重新设回true。
(4)尽量为每一个会调用Animation的ViewGroup(无论它平时是否进行cache)使用setDrawingCacheBackgroundColor。这会大大减少Animation时的cache开销。
按理说,依照上面四条法则,你就能最大限度地发挥Drawing cache的作用并抑制其副作用。但是,鉴于Android杯具的设计,如果你的工作中同时大量涉及Animation和Drawing Cache,你就必须有一些更透彻的认识才能避免不知不觉的错误。
3、Animation在drawing cache方面到底做了啥?
答:其实是ViewGroup为了保证Animation的流畅,设计了一个Animation Cache机制。这一机制就是将ViewGroup的所有child都强制建立Drawing Cache,在Animation结束后再释放cache。其中onAnimationStart方法负责建立cache,onAnimationEnd方法负责释放cache。
4、我们一般可能犯什么错?
答:看你是否会这样做:对于某个动画后要消失的View,使用AnimationListener的onAnimationEnd事件,在里面把要消失的View从parent中remove掉或者setVisibility(GONE)。
这样做的结果是,Animation结束时可能会卡一下,哪怕你同时clearAnimation后依然如此。
为什么呢?
因为无论你是remove掉child还是setVisibility(GONE),都会立刻触发destroyDrawingCache方法,也就是cache会被清除掉。
然后再从Trace Stack看一下onAnimationEnd的触发时机,是在draw方法中,是在即将绘制View之前(就是说无论你remove了还是GONE了,都阻止不了View的绘制)。于是,当要画Animation的最后一帧时,必须重新建立cache(前面被你destroy掉了),哪怕这一帧很有可能完全不用画(比如View已经移动到屏幕外了)。
如何解决?
貌似继承View.onAnimationEnd在里面清除掉无用的View可以避免重建cache,但是我没试,因为View.onAnimationEnd本身会引起另外一个问题(后面再说)。而除此之外我根本没看到android提供了其它接口可以解决上述问题,于是不得不发明了一个trick。
trick是这样:定义一个EmptyAnimation类,除了extends Animation外什么都不做。当你对A中的child B进行Animation,结束时想把B从A中remove掉或者GONE掉,你应该在B的Animation开始的同时,也同时启动A的一个EmptyAnimation(Duration与B的Animation一样),然后在这个EmptyAnimation的onAnimationEnd事件时,去执行将B移除的操作,并且记得对B进行clearAnimation。
实际上,如果你想让B在动画结束后消失,那么动画的最后一帧是不用显示的(最后一帧表达的就是:消失)。使用以上trick,就可以在B绘制最后一帧前,把B给清除掉,同时把动画也给关掉(避免调用View.onAnimationEnd),因此目前所知是最高效的办法。
5、更蛋疼的问题
为什么非要避开View.onAnimationEnd呢?因为ViewGroup.onAnimationEnd会将child的Drawing Cache机制统统关掉,完全不管这个child原来是否setDrawingCacheEnabled(true)。
所以非常悲催,对于任何Animation,你都必须记得在AnimationListener.onAnimationEnd的时候去clearAnimation,并且手动将一些你觉得不需要的cache给关掉(因为View.onAnimationStart将child的cache都打开了)。
引用地址:95 / 115 页
【Android开发网上的一些重要知识点[经验分享2。。】
认证徽章论坛徽章:1675
09:02 1505人阅读 (0) [url=]收藏[/url]
& & 在我们开发一些如通讯录、社交等应用或者应用添加新功能模块时,会考虑在对应的图标上加上未读信息的数量,或者是新功能提醒的图标,这样不占太大空间还能达到提示的目的.
& &之前在MMS分析部分,也有人问过我这种提醒的实现. 关于这种提醒的添加,我总结了下,有大概几种方法可以实现:
1. 在对应的布局放置TextView或者ImageView.
2. 用Canvas在原来Icon的bitmap基础上进行绘制
3. 利用开源项目ViewBadger进行添加,很方便,而且相对灵活
第一种方法只是调整下布局.这里不再讲述,直接看第二种方法:
认证徽章论坛徽章:1675
这里用到一个自定义的根据资源图标id获取图片的函数,很简单,代码如下:
/**&&& & * 根据id获取一个图片&&& & * @param res&&& & * @param resId&&& & * @return&&& & */& & & &private Bitmap getResIcon(Resources res,int resId){& & & & Drawable icon=res.getDrawable(resId);& & & & if(icon instanceof BitmapDrawable){& & & && &&&BitmapDrawable bd=(BitmapDrawable)& & & && &&&return bd.getBitmap();& & & & }else{& & & && &&&& & & & }& & & &}& &
获取到图标之后就要对这个图标进行处理了,要为该图标加上数量的覆盖
/**&& * 在给定的图片的右上角加上数量&& * @param icon 给定的图片&& */& & private Bitmap generatorContactCountIcon(Bitmap icon){& & & & //初始化画布& & & & int iconSize=(int)getResources().getDimension(android.R.dimen.app_icon_size);& & & & Log.d(TAG, &the icon size is &+iconSize);& & & & Bitmap contactIcon=Bitmap.createBitmap(iconSize, iconSize, Config.ARGB_8888);& & & & Canvas canvas=new Canvas(contactIcon);& & & && &&&& & //拷贝图片& & & & Paint iconPaint=new Paint();& & & & iconPaint.setDither(true);//防抖动& & & & iconPaint.setFilterBitmap(true);//用来对Bitmap进行滤波处理,这样,当你选择Drawable时,会有抗锯齿的效果& & & & Rect src=new Rect(0, 0, icon.getWidth(), icon.getHeight());& & & & Rect dst=new Rect(0, 0, iconSize, iconSize);& & & & canvas.drawBitmap(icon, src, dst, iconPaint);& & & && &&&& & & & //启用抗锯齿和使用设备的文本字距& & & & Paint countPaint=new Paint(Paint.ANTI_ALIAS_FLAG|Paint.DEV_KERN_TEXT_FLAG);& & & & countPaint.setColor(Color.RED);& & & & countPaint.setTextSize(20f);& & & & countPaint.setTypeface(Typeface.DEFAULT_BOLD);& & & & canvas.drawText(String.valueOf(count), iconSize-18, 25, countPaint);& & & & return contactI& & }& &
如有转载,请声明出处: 时之沙:
认证徽章论坛徽章:1675
10:04 790人阅读 (0) [url=]收藏[/url]
Android从3.0(API Level 11)开始,在绘制View的时候支持硬件加速,充分利用GPU的特性,使得绘制更加平滑,但是会多消耗一些内存。& && &开启或关闭硬件加速:
& && &由于硬件加速自身并非完美无缺,所以Android提供选项来打开或者关闭硬件加速,默认是关闭。可以在4个级别上打开或者关闭硬件加速:
& && &Application级别:&applicationandroid:hardwareAccelerated=&true& ...&
& && &Activity级别:&activity android:hardwareAccelerated=&false& ...&
& && &Window级别:
getWindow().setFlags( WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);&&
注意:目前为止,Android还不支持在Window级别关闭硬件加速。
& && &View级别:
myView.setLayerType(View.LAYER_TYPE_HARDWARE, null);&&
&&注意:目前为止,Android还:不支持在View级别开启硬件加速。
检测当前是否启用了硬件加速:
// 方法一&&// 此方法返回true,如果myView挂在一个开启了硬件加速的Window之下,&&// 也就是说,它在绘制的时候不一定使用了硬件加速,getDrawingCache&&myView.isHardwareAccelerated();&&& && && && && && && && &&&// 方法二&&// 返回true,如果canvas在绘制的时候启用了硬件加速&&// 尽量采用此方法来判断是否开启了硬件加速&&canvas.isHardwareAccelerated();&&
认证徽章论坛徽章:1675
理解View的绘制模型:
& && &1.没有硬件加速:invalidate the view hierarchy ------& draw the view hierarchy
& && &2.有硬件加速:invalidate the view hierarchy ------& record and update the display list ------& draw the display list
& && &硬件加速的限制:
& && &目前,Android对硬件加速的支持并非完美,有些绘制操作在开启硬件加速的情况下不能正常工作(具体的列表可以参考Android开发者文档)。
& && &不过Android可以保证内置的组件和应用支持硬件加速。因此,如果应用中只使用了标准UI组件,可以放心开启硬件加速。
& && &随着Android的版本升级,相信一段时间之后,硬件加速可以得到完美的支持。
& && &开启硬件加速之后的异常反应:
& && &1.某些UI元素没有显示:可能是没有调用invalidate
& && &2.某些UI元素没有更新:可能是没有调用invalidate
& && &3.绘制不正确:可能使用了不支持硬件加速的操作, 需要关闭硬件加速或者绕过该操作
& && &4.抛出异常:可能使用了不支持硬件加速的操作, 需要关闭硬件加速或者绕过该操作
认证徽章论坛徽章:1675
08:43 2130人阅读 (4) [url=]收藏[/url]
& &&&&&在很多天气或者新闻的应用中,我们都能看到一些字幕滚动的效果,最简单的实现为跑马灯效果,用系统提供的属性即可实现. 复杂一些的就需要自己去用自定义控件实现. 比如 让TextView 实现垂直滚动. 这里我要讲的是垂直滚动的字幕效果,并且内容并不仅为文字,还可以加入图片或者其他元素. 废话不多说,还是直接上效果图:
& && && && && && && && && && && &
认证徽章论坛徽章:1675
首先还是看一下核心的实现:目前我的做法是重写了ScrollView,对外提供几个重要的方法:isScrolled()方法判断当前是否为滚动状态setScrolled(boolean flag)设置滚动的开关setPeriod(long period)设置从开始滚动到结束的时间setSpeed(long speed)设置滚动的速度
下面说一些需要注意的地方:1.由于是定时操作,所以需要在Activity的对应生命周期进行处理: 当界面由不可见到可见时,设置setScrolled(true)打开滚动开关,由可见到不可见时,setScrolled(false)
关闭开关2. 可根据自己需要调用setPeriod(long period)和setSpeed(long speed)控制滚动的速度3. 由于是ScrollView实现的,中间放置的内容同ScrollView,不仅仅可以设置文字,还可以添加图片等其他元素,实现复杂的UI4. 图文混排, 目前这个DEMO我还没做细致处理. 最主要的部分就是文字的处理,需要考虑中英文,全角半角,字体大小,段落处理,计算对应的字符宽高等进行排版& & 图片等资源处理的部分就相对要简单,主要处理分辨率与计算宽高
& & 关于这些部分,之后我会慢慢做细致讲解.这个Demo是我临时写的,UI和图文混排包括具体的滚动部分处理都相对简单,大家可以在这个例子的基础上进行扩展,根据需求做出自己想要的效果:Demo下载地址:
下面是对应的代码:首先是自定义View:
认证徽章论坛徽章:1675
package com.tony.&&&&&&import android.content.C&&import android.os.H&&import android.util.AttributeS&&import android.util.L&&import android.view.MotionE&&import android.widget.ScrollV&&&&&&/**
* @author Tony
*/&&public class AutoScrollView extends ScrollView {&&& & private final Handler handler = new Handler();&&& &&&private long duration& &&&= 50;&&& &&&private boolean isScrolled& &=&&& & private int currentIndex = 0;&&& & private long period = 1000;&&& & private int&&currentY = -1;&&& & private double&&x;&&& & private double&&y;&&& & private int type = -1;&&& & /** & &&&* @param context & && &*/&&& &&&public AutoScrollView(Context context) {&&& && &&&this(context, null);&&& & }&&& && && &&&/** & && &* @param context & &&&* @param attrs & && &*/&&& & public AutoScrollView(Context context, AttributeSet attrs) {&&& && && &this(context, attrs, 0);&&& & }&&& && && & /** & && &* @param context & && & * @param attrs & && & * @param defStyle & && & */&&& & public AutoScrollView(Context context, AttributeSet attrs, int defStyle) {&&& && &&&super(context, attrs, defStyle);&&& &&&}&&& && && & public boolean onTouchEvent(MotionEvent event) {&&& && && &int Action = event.getAction();&&& && &&&switch (Action) {&&
认证徽章论坛徽章:1675
&&case MotionEvent.ACTION_DOWN:&&& && && && && & x=event.getX();&&& && && && && & y=event.getY();&&& && && && && &&&if (type == 0) {&&& && && && && && && &setScrolled(false);&&& && && && && && && && && && &&&}&&& && && && && &&&&&& && && && & case MotionEvent.ACTION_MOVE:&&& && && && && & double moveY = event.getY() -&&& && && && && &&&double moveX = event.getX() -&&& && && && && && & & && && && && & if ((moveY&20||moveY&-20) && (moveX & 50 || moveX & -50) && getParent() != null) {&&& && && && && && && &getParent().requestDisallowInterceptTouchEvent(true);& & & && && && && && && && && && && &}&&& && && && &&&& && && && && &&&&&& && && && &case MotionEvent.ACTION_UP:&&& && && && && &&&if (type == 0) {&&& && && && && && && &currentIndex = getScrollY();&&& && && && && && &&&setScrolled(true);&&& && && && && & }&&& && && && && &&&& && && && &default:&&& && && && && &&&& && &&&}&&& && && && && && &return super.onTouchEvent(event);& & & && & }&&& && && &@Override& & & && && &public boolean onInterceptTouchEvent(MotionEvent p_event)& & & && &&&{& & & && && &&&& && && && && & & && &&&}& & & & /** & && &* 判断当前是否为滚动状态 & && &*&&& && &* @return the isScrolled & && &*/&&& &&&public boolean isScrolled() {&&& && &&&return isS&&& &&&}&&& && && &&&/** & && &* 开启或者关闭自动滚动功能 & && &*&&& && &* @param isScrolled true为开启,false为关闭 & && &*/&&& &&&public void setScrolled(boolean isScrolled) {&&& && &&&this.isScrolled = isS&&& && &&&autoScroll();&&& &&&}&&& && &
认证徽章论坛徽章:1675
/** & && &* 获取当前滚动到结尾时的停顿时间,单位:毫秒 & && &*&&& && &* @return the period & && &*/&&& & public long getPeriod() {&&& && &&&&&& &&&}& && && && & /** & && &* 设置当前滚动到结尾时的停顿时间,单位:毫秒 & && &*&&& && &* @param period & && &*&&the period to set & &&&*/&&& & public void setPeriod(long period) {&&& && && &this.period =&&& &&&}&&& && && && &/** & && &* 获取当前的滚动速度,单位:毫秒,值越小,速度越快。 & && & *&&& && &* @return the speed & && &*/&&& &&&public long getSpeed() {&&& && &&&&&& &&&}&&& && && &&&/** & && &* 设置当前的滚动速度,单位:毫秒,值越小,速度越快。 & && &*&&& && &* @param speed & && &*& && && && &the duration to set & && &*/&&& &&&public void setSpeed(long speed) {&&& && && &this.duration =&&& &&&}&&& &&&public void setType(int type){&&& && && &this.type =&&& &&&}&&& &&&private void autoScroll() {&&& && && &handler.postDelayed(new Runnable() {&&& && && && &@Override&&& && && && & public void run() {&&& && && && && & boolean flag = isS&&& && && && && &&&if (flag) {&&& && && && && && &&&if (currentY == getScrollY()) {&&& && && && && && && && & try {&&& && && && && && && && && & Thread.sleep(period);&&& && && && && && && && &} catch (InterruptedException e) {&&& && && && && && && && && & e.printStackTrace();&&
认证徽章论坛徽章:1675
}&&& && && && && && && && &currentIndex = 0;&&& && && && && && && && & scrollTo(0, 0);&&& && && && && && && && &handler.postDelayed(this, period);&&& && && && && && &&&} else {&&& && && && && && && && &currentY = getScrollY();&&& && && && && && && && &handler.postDelayed(this, duration);&&& && && && && && && && &currentIndex++;&&& && && && && && && && &scrollTo(0, currentIndex * 1);&&& && && && && && &&&}&&& && && && && & } else {&&& && && && && && && && && && && && && &//currentIndex = 0;&&& && && && && && && && && && && && && &//scrollTo(0, 0);&&& && && && && & }&&& && && && &}&&& && &&&}, duration);&&& & }&&}&&
MainActivity:
package com.tony.&&&&import com.example.testautoscroll.R;&&&&import android.os.B&&import android.app.A&&&&/**
* link: blog.csdn.net/t12x3456
* @author Tony
*/&&public class MainActivity extends Activity {&&&&& & private AutoScrollView scrollV&&& && && && && & @Override&&& & protected void onCreate(Bundle savedInstanceState) {&&& && &&&super.onCreate(savedInstanceState);&&& && &&&setContentView(R.layout.activity_main);&&& && && && &&&scrollView = (AutoScrollView) findViewById(R.id.auto_scrollview);&&& & }&&&&& & @Override&&& & protected void onStart() {&&& && &&&// TODO Auto-generated method stub&&& && && & & && &&&if(!scrollView.isScrolled()){&&& && && && &scrollView.setScrolled(true);&&& && &&&}&&& && &&&super.onStart();&&& & }&&& && && & @Override&&& & protected void onStop() {&&& && &&&// TODO Auto-generated method stub&&& && && & & && &&&if(scrollView.isScrolled()){&&& && && && &scrollView.setScrolled(false);&&& && &&&}&&& && &&&super.onStop();&&& & }&&}&&
95 / 115 页
itpub.net All Right Reserved. 北京皓辰网域网络信息技术有限公司版权所有    
 北京市公安局海淀分局网监中心备案编号: 广播电视节目制作经营许可证:编号(京)字第1149号您所在位置: &
&nbsp&&nbsp&nbsp&&nbsp
ArcGISEngine开发-自定义图层类型.doc 144页
本文档一共被下载:
次 ,您可全文免费在线阅读后下载本文档。
下载提示
1.本站不保证该用户上传的文档完整性,不预览、不比对内容而直接下载产生的反悔问题本站不予受理。
2.该文档所得收入(下载+内容+预览三)归上传者、原创者。
3.登录后可充值,立即自动返金币,充值渠道很便利
需要金币:100 &&
ArcGISEngine开发-自定义图层类型
你可能关注的文档:
··········
··········
ArcGISEngine开发-自定义图层类型 3ArcGISEngine开发-取得ArcMap文档缩略图 3ArcSDE中直接取得图层几何类型 4ArcGISServer常见问题之一 5IFeatureLayer.DataSourceTypeProperty??[C#] 11IQueryFilter接口中的SubFileds属性的使用 12用程序实现从带高程的点数据到等高线的转换 13空间查询的实现 14创建带Z值的Feature 15在AO或者ENGINE中为SHAPEFILE添加SPATIALINDEX 19把一个图层ILayer数据COPY到三维Scenecontrol控件中(进行相关操作) 20vb+arcgisengine用raster生成等值线源码 22关于IIdentify定义时只能找到面而不能找到点和线的问题 31使用ArcGISEngine来实现地图的点击查询并闪烁 32空间查询的实现 34如何在同一图层中做缓冲选择 35怎么样使用Engine来保存Mxd文件(几种情况)? 36在ArcGISEngine开发时如何改变标注字段 37对shape文件添加字段 38在ArcGisEngine开发中如何在Toolbar控件上添加Combobox等其他控件 40自相交对象的处理 41在图中加入采集点 42创建拓扑类、投影等等。 43如何解决shapefile和coverage出现无法导入SDE数据库现象? 44怎么显示布局控件的标尺 45把shapefilepolygons转为polylines 45为什么不能编辑raster属性表或添加字段? 46使用ArcGIS将GTOPO30DEM数据转换到栅格数据 47旋转地图 47给geodatabase或shapefile定义一个投影 49ArcGISEngine中Undo、Redo命令的使用 50创建带Z值的Feature 50在Ao中如何通过查询获得ITable 53关于多个实体联合(union)的使用 54在Ao中如何通过查询获得ITable 55在VisualBasic中实现ICommand接口 56使用ArcObjects程序按照顶点来分割一条线 58使用AO加载RasterCatalog 61把不同层的几次的选择结果加到一个选择集中 61如何为ArcObjects扩展出&GroupRenderer&的效果来? 62在AO或者ENGINE中为SHAPEFILE添加SPATIALINDEX 68如何ArcObject的环境中用程序实现3D环境中的查询功能 69截取任意范围地图区域 71使用AO新增记录的3种方法 74如何在ArcEngine环境中的SceneControl中实现查询功能 75删除FeatureClass中满足一定条件的Feature问题及解决办法! 77创建孤立的要素类和数据集中的要素类 78SUMColorofvertexsymbolsinedit 80要素动态跟踪的算法 83同时闪烁满足条件的记录n次 86旋转地图 89转载-AO代码〔Display) 94在arcEngine中标注字段属性数据 99IfeatureSelection:SelectFeatures方法介绍 100AO基本函数集合(很多函数功能) 103AO画一个多边形 110AO画带节点的线 111AO计算Polygon的面积 112AO缓冲区查询 113AO画一个圆 114AO查询被选中的实体 116AO绘制带节点橡皮筋线条 117AO绘制橡皮筋多边形 123AO绘制缓冲区 126vb+ao鹰眼图代码 127如何利用ao编辑shape文件的某个属性的属性值 129MO作为B/S客户端控件的开发 130MO作为B/S服务器端的开发 133两点间画线 135创建PersonalGeodatabase 136ArcObject学习的重要工具--ObjectModelDiagrams 137ArcObject学习的重要工具--ObjectModelDiagrams(二) 139AO开发感想 141AO中的组件库(1) 143 ArcGISEngine开发-自定义图层类型用ArcGISEngine开发的一个特别就是面向接口编程,每组接口代表了对象在某个方面的特性,表现为一个方法、属性或事件。要定义自己的图层类型,实际上只需要实现ILayer接口就可以了。该接口的主要方法或属生包括: publicIEnvelopeAreaOfInterest{} publicvoidDraw( ????esriDrawPhaseDrawPhase, ????IDisplayDisplay, ????ITrackCanceltrackCancel ) publicvoidSp
正在加载中,请稍后...Android应用程序窗口View的draw过程
日期: 18:07:58
来源:ITeye
Android应用程序窗口View的draw过程
前面已经分析了Android应用程序窗口View的的测量,布局过程,接下来分析View的draw过程.
在frameworks/base/core/java/android/view/ViewRootImpl.java中的performTraversals()函数里调用 performLayout()函数进行布局之后,接着会调用 performDraw()函数进行绘制,现在就从这个函数开始分析
第一步:performDraw()
在frameworks/base/core/java/android/view/ViewRootImpl.java中
private void performDraw() {
draw(fullRedrawNeeded);
继续调用draw()函数
第二步:draw()
在frameworks/base/core/java/android/view/ViewRootImpl.java中
private void draw(boolean fullRedrawNeeded) {
if (!dirty.isEmpty() || mIsAnimating) {
if (attachInfo.mHardwareRenderer != null && attachInfo.mHardwareRenderer.isEnabled()) {
// Draw with hardware renderer.
mIsAnimating =
mHardwareYOffset =
mResizeAlpha = resizeA
mCurrentDirty.set(dirty);
mCurrentDirty.union(mPreviousDirty);
mPreviousDirty.set(dirty);
dirty.setEmpty();
if (attachInfo.mHardwareRenderer.draw(mView, attachInfo, this,
animating ? null : mCurrentDirty)) {
mPreviousDirty.set(0, 0, mWidth, mHeight);
} else if (!drawSoftware(surface, attachInfo, yoff, scalingRequired, dirty)) {
函数要选择是用硬件加速渲染UI,还是软件渲染.关于硬件加速渲染和软件渲染,我也不是很熟悉,所以没分析了.
这里假设是软件渲染,那么继续往下看
第三步:drawSoftware()
在frameworks/base/core/java/android/view/ViewRootImpl.java中
private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int yoff,
boolean scalingRequired, Rect dirty) {
// Draw with software renderer.
int left = dirty.
int top = dirty.
int right = dirty.
int bottom = dirty.
canvas = mSurface.lockCanvas(dirty);
if (left != dirty.left || top != dirty.top || right != dirty.right ||
bottom != dirty.bottom) {
attachInfo.mIgnoreDirtyState =
// TODO: Do this in native
canvas.setDensity(mDensity);
} catch (Surface.OutOfResourcesException e) {
} catch (IllegalArgumentException e) {
canvas.translate(0, -yoff);
if (mTranslator != null) {
mTranslator.translateCanvas(canvas);
canvas.setScreenDensity(scalingRequired ? mNoncompatDensity : 0);
attachInfo.mSetIgnoreDirtyState =
mView.draw(canvas);
drawAccessibilityFocusedDrawableIfNeeded(canvas);
} finally {
} finally {
函数首先获得了画布canvas,View内容绘制都是通过canvas来执行的,关于surface,canvas这里也没有过多的分析了.然后将canvas传给mView也就是DecorView开始整个View树的绘制了.
第四步:draw()
在frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java中
public void draw(Canvas canvas) {
super.draw(canvas);
if (mMenuBackground != null) {
mMenuBackground.draw(canvas);
先调用父类的draw()函数
第五步:draw()
在frameworks/base/core/java/android/widget/FrameLayout.java中
public void draw(Canvas canvas) {
super.draw(canvas);
if (mForeground != null) {
final Drawable foreground = mF
if (mForegroundBoundsChanged) {
mForegroundBoundsChanged =
final Rect selfBounds = mSelfB
final Rect overlayBounds = mOverlayB
final int w = mRight-mL
final int h = mBottom-mT
if (mForegroundInPadding) {
selfBounds.set(0, 0, w, h);
selfBounds.set(mPaddingLeft, mPaddingTop, w - mPaddingRight, h - mPaddingBottom);
final int layoutDirection = getLayoutDirection();
Gravity.apply(mForegroundGravity, foreground.getIntrinsicWidth(),
foreground.getIntrinsicHeight(), selfBounds, overlayBounds,
layoutDirection);
foreground.setBounds(overlayBounds);
foreground.draw(canvas);
继续调用父类的draw()
第六步:draw()
在frameworks/base/core/java/android/view/view.java中
public void draw(Canvas canvas) {
final int privateFlags = mPrivateF
final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
(mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
* Draw traversal performs several drawing steps which must be executed
* in the appropriate order:
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)
// Step 1, draw the background, if needed
if (!dirtyOpaque) {
final Drawable background = mB
if (background != null) {
final int scrollX = mScrollX;
final int scrollY = mScrollY;
if (mBackgroundSizeChanged) {
background.setBounds(0, 0,
mRight - mLeft, mBottom - mTop);
mBackgroundSizeChanged =
if ((scrollX | scrollY) == 0) {
background.draw(canvas);
canvas.translate(scrollX, scrollY);
background.draw(canvas);
canvas.translate(-scrollX, -scrollY);
// skip step 2 & 5 if possible (common case)
final int viewFlags = mViewF
boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
if (!verticalEdges && !horizontalEdges) {
// Step 3, draw the content
if (!dirtyOpaque) onDraw(canvas);
// Step 4, draw the children
dispatchDraw(canvas);
// Step 6, draw decorations (scrollbars)
onDrawScrollBars(canvas);
// we're done...
* Here we do the full fledged routine...
* (this is an uncommon case where speed matters less,
* this is why we repeat some of the tests that have been
* done above)
boolean drawTop =
boolean drawBottom =
boolean drawLeft =
boolean drawRight =
float topFadeStrength = 0.0f;
float bottomFadeStrength = 0.0f;
float leftFadeStrength = 0.0f;
float rightFadeStrength = 0.0f;
// Step 2, save the canvas' layers
int paddingLeft = mPaddingL
final boolean offsetRequired = isPaddingOffsetRequired();
if (offsetRequired) {
paddingLeft += getLeftPaddingOffset();
int left = mScrollX + paddingL
int right = left + mRight - mLeft - mPaddingRight - paddingL
int top = mScrollY + getFadeTop(offsetRequired);
int bottom = top + getFadeHeight(offsetRequired);
if (offsetRequired) {
right += getRightPaddingOffset();
bottom += getBottomPaddingOffset();
final ScrollabilityCache scrollabilityCache = mScrollC
final float fadeHeight = scrollabilityCache.fadingEdgeL
int length = (int) fadeH
// clip the fade length if top and bottom fades overlap
// overlapping fades produce odd-looking artifacts
if (verticalEdges && (top + length & bottom - length)) {
length = (bottom - top) / 2;
// also clip horizontal fades if necessary
if (horizontalEdges && (left + length & right - length)) {
length = (right - left) / 2;
if (verticalEdges) {
topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
drawTop = topFadeStrength * fadeHeight & 1.0f;
bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
drawBottom = bottomFadeStrength * fadeHeight & 1.0f;
if (horizontalEdges) {
leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
drawLeft = leftFadeStrength * fadeHeight & 1.0f;
rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
drawRight = rightFadeStrength * fadeHeight & 1.0f;
saveCount = canvas.getSaveCount();
int solidColor = getSolidColor();
if (solidColor == 0) {
final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
if (drawTop) {
canvas.saveLayer(left, top, right, top + length, null, flags);
if (drawBottom) {
canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
if (drawLeft) {
canvas.saveLayer(left, top, left + length, bottom, null, flags);
if (drawRight) {
canvas.saveLayer(right - length, top, right, bottom, null, flags);
scrollabilityCache.setFadeColor(solidColor);
// Step 3, draw the content
if (!dirtyOpaque) onDraw(canvas);
// Step 4, draw the children
dispatchDraw(canvas);
// Step 5, draw the fade effect and restore layers
final Paint p = scrollabilityCache.
final Matrix matrix = scrollabilityCache.
final Shader fade = scrollabilityCache.
if (drawTop) {
matrix.setScale(1, fadeHeight * topFadeStrength);
matrix.postTranslate(left, top);
fade.setLocalMatrix(matrix);
canvas.drawRect(left, top, right, top + length, p);
if (drawBottom) {
matrix.setScale(1, fadeHeight * bottomFadeStrength);
matrix.postRotate(180);
matrix.postTranslate(left, bottom);
fade.setLocalMatrix(matrix);
canvas.drawRect(left, bottom - length, right, bottom, p);
if (drawLeft) {
matrix.setScale(1, fadeHeight * leftFadeStrength);
matrix.postRotate(-90);
matrix.postTranslate(left, top);
fade.setLocalMatrix(matrix);
canvas.drawRect(left, top, left + length, bottom, p);
if (drawRight) {
matrix.setScale(1, fadeHeight * rightFadeStrength);
matrix.postRotate(90);
matrix.postTranslate(right, top);
fade.setLocalMatrix(matrix);
canvas.drawRect(right - length, top, right, bottom, p);
canvas.restoreToCount(saveCount);
// Step 6, draw decorations (scrollbars)
onDrawScrollBars(canvas);
这也是所有View的默认实现了.从函数看,绘制主要分几个步骤:
第一:首先画该View的背景
第二:画渐变框
第三:画该View本身的内容.比如textview就画自己text的内容,imagebutton就画所指的image...通过回调View的onDraw()函数开始绘制
第四:画自己的子View.当然前提是该View是ViewGroup类型.通过回调View的dispatchDraw()函数开始执行.dispatchDraw()函数在ViewGroup类里已经有默认实现了,函数里会分别调用子view的draw()函数去进行绘制,这样又是到上面的函数了.所以一般自定义的ViewGroup子类,不用去重写dispatchDraw()函数.只需要到自定义的子View的onDraw()函数绘制该view自己的内容.
第五:绘制scrollbar.
所以从上面来看,如果我们自定义View,简单的话只需要重写onDraw()函数来绘制自己的内容即可,其他的几个绘制View系统都默认执行,我们只需根据API设置相应的Drawable即可.
下面是View的onDraw()函数,默认什么都没做,不同View要绘制不同的内容.
protected void onDraw(Canvas canvas) {
下面是View的dispatchDraw()函数,默认什么都没做,因为dispatchDraw()是让ViewGroup类型的容器视图去安排它的子View进行绘制.
protected void dispatchDraw(Canvas canvas) {
下面是ViewGroup的dispatchDraw()函数,默认实现.
protected void dispatchDraw(Canvas canvas) {
final int count = mChildrenC
final View[] children = mC
int flags = mGroupF
if ((flags & FLAG_RUN_ANIMATION) != 0 && canAnimate()) {
final boolean cache = (mGroupFlags & FLAG_ANIMATION_CACHE) == FLAG_ANIMATION_CACHE;
final boolean buildCache = !isHardwareAccelerated();
for (int i = 0; i & i++) {
final View child = children[i];
if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
final LayoutParams params = child.getLayoutParams();
attachLayoutAnimationParameters(child, params, i, count);
bindLayoutAnimation(child);
if (cache) {
child.setDrawingCacheEnabled(true);
if (buildCache) {
child.buildDrawingCache(true);
final LayoutAnimationController controller = mLayoutAnimationC
if (controller.willOverlap()) {
mGroupFlags |= FLAG_OPTIMIZE_INVALIDATE;
controller.start();
mGroupFlags &= ~FLAG_RUN_ANIMATION;
mGroupFlags &= ~FLAG_ANIMATION_DONE;
if (cache) {
mGroupFlags |= FLAG_CHILDREN_DRAWN_WITH_CACHE;
if (mAnimationListener != null) {
mAnimationListener.onAnimationStart(controller.getAnimation());
int saveCount = 0;
final boolean clipToPadding = (flags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK;
if (clipToPadding) {
saveCount = canvas.save();
canvas.clipRect(mScrollX + mPaddingLeft, mScrollY + mPaddingTop,
mScrollX + mRight - mLeft - mPaddingRight,
mScrollY + mBottom - mTop - mPaddingBottom);
// We will draw our child's animation, let's reset the flag
mPrivateFlags &= ~PFLAG_DRAW_ANIMATION;
mGroupFlags &= ~FLAG_INVALIDATE_REQUIRED;
boolean more =
final long drawingTime = getDrawingTime();
if ((flags & FLAG_USE_CHILD_DRAWING_ORDER) == 0) {
for (int i = 0; i & i++) {
final View child = children[i];
if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) {
more |= drawChild(canvas, child, drawingTime);
for (int i = 0; i & i++) {
final View child = children[getChildDrawingOrder(count, i)];
if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) {
more |= drawChild(canvas, child, drawingTime);
// Draw any disappearing views that have animations
if (mDisappearingChildren != null) {
final ArrayList&View& disappearingChildren = mDisappearingC
final int disappearingCount = disappearingChildren.size() - 1;
// Go backwards -- we may delete as animations finish
for (int i = disappearingC i &= 0; i--) {
final View child = disappearingChildren.get(i);
more |= drawChild(canvas, child, drawingTime);
if (debugDraw()) {
onDebugDraw(canvas);
if (clipToPadding) {
canvas.restoreToCount(saveCount);
// mGroupFlags might have been updated by drawChild()
flags = mGroupF
if ((flags & FLAG_INVALIDATE_REQUIRED) == FLAG_INVALIDATE_REQUIRED) {
invalidate(true);
if ((flags & FLAG_ANIMATION_DONE) == 0 && (flags & FLAG_NOTIFY_ANIMATION_LISTENER) == 0 &&
mLayoutAnimationController.isDone() && !more) {
// We want to erase the drawing cache and notify the listener after the
// next frame is drawn because one extra invalidate() is caused by
// drawChild() after the animation is over
mGroupFlags |= FLAG_NOTIFY_ANIMATION_LISTENER;
final Runnable end = new Runnable() {
public void run() {
notifyAnimationListener();
post(end);
一般ViewGroup的子类,不用去重写该函数.该函数的作用是绘制该视图中包含的子视图,本质也就是给不同的子视图分配合适的画布(Canvas),至于子视图如何绘制,则又递归到View类的draw()函数中.
关于View绘制过程,源码也没什么了.过程还是挺简单的.
关于View的测量,布局,绘制过程就分析完了.
本页内容版权归属为原作者,如有侵犯您的权益,请通知我们删除。
介绍 本篇主要是对个人对LinphoneManger类的理解及对上面的注释,这是对linphone研究的一个开始. 会慢慢对linphone逐步分析, 随着时间的推进, 我会对linphone有进一步的了解,希望希望了解的同学能跟上我的脚步. 简介 LinphoneManager类是Linphone的主要操作管理类. 主要功能: 官方 /** * * Manager of the low level LibLinphone stuff. br / * Including: ul * li Starting
大概在2015年10月底,QQ空间发了一篇叫《安卓App热补丁动态修复技术介绍》的文章,文章中提到为了能让Class进行热修复,其中一个条件就是防止类被打上CLASS_ISPREVERIFIED标记,具体的做法便是让一个Dex引用另一个Dex(hack.apk)中的空类(为了让业务无感知,需要在编译时动态注入字节码),并且在应用程序Application类起来的时候要加载这个hack.apk。也就是说最多需要进行两次反射,即加载hack.apk的时候需要进行一次反射操作,将hack.apk加入到DexEl
先上几张效果图: 在加载多图片时,我们采用后进先出策略(即滑动到哪里就先加载哪里的图片),节省了内存的使用,也有了更好的用户体验。接着我们就先定义自己的ImageLoader。 ①首先我们先定义一些基本的变量 private static final int MSG_ADDTASK = 0x001 ; private LruCacheString, Bitmap mLruC // 图片缓存核心对象,LruCache是android提供的一个缓存工具类,其算法是最近最少使用算法 private E
文章大部分内容来自 Android开发全程实录 , 希望大家能看看原书 SharedPreferences sharepreferences是Android中最轻量级的数据存储. 原理相信很多人也很清楚, 这里简单再介绍以下. 系统提供了SharedPreferences这个类, 所有用这个类存储的内容都会放在 data/data/ package name /shares_prefs/… 目录下以xml文件的形式存储. xml文件中存储的都是键值对形式的内容. 一般可以存储java的简单类型(boole
回想一下,通常在Android开发中,我们最常接触到的是什么东西?显然除了Activity以外,就是各种形形色色的控件(即View)了。 与此同时,一个App诞生的起因,终究是根据不同需求完成与用户的各种交互。而所谓的交互,本质就是友好的响应用户的各种操作行为。 所以说,有很多时候,一个控件(View)出现在屏幕当中,通常不会是仅仅为了摆设,而是还要能够负责响应用户的操作。 以最基本的例子而言:现在某一个界面中有一个按钮(Button),而每当用户点击了该按钮,我们的程序将做出一定回应。 那么,如果我们还
在ViewController.h里面声明对象和属性,并加上代理UITextFieldDelegate: #import UIKit/UIKit.h @interface ViewController : UIViewController UITextFieldDelegate { //定义一个textField //文本输入区域 //例如:用户名,密码等需要输入文本文字的内容区域 //只能输入单行的文字,不能输入或者显示多行 UITextField * _textF} //定义属性 @prop
转载请标明出处: 一片枫叶的专栏 上一篇文章中我们讲解了android中的实用调试技巧。讲解了android中的原生Log API以及其使用方式,讲解了自定义日志API、使用方式和实现原理,讲解了通过gradle配置日志框架在正式环境中屏蔽日志信息等。最后我们还重点讲解了android studio中的断点调试技巧,主要包括:断点调试功能、日志断点、求值调试、异常断点、方法断点等。更多关于android中实用调试技巧的知识,可以参考我的: android产品研发(二十二)–android实用调试技巧 本文
这篇文章主要讲两点: 一、xxxhdpi、560dpi、xxhdpi、xhdpi、hdpi、mdpi、ldpi (还有tvdpi 主要用于电视,不去讨论) 在某个dpi缺失的情况下,如果去找寻。 二、values-xxhdpi- 这种以dpi加屏幕分辨率的适配方案是什么规律。 一、各种dpi之间的关系 【1】:由于网上以及存在一篇很好的文章,所以就不细讲了,这里给出链接地址:http://blog.csdn.net/a/article/details/
要逆向分析并修改一个Android应用,首先是对APK进行解包和打包,这一部分网上资料铺天盖地,不再赘述了。值得一提的一点就是,如果apktool无法解包或打包的话,可以尝试国人在apktool基础上开发的ShakaApktool,另外也可以使用 AndroidKiller这个工具,当然 AndroidKiller内部是使用ShakaApktool来进行解包打包。
关于如何解包和打包、反编译为JAVA代码、修改smali代码的资料很多,按部就班做起来也比较简单。dex2jar、JD-GUI获得了反
一. 列表内容 这段负责通话模块的开发,研究了一下telephony模块,网上参考了些资料加上自己的理解,总结了一下android6.0 MT 流程: Markdown和扩展Markdown简洁的语法 代码块高亮 图片链接和图片上传 LaTex 数学公式 UML序列图和流程图 离线写博客 导入导出Markdown文件 gdsfdsfs 丰富的快捷键 第一部分:RIL–GSMPhone Call状态变化 - 发出来电通知(frameworks\opt\telephony) 1. framwork/opt/t
Copyright (C)
ITfish.net

我要回帖

更多关于 新四军南通四分区 的文章

 

随机推荐