# UIDemo2 **Repository Path**: lzbgit/UIDemo2 ## Basic Information - **Project Name**: UIDemo2 - **Description**: 沉浸式、自定义view总结 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2018-07-24 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # UIDemo2 #### 项目介绍 沉浸式、自定义view总结 #### 一 沉浸式 1.获取状态栏高度 ```` private int getStatusHeight() { int height=-1; try { Class clazz=Class.forName("com.android.internal.R$dimen"); Object object=clazz.newInstance(); String heightStr=clazz.getField("status_bar_height").get(object).toString(); height = Integer.parseInt(heightStr); //dp--px height = getResources().getDimensionPixelSize(height); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } return height; } ```` 2.判断是否有导航栏 ```` @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1) private boolean haveNavgtion() { //屏幕的高度 真实物理的屏幕 Display display=getWindowManager().getDefaultDisplay(); DisplayMetrics displayMetrics=new DisplayMetrics(); display.getRealMetrics(displayMetrics); int heightDisplay=displayMetrics.heightPixels; //为了防止横屏 int widthDisplay=displayMetrics.widthPixels; DisplayMetrics contentDisplaymetrics=new DisplayMetrics(); display.getMetrics(contentDisplaymetrics); int contentDisplay=contentDisplaymetrics.heightPixels; int contentDisplayWidth=contentDisplaymetrics.widthPixels; //屏幕内容高度 显示内容的屏幕 int w=widthDisplay-contentDisplayWidth; //哪一方大于0 就有导航栏 int h=heightDisplay-contentDisplay; return w>0||h>0; } ```` 3.获取导航栏高度 ```` private int getNavigationHeight() { int height=-1; try { Class clazz=Class.forName("com.android.internal.R$dimen"); Object object=clazz.newInstance(); String heightStr=clazz.getField("navigation_bar_height").get(object).toString(); height = Integer.parseInt(heightStr); //dp--px height = getResources().getDimensionPixelSize(height); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } return height; } ```` 4 设置状态栏5.0以上 ```` if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { //状态栏 getWindow().setStatusBarColor(Color.GREEN); //虚拟键盘 getWindow().setNavigationBarColor(Color.GREEN); } ```` 4.4~5.0这样设置 ```` protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); //setContentView之前 全屏 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); } } /** * 5.0 4.4 * @param toolbar * @param styleColor */ public void setToolBarStyle(Toolbar toolbar, View bottomView, int styleColor) { // 5.0 4.4 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { if (toolbar != null) { // ViewGroup.LayoutParams layoutParams=topView.getLayoutParams(); // getResources().getDimension(android.R.dimen.s) int statusHeight=getStatusHeight(); Log.i("barry", " statusHeight " + statusHeight); // // layoutParams.height=statusHeight; // topView.setBackgroundColor(Color.GREEN); //第二种 toolbar.setPadding(0,toolbar.getPaddingTop()+statusHeight,0,0); //下面的导航栏 if (haveNavgtion()) { ViewGroup.LayoutParams layoutParams=bottomView.getLayoutParams(); layoutParams.height+=getNavigationHeight(); Log.i("barry", "getNavigationHeight " + getNavigationHeight()); bottomView.setLayoutParams(layoutParams); bottomView.setBackgroundColor(styleColor); } } }else if(Build.VERSION.SDK_INT >=Build.VERSION_CODES.LOLLIPOP) { }else { //没救了 } } ```` #### 二 自定义view 自定义控件开发总结: 1.熟悉大量的系统控件 2.ui绘制流程 3.事件分发处理 去根据层级找到对应的onToucheEvent onInterceptToucheEvent 4.学会渲染(性能) 5.关注第三方开源引擎 自定义控件分类 1.继承控件 1.1.继承系统原生控件在他的基础上进行自己业务的扩展,修改或者装饰系统控件 1.2.选用场景 1.2.1.系统当中是有控件能够支持50%-80%的产品功能选用继承控件进行拓展 1.2.2.在原有的基础上,添加特定的场景功能 1.View 2.ViewGroup 2.封装控件(自绘) 系统当中找不到相似逻辑的控件 定义:为了完成产品逻辑不规则,较为特殊的产品需求,需要自己绘制 注意点: 封装性/适配性 知识点要用到非常多: Paint Canvas Path 动画 3.组合控件 场景,业务复杂的情况下去要一个可扩展性能模块化组件,能达到可替换的灵活便捷 系统控件他遵循的 我们自己在继承系统控件的时候 得到的就是这个规则 但是我们自己开发自定义控件(布局-->会有子控件) 三个模式是我们自己给子控件的 测量使用技巧 自定义控件开发技巧: 1.onMesure 1.1.在继承view子类体系下如果腰改变自身的大小 只需要重写onMeasure测量好自己的宽高就可以了。 最终调用setMeasuredDimension()保存好自己的测量宽高。 int mode = MeasureSpec.getMode(widthMeasureSpec); int Size = MeasureSpec.getSize(widthMeasureSpec); int viewSize = 0; switch(mode){ case MeasureSpec.EXACTLY: viewSize = size;//当前view的尺寸就为父容器的尺寸 break; case MeasureSpec.AT_MOST: viewSize = Math.min(size, getContentSize());//当前view的尺寸就为内容尺寸和费容器尺寸当中的最小值。 break; case MeasureSpec.UNSPECIFIED: viewSize = getContentSize();//内容有多大,久设置多大尺寸。 break; default: break; } 系统提供了api:resolveSize 1.2.在继承ViewGroup体系下 不但需要重写onMeasure测量自己,还要测量子控件的规格大小。 可以直接使用ViewGroup的工具方法来测量里面的子控件,也可以自己来实现这一套子控件的测量(比如:RelativeLayout) //1.测量自己的尺寸 ViewGroup.onMeasure(); //1.1 为每一个child计算测量规格信息(MeasureSpec) ViewGroup.getChildMeasureSpec(); //1.2 将上面测量后的结果,传给每一个子View,子view测量自己的尺寸 child.measure(); //1.3 子View测量完,ViewGroup就可以拿到这个子View的测量后的尺寸了 child.getChildMeasuredSize();//child.getMeasuredWidth()和child.getMeasuredHeight() //1.4ViewGroup自己就可以根据自身的情况(Padding等等),来计算自己的尺寸 ViewGroup.calculateSelfSize(); //2.保存自己的尺寸 ViewGroup.setMeasuredDimension(size); ViewGroup中提供的Measure相关的api: measureChild measureChildren(所有) measureChildWithMargins getChildMeasureSpec #### DrawLayoutDemo示例 1. Drawable转为color ```` public void setColor(Drawable color){ ColorDrawable colorDrawable = (ColorDrawable) color; //背景转换成图片 paint.setColor(colorDrawable.getColor()); } ```` 2. xxxx 3. 效果图: ![](https://gitee.com/lzbgit/UIDemo2/raw/master/img/drawlayout.png) #### 参与贡献 1. Fork 本项目 2. 新建 Feat_xxx 分支 3. 提交代码 4. 新建 Pull Request #### 码云特技 1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md 2. 码云官方博客 [blog.gitee.com](https://blog.gitee.com) 3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解码云上的优秀开源项目 4. [GVP](https://gitee.com/gvp) 全称是码云最有价值开源项目,是码云综合评定出的优秀开源项目 5. 码云官方提供的使用手册 [http://git.mydoc.io/](http://git.mydoc.io/) 6. 码云封面人物是一档用来展示码云会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)