首页 文章 精选 留言 我的

精选列表

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

MetInfo 7.0.0 20200326 细节优化补丁,主要优化商城相关细节

MetInfo7.0.0 2020年3月26日系统升级更新: 修复:首页购物车里的商品图片显示空白的问题; 修复:导航栏购物车里商品删除后没反应的问题; 修复:商城编辑商品-批量编辑价格保存后无效的问题; 修复:前台语言列表-编辑插件语言-编辑应用参数时,搜索参数请求地址没有提交应用编号的问题; 同时,MetInfo为方便大家快速使用开源系统搭建企业网站,已陆续上线数十套免费模板数据,欢迎下载使用:https://www.metcms.cn/mb/ 修复方法: 方法一、商业版用户可以直接在网站后台使用“系统诊所”插件在线修复; 方法二、下载本次优化文件包,覆盖网站对应文件:update20200326.zip 你需要先将网站升级到7.0.0正式版后再使用此文件覆盖。 方法三、直接使用码云的开源包,同步更新文件:https://gitee.com/MetInfo_1/MetInfo MetInfo官网的安装包和升级包均已更新的到2020年3月26日的文件状态,在此时间之后安装和升级的用户无需执行以上操作。 MetInfo7.0.0历次补丁下载包: 20200114补丁:https://www.metinfo.cn/news/2719.html 20200205补丁:https://www.metinfo.cn/news/2726.html 20200210补丁:https://www.metinfo.cn/news/2728.html 20200318补丁:https://www.metinfo.cn/news/2733.html 米拓企业建站系统主要用于搭建企业网站,采用PHP+MySQL架构,支持SQLite数据库,全站内置了SEO搜索引擎优化机制,支持用户自定义语言(全球各种语言),支持可视化编辑管理,拥有企业网站常用的功能模块(简介模块、文章模块、产品模块、下载模块、图片模块、招聘模块、在线留言、反馈系统、在线交流、友情链接、网站地图、会员与权限管理、TAG标签),强大的SEO及伪静态设置功能,支持自定义网站颜色风格,支持按栏目自定义Banner图和数据调用,支持手机底部菜单,支持用户自主二次开发,商业模板支持在线升级。系统内置标准的应用插件开发接口,拥有丰富的免费插件和收费插件,如短信接口、robots文件修改、模板制作助手、小程序(微信、百度、支付宝、字节跳动[今日头条、抖音]、360、QQ)、支付接口、商城模块、系统诊所、图片加速、网站广告插件等。无论你是技术大咖还是建站小白,都可以使用MetInfo快速搭建一个功能齐全的响应式专业网站。

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

[php入门] 3、WAMP中的集成MySQL相关基础操作

前言:本文以小白视角了解WAMP集成开发环境中的MYSQL,涉及的面广而浅,算是导读性质。 1、启动运行熟悉WAMP中的MySQL 先有库、再有表、数据最终以记录的形式插入表中。其中对数据进行操作使用SQL语句,SQL是结构化的查询语言。 在wamp中已经内置了MySQL数据库,可以通过如下操作进行启动MySQL服务(每次使用数据库时,必须启动MySQL服务器) 2、控制台操作数据库简介 我们可以通过控制台来连接、操作数据库:(其中默认没有密码,直接回车即可以) 在console中常用的有show、create、drop等命令: mysql> show databases; 3、phpMyAdmin可视化操作数据库简介 控制台操作起来不太方便,这里可以用phpMyAdmin可视化MySQL数据库操作图形界面(wamp中) 4、建表及表操作的基础知识 4.1、建表: 创建一张表时要设置名称、引擎、编码和表中的字段信息。 建表时需要指定引擎,不同引擎提供不同的功能; 字段用来指明这张表里用了哪些类型的数据:int、varchar、data(日期)、text(文本,最大65535) 4.2、表操作: insert into 表名(字段列表) value(值列表) select * from 表名 select * from 表名 where delete from 表名 where 条件 update 表名 set 字段1=值1,字段2=值2..... where 条件 5、PHP操作MySQL 5.1、开启MySQL扩展: 总共有3种扩展:①MySQL扩展(老的,基本不用了);②MySQLi扩展; ③PDO扩展; 5.2、以使用MySQL扩展为例,用PHP操作MySQL 其实就是函数调用,当开启扩展之后,就可以调用扩展提供的相应函数对数据库进行连接、读写删等操作。默认情况下用户名为root,密码为空 下面几个数MySQL扩展开放的几个重要的接口: mysql_connect(mysql服务器ip,用户名,密码) mysql_select_db mysql_query mysql_fech_array 1 <?php 2 $conn = mysql_connect("localhost","root",""); 3 mysql_select_db("mysql",$conn); 4 $results = mysql_query("set names utf-8");//设置编码 5 $results = mysql_query("select * from user"); 6 $row = mysql_fetch_array($results);//每次调用显示一条,因此需要循环调用 7 var_dump($row); 8 ?> 本文转自beautifulzzzz博客园博客,原文链接: http://www.cnblogs.com/zjutlitao/p/5648590.html ,如需转载请自行联系原作者

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

K8S集群存储服务相关日志获取指南

自动日志获取 1. 在一台可以通过kubectl访问集群的节点上下载脚本: curl -o diagnose_storage.sh http://aliacs-k8s-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/public/diagnose/diagnose_storage.sh 2. 执行脚本: sh diagnose_storage.sh logs podID nameSpaceName 其中:podID为出问题的pod ID;nameSpaceName为出问题pod的名词空间; 3. 查看日志: 在当前目录下面会生成日志文件: 一个logs目录和对其打包的文件;logs下面包括:flexvolume、disk provisioner、kubelet的日志。 Flexvolume日志(master1上执行

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

C#字符串string以及相关内置函数

C#字符串string函数 本文提供全流程,中文翻译。 Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 —— 高分辨率用户请根据需求调整网页缩放比例) Chinar —— 心分享、心创新!助力快速理解 C# string 字符串内置函数用法为新手节省宝贵的时间,避免采坑! 1 Info —— Main 支持 May Be —— 搞开发,总有一天要做的事! 全文高清图片,点击即可放大观看 (很多人竟然不知道) 1 Info —— Main class Program { static void Main(string[] args) { /* CompareTo() 函数在字符串相等的时候,返回值为:0 当两个字符 ,比较的字符 str 中出现一个 与下边不同的字符时,str的字母排序靠前,返回-1 否则返回1*/ string str = "a"; int res = str.CompareTo("b"); Console.WriteLine(res); str = "b"; res = str.CompareTo("a"); Console.WriteLine(res); str = "b"; res = str.CompareTo("a"); Console.WriteLine(res); Console.WriteLine("_________________________________比较________________________________________"); str = "www.unity.kim"; string newReplace = str.Replace('.', '-'); //替换字符串中的某个字符/字符串:Replace(指定字符,替换字符) Console.WriteLine(newReplace); Console.WriteLine("___________________________________替换______________________________________"); string[] strings = str.Split('.'); //字符串拆分,用一个字符拆分现有字符串 foreach (var s in strings) { Console.WriteLine(s); } Console.WriteLine("__________________________________拆分_______________________________________"); string newSubstring = str.Substring(4, 5); //从str 中的第四个字符开始截取,然后截取长度为5的字符 Console.WriteLine(newSubstring); newSubstring = str.Substring(4); //如果不给长度,则直接到末端 Console.WriteLine(newSubstring); Console.WriteLine("__________________________________从某个位置截取字符串_______________________________________"); string strUp = str.ToUpper(); //字符串转大写 Console.WriteLine(strUp); var strLow = str.ToLower(); //字符串转小写 Console.WriteLine(strLow); Console.WriteLine("__________________________________大小写_______________________________________"); str = " www.unity.kim "; string newTrim = str.Trim(); //删除 字符串收尾空白处 Console.WriteLine(str); Console.WriteLine(newTrim); Console.WriteLine("__________________________________去首位空格_______________________________________"); int num = str.IndexOf("unidty"); //可以用来判断是否包含一个子字符串,不包含返回-1,包含返回第一个字符在哪个位置的下标 Console.WriteLine(num); Console.ReadLine(); } } 支持 May Be —— 搞开发,总有一天要做的事! 拥有自己的服务器,无需再找攻略! Chinar 提供一站式教程,闭眼式创建!为新手节省宝贵时间,避免采坑! 先点击领取 —— 阿里全产品优惠券 (享受最低优惠) 1 —— 云服务器超全购买流程 (新手必备!) 2 —— 阿里ECS云服务器自定义配置 - 购买教程(新手必备!) 3—— Windows 服务器配置、运行、建站一条龙 ! 4 —— Linux 服务器配置、运行、建站一条龙 ! Chinar END 本博客为非营利性个人原创,除部分有明确署名的作品外,所刊登的所有作品的著作权均为本人所拥有,本人保留所有法定权利。违者必究 对于需要复制、转载、链接和传播博客文章或内容的,请及时和本博主进行联系,留言,Email: ichinar@icloud.com 对于经本博主明确授权和许可使用文章及内容的,使用时请注明文章或内容出处并注明网址、

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

Windows 2012 R2 FSMO角色相关小记录

科普: 森林级别(即一个森林只存在一台DC有这个角色): (1)、Schema Master 架构主机 (2)、Domain Naming Master 域命名主机 域级别(即一个域里面只存一台DC有这个角色): (1)、PDC Emulator PDC (2)、RID Master RID 池管理器 (3)、Infrastructure Master 结构主机(基础架构主控) 查询FSMO角色所在主机 Powershell > Get-ADForest | Format-List SchemaMaster,DomainNamingMaster Get-ADDomain | Format-List InfrastructureMaster,PDCEmulator,RIDMaster CMD命令行 > netdom query fsmo 本文转自 ljpwinxp 51CTO博客,原文链接:http://blog.51cto.com/191226139/1630904

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

[转]Android笔记:OnGestureListener相关、滑动屏幕效果GestureDetector、OnGestureListen...

一个activity中new一个GestureDetector之后,里面会实现一下的方法: onSingleTapUp onShowPress onScroll onLongPress onFling onDown ============说一下这些方法都是由那些MotionEvent触发的============================= 1、onSingleTapUp、onSingleTapConfirmed 用户(轻触触摸屏后)松开,由一个1个MotionEvent ACTION_UP触发 这个事件执行的顺序是onDown-》onShowPress-》onSingleTapUp 区别: 点击一下非常快的(不滑动)Touchup:onDown->onSingleTapUp->onSingleTapConfirmed点击一下稍微慢点的(不滑 动)Touchup:onDown->onShowPress->onSingleTapUp->onSingleTapConfirmed 2、onShowPress 用户轻触触摸屏,尚未松开或拖动,由一个1个MotionEvent ACTION_DOWN触发 它与onDown()的区别,强调的是没有松开或者拖动的状态 3、onDown 而onDown也是由一个MotionEventACTION_DOWN触发的,但是他没有任何限制,也就是说当用户点击的时候,首先MotionEventACTION_DOWN,onDown就会执行,如果在按下的瞬间没有松开或者是拖动的时候onShowPress就会执行,如果是按下的时间超过瞬间(这块我也不太清楚瞬间的时间差是多少,一般情况下都会执行onShowPress),拖动了,就不执行onShowPress。 4、onLongPress 用户长按触摸屏,由多个MotionEvent ACTION_DOWN触发 这个事件执行的顺序是onDown-》onShowPress-》onLongPress 5、onFling 用户按下触摸屏、快速移动后松开,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE,1个ACTION_UP触发 6、onScroll Touch了 滑动时触发。 ============================另外需要说的一点======================================== 如果你是在一个大的view上装载了一个一个的小view,如果你想让大的view有界面动态效果(比如左右向下滑动),那么你必须将这些小的view加入setOnTouchListener,然后你可以在OnTouchListener方法中加入如下方法将你的MotionEvent事件传到gestureDetector中。如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 switch (event.getAction()) { case MotionEvent.ACTION_MOVE: { gestureDetector.onTouchEvent(event); break ; } // inner case MOVE case MotionEvent.ACTION_UP: { v.setPressed( false ); Log.i( "cat" , "CCCCCCCCCCCCCCCC" ); gestureDetector.onTouchEvent(event); // TODO animation return true ; } // inner case UP case MotionEvent.ACTION_DOWN: { v.setPressed( true ); gestureDetector.onTouchEvent(event); break ; } // inner case UP } // inner switch ==============滑动屏幕效果GestureDetector、OnGestureListener、ViewFlipper============================ 通过GestureDetector、OnGestureListener实现滑屏事件。ViewFlipper是继承至FrameLayout的,所以它是一个Layout里面可以放置多个View。示例中第一页仅放了一个按钮BUTTON,向下滑屏时,每页都只放了一个TEXTVIEW。 页面: 1 2 3 4 5 6 7 8 9 10 <?xml version= "1.0" encoding= "utf-8" ?> <LinearLayout xmlns:Android= "http://schemas.android.com/apk/res/android" android:orientation= "vertical" android:layout_width= "fill_parent" android:layout_height= "fill_parent" > <ViewFlipper android:id= "@+id/ViewFlipper01" android:layout_width= "fill_parent" android:layout_height= "fill_parent" > </ViewFlipper> </LinearLayout> 代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 public class Flip extends Activityimplements OnGestureListener { private GestureDetector detector; private ViewFlipper flipper; @Override public void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.main); flipper = (ViewFlipper) this .findViewById(R.id.ViewFlipper01); flipper.addView(addButtonByText( "按钮" ),newLayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT)); detector = new GestureDetector( this ); } public View addButtonByText(String text){ Button btn = new Button( this ); btn.setText(text); return btn; } public View addTextByText(String text){ TextView tv = new TextView( this ); tv.setText(text); tv.setGravity( 1 ); return tv; } @Override public boolean onTouchEvent(MotionEvent event) { Log.i( "Fling" , "Activity onTouchEvent!" ); return this .detector.onTouchEvent(event); } @Override public boolean onDown(MotionEvent e) { // TODO Auto-generated method stub return false ; } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, floatvelocityX, float velocityY) { // TODO Auto-generated method stub Log.i( "Fling" , "Fling Happened!" ); if (e1.getX() - e2.getX() > 120 ) { this .flipper.setInAnimation(AnimationUtils.loadAnimation( this ,R.anim.push_left_in)); this .flipper.setOutAnimation(AnimationUtils.loadAnimation( this ,R.anim.push_left_out)); this .flipper.addView(addTextByText( "文本框" ),newLayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT)); this .flipper.showNext(); return true ; } else if (e1.getX() - e2.getX() < - 120 ) { this .flipper.setInAnimation(AnimationUtils.loadAnimation( this ,R.anim.push_right_in)); this .flipper.setOutAnimation(AnimationUtils.loadAnimation( this ,R.anim.push_right_out)); this .flipper.showPrevious(); return true ; } return true ; } @Override public void onLongPress(MotionEvent e) { // TODO Auto-generated method stub } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, floatdistanceX, float distanceY) { // TODO Auto-generated method stub return false ; } @Override public void onShowPress(MotionEvent e) { // TODO Auto-generated method stub } @Override public boolean onSingleTapUp(MotionEvent e) { // TODO Auto-generated method stub return false ; } } 动画源文件:(在res目录下,创建一个anim文件夹,把下面的文件都放在这里) push_left_in.xml 1 2 3 4 5 6 7 <?xml version= "1.0" encoding= "utf-8" ?> <set xmlns:android= "http://schemas.android.com/apk/res/android" > <translate android:fromXDelta= "100%p" android:toXDelta= "0" android:duration= "500" /> <alpha android:fromAlpha= "0.1" android:toAlpha= "1.0" android:duration= "500" /> </set> push_left_out.xml: 1 2 3 4 5 6 7 <?xml version= "1.0" encoding= "utf-8" ?> <set xmlns:android= "http://schemas.android.com/apk/res/android" > <translate android:fromXDelta= "0" android:toXDelta= "-100%p" android:duration= "500" /> <alpha android:fromAlpha= "1.0" android:toAlpha= "0.1" android:duration= "500" /> </set> push_right_in.xml: 1 2 3 4 5 6 7 <?xml version= "1.0" encoding= "utf-8" ?> <set xmlns:android= "http://schemas.android.com/apk/res/android" > <translate android:fromXDelta= "-100%p" android:toXDelta= "0" android:duration= "500" /> <alpha android:fromAlpha= "0.1" android:toAlpha= "1.0" android:duration= "500" /> </set> push_right_out.xml: 1 2 3 4 5 6 7 <?xml version= "1.0" encoding= "utf-8" ?> <set xmlns:android= "http://schemas.android.com/apk/res/android" > <translate android:fromXDelta= "0" android:toXDelta= "100%p" android:duration= "500" /> <alpha android:fromAlpha= "1.0" android:toAlpha= "0.1" android:duration= "500" /> </set> 本文转自 glblong 51CTO博客,原文链接:http://blog.51cto.com/glblong/1290645,如需转载请自行联系原作者

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

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,如需转载请自行联系原作者

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

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

Nacos

Nacos

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

Sublime Text

Sublime Text

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

用户登录
用户注册