【slidyy源码】【冒泡排序的核心源码】【梦幻西游笑傲版源码】android ui效果源码_安卓ui源码

时间:2024-11-23 06:54:12 分类:android网易新闻客户端源码 来源:猎手指标源码

1.Android UI绘制之View绘制的工作原理
2.设计师设计 Android UI 应该用多大分辨率进行设计
3.【Android】UI(二)Android常用的基础布局容器
4.Android UI布局
5.车机开发Android SystemUI 架构音量控制详解

android ui效果源码_安卓ui源码

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开发艺术探索》

设计师设计 Android UI 应该用多大分辨率进行设计

       1. 程序启动图标:

       ldpi ( dpi)

       å°å±

       mdpi ( dpi)

       ä¸­å±

       hdpi ( dpi)

       å¤§å±

       xhdpi ( dpi)

       ç‰¹å¤§å±

        x px

        x px

        x px

        x px

       2.底部菜单图标

       1. 大屏:

       1. 完整图片(红色): x px

       2. 图标(蓝色): x px

       3. 图标外边框(粉色): x px

       1. 中屏:

       1. 完整图片: x px

       2. 图标: x px

       3. 图标外边框: x px

       1. 小屏:

       1. 完整图片: x px

       2. 图标: x px

       3. 图标外边框: x px

       3. 弹出对话框顶部图标

       Low density screen (ldpi)

       å°å±

       Medium density screen (mdpi)

       ä¸­å±

       High density screen (hdpi)

       å¤§å±

        x px

        x px

        x px

       4. 长列表内部列表项图标

       Low density screen (ldpi)

       å°å±

       Medium density screen (mdpi)

       ä¸­å±

       High density screen (hdpi)

       å¤§å±

        x px

        x px

        x px

       5. 底部或顶部tab标签图标

       1. 大屏 (hdpi) screens:

       1. 完整图片(红色): x px

       2. 图标(蓝色): x px

       1. 中屏 (mdpi) screens:

       1. 完整图片: x px

       2. 图标: x px

       1. 小屏(ldpi) screens:

       1. 完整图片: x px

       2. 图标: x px

       6. 底部状态栏图标

       ldpi ( dpi)

       å°å±

       mdpi ( dpi)

       ä¸­å±

       hdpi ( dpi)

       å¤§å±

       xhdpi ( dpi)

       ç‰¹å¤§å±

        x px

        x px

        x px

        x px

【Android】UI(二)Android常用的基础布局容器

        Android 的UI 可以分为两类,一类叫做ViewGroup容器,一类叫做View视图

        View视图:(TextView,Button,ImageView)都是常用常见的视图.

        ViewGroup容器:内部可以承载、放置、添加View视图

        线性布局就是从左到右或从上到下按顺序排列的一种布局。下面讲一讲LinearLayout的基础属性。

        相对布局在摆放子视图位置时,按照指定的参考系来摆放子视图的位置,默认以屏幕左上角(0,0)位置作为参考系摆放位置

        使用layout_below使得后面一个组件位于前面一个组件的下方

        配合layout_toRightOf使得后面一个组件位于前面一个组件的右方

        组件的默认位置都是左上角,组件之间可以重叠。像千层饼一样,一层压着一层 可以设置上下左右的对齐、水平垂直居中、设置方式与线性布局相似

        参考: Android从零入门到实战(Kotlin版)

Android UI布局

       æˆ‘有类似的布局

       <LinearLayout

                           android:id="@+id/lyApp"

                           android:layout_width="match_parent"

                           android:layout_height="0dp"

                           android:layout_marginLeft="5dp"

                           android:layout_marginTop="dp"

                           android:layout_weight="1"

                           android:background="@drawable/app"

                           android:gravity="center_horizontal" >

                           <LinearLayout

                               android:layout_width="wrap_content"

                               android:layout_height="match_parent"

                               android:gravity="left"

                               android:orientation="vertical" >

                               <TextView

                                   android:id="@+id/mtxt"

                                   android:layout_width="wrap_content"

                                   android:layout_height="0dp"

                                   android:layout_weight="1"

                                   android:gravity="center"

                                   android:text="我的图像"

                                   android:textColor="#FFFFFF"

                                   android:textSize="dp" />

                               <TextView

                                   android:id="@+id/mtxt"

                                   android:layout_width="wrap_content"

                                   android:layout_height="0dp"

                                   android:layout_weight="1"

                                   android:gravity="right"

                                   android:text="点击进入专业影像处理模块"

                                   android:textColor="#FFFFFF" />

                           </LinearLayout>

                       </LinearLayout>

车机开发Android SystemUI 架构音量控制详解

       在Android系统中,SystemUI是码安码一个特殊的应用,尽管它的果源源代码形式类似于普通应用,但它以独特的码安码存在方式运行在系统内部。这个模块以APK文件的果源形式存在,位于`frameworks/base/packages/SystemUI/`目录下,码安码slidyy源码并安装在`system/priv-app/-SystemUI`路径中。果源尽管它是码安码一个应用,但它的果源界面和功能设计使得用户在使用过程中难以将其视为一个传统应用。

       SystemUI的码安码核心功能包括提供系统控制界面,例如音量控制、果源通知管理等。码安码其中,果源冒泡排序的核心源码音量控制模块(VolumeUI)在用户操作音量键时负责提供相应的码安码用户界面,并允许设置音量大小和情景模式。果源VolumeUI的代码主要集中在`SystemUI/volume`目录下,不同模式下音量键触发的UI显示样式会有所不同,包括通话、铃声(通知)、梦幻西游笑傲版源码音乐、闹铃、蓝牙输出等。

       当音量键触发时,VolumeUI通过系统服务启动,主要经过初始化过程,日均选股公式源码包括读取配置、实例化UI控件、创建VolumeController控制器等步骤。初始化过程中的关键步骤包括实例化`VolumePanel`,这是一个`Handler`的子类,负责UI的溯源码印刷咨询热线绘制和控制。此过程以Dialog的形式显示UI,确保UI的交互性。`VolumePanel`同时继承了`VolumeUI`的`Pannel`,因此,它不仅负责显示,还控制了UI的显示和关闭。

       VolumeUI的架构展示了如何在不同模式下控制音量。当非活动窗口接收到音量键事件时,这些事件通常在`Window`中被处理。系统通过Binder机制将事件信息传递给`MediaSessionService`,然后传递给`AudioService`,最后到达`SystemUI`的`VolumeUI`部分,使得音量控制响应用户操作。

       在具体的音量控制过程中,当活动窗口为Launcher桌面时,音量键事件在`PhoneWindow`中被处理。事件分发到`onKeyUp()`和`onKeyDown()`方法,调用`sendAdjustVolumeBy()`方法来调整音量。这些事件最终传递到`MediaSessionService`,进一步通过Binder机制到达`AudioService`,完成音量调整的过程。

       总结整个流程,从音量键触发到UI显示和关闭,涉及到多个系统服务和进程之间的通信。通过Binder机制确保了不同组件之间的高效通信和控制。整个控制过程直观且高效,为用户提供了一致且响应迅速的音量控制体验。