深入理解android2-WMS,控件

深入理解android2-WMS,控件,第1张

title: '深入理解android2-WMS,控件-图床版'

date: 2020-03-08 16:22:42

tags:

typora-root-url: /深入理解android2-WMS-控件

typora-copy-images-to: /深入理解android2-WMS-控件

WMS主要负责两个功能, 一是负责窗口的管理,如窗口的增加删除,层级二是负责全局事件的派发如触摸点击事件

先简单介绍几个重要的类

IWindowSession 进程唯一的是一个匿名binder通过他向WMS请求窗口 *** 作

surface 绘画时,canvas会把内容绘制到surface里surface是有surfaceFlinger提供给客户端的

WindowManagerLayoutParams 集成自ViewGroupLayoutParams用来指明client端的窗口的一些属性最重要的是type 根据这属性来对多个窗口进程ZOrder的排序

windowToken向WMS添加的窗口令牌每个窗口都要有一个令牌

IWindow 是client提供给WMS的继承自binderWMS通过IWindow对象来主动发起client端的事件

窗口的本周就是进行绘制所使用的surface,客户端向WMS添加窗口的过程,就是WMS为客户端分配surface的过程

ui框架层就是使用surface上绘制ui元素及响应输入事件

WMS负责surface的分配窗口的层级顺序

surfaceFlinger负责将多个Surface混合并输出

WMS有SystemServer 进程启动他和AMS其实是运行于一个进程中的只是分别有各自的线程

上边传入了两个handler这里就使用windowManager的handler来创建WMS也就是在一个handerThread线程中创建

用来管理每个窗口的事件输入也就是把输入事件转发到正确的窗口

能获取显示系统的同步信号用来驱动动画的渲染

所有窗口动画的总管,在mChoreographer的驱动下渲染所有动画

只有PhoneWindowManager一个实现定义了很多窗口相关的策略是最重要的成员,比如负责窗口的zorder顺序

zorder就是各个窗口在z轴的值越大越在屏幕上层窗口就是根据zorder值一层一层堆在一起

可以绘制的屏幕列表默认是只有1个

管理所以窗口的显示令牌token,每个窗口都要属于一个token这里的IBinder 是

表示所有Activity的token AppWindowToken是WindowToken的子类,这个list的顺序和AMS中对mHistory列表中activity的顺序是一样的 反应了系统中activity的叠加顺序也就是说所有窗口都有WindowToken而Activity对应的窗口则多了AppWindowToken

每个窗口都对应一个WindowState存储改窗口的状态信息(这就和AMS中对每个activity抽象成ActivityRecord一样)

这里的iBinder 是IWIndow类

Session 是WMS提供给客户端来与WMS进行交互的,这是匿名binder为了减轻WMS的负担客户端通过IWindowManageropenSession 拿到他的代理然后通过代理与WMS交互每个进程唯一

客户端通过IWindowSessionadd 来添加窗口 iWindowSession 是同aidl形成的最终到了WMSaddWindow

这里总的来说就是确立了客户窗口的WindowTokenWindowState和DisplayContent 并都保存了起来同时根据layoutparamstype进行了些窗口等级的判断

WindowToken将同一个应用组件的窗口安排在一起一个应用组件可以是Activity,InputMethod

WindowToken使应用组件在变更窗口时必须与自己的WindowToken匹配

这里主要是为了处理窗口的层级关系而设立的

只要是一个binder对象都可以作为token向wms声明wms会把这个binder对应起一个WindowToken其实就是把客户端的binder和wms里的一个WindowToken对象进行了绑定

因为Activity比较复杂,因此WMS为Activity实现了WindowToken的子类 appwindowtoken同时在AMS启动Activity的ActivityStackstartActivityLocked里声明token

然后在activityStackrealStartActivityLocked里在发给用户进程,然后用户在通过这个binder和WMS交互时带过来

activity则在 activityStack 线程的handleResumeActivity 里把Activity 对应的窗口,加入到wMS中

取消token 也是在AMS中 ,也就是说, AMS负责avtivity的token向WMS的添加和删除

当然Activity的 rappToken 是 IApplicationTokenStub ,他里边有一系列的窗口相关的通知回调

这里总结下 AMS在创建Activity的ActivityRecord时,创建了他的appToken,有把appToken传送给WMSWMS对应匹配为APPWindowToken,最后还把这个appToken发送给activity因此AMS就通过ActivityRecord就可有直接 *** 作WMS对该窗口的绘制如图

每个window在WMS里都抽象成了WindowState他包含一个窗口的所有属性WindowState在客户端对应的则是iWidowstub类iWidowstub有很多窗口通知的回调

WindowState被保存在mWindowMap里这是整个系统所有窗口的一个全集

HashMap<IBinder, WindowToken> mTokenMap 这里是 IApplicationToken(客户端)和WindowToken的映射

HashMap<IBinder, WindowState> mWindowMap 这里是IWidow(客户端)和WindowState的映射,并且WMS通过这个IWindow 来回调客户端的方法

上图可以看出每个activity 只有一个ActivityRecord也只有一个AppToken,也就只有一个WindowToken而一个acitvity可能有多个窗口每个窗口对应一个WindowState

WindowToken用来和AMS交换 而WindowState对应的iWindow则是WMS来与客户端交互的

窗口显示次序就是窗口在Z轴的排了因为窗口是叠加在一起的因此就需要知道哪些显示在上边,哪些在下边这个由WindowState构造时确定

可见分配规则是由WindowManagerPolicy mPolicy来决定的产生 mBaseLayer和mSubLayer mBaseLayer决定该窗口和他的子窗口在所有窗口的显示位置 mSubLayer决定子窗口在同级的兄弟窗口的显示位置值越高显示约靠上

WindowState 产生了他自己这个窗口的layer值后在添加窗口的时候就会把所有窗口按layer排序插入mWindows列表中,在通过 adjustWallpaperWindowsLocked();进行层级调整

当客户端通过IWindowsessionadd后,客户端还没有获得Surface只有在执行IWindowsessionrelayout后客户端才获得了一块Surface IWindowsessionrelayout根据客户端提供的参数,为客户端提供surface具体实现是WMSrelayoutWindow

总的来说就是根据用户传入的参数,更新WindowState然后遍历所有窗口布局在设置合适的Surface尺寸,在返回给用户端

performLayoutAndPlaceSurfacesLocked 会循环调用6次里边的逻辑大概如下

这里主要下,因为之前加了锁requestTraversalLocked他又会重复执行performLayoutAndPlaceSurfacesLocked();因此会重复循环执行布局

布局这部分就记个原理吧

布局完成后客户端的尺寸和surface都得到了就可以绘制 了WMS会通知客户端布局发送变化

总结,WMS 负责管理所有的窗口包括系统窗口和APP窗口,而窗口必须有一个WindowToken所为标识符同时WMS为每个窗口创建一个WindowState类,这是窗口在服务端的抽象WindowState则绑定了一个客户端的IWindow类,WMS通过这个IWindow 向APP发送消息

AMS在启动Activity的时候把ActivityRecordtoken 通过wmsaddtoken 注册到WMS又把这个token发送到APP端因此三方可以通过这个token正确找到对应的数据

WMS负责给所以窗口按ZOrder排序,确定窗口的尺寸,提供绘画用的surface

Activity的窗口是先wmsaddtoken 建立windowToken关系 wmsaddWindow 添加串口, WMSrelayout获取surface 完成

一个windowToken对应一个Activity 但是可能对应多个windowSatate也就是对应多个窗口

是view树的根实现类是viewRootImpl但是他不是view他是用来和WMS进行交流的管理者viewRootImpl内部有个IWindowSession,是WMS提供的匿名binder,同时还有个iWindow子类,用来让WMS给viewr发消息 view通过ViewRoot向WMS发消息WMS在通过IWIndow 向APP发消息 每个View树只有一个ViewRoot,每个Activity也只有一个ViewRoot UI绘制,事件传递都是通过ViewRoot

实现类是PhoneWindow Activity和View的沟通就是通过WindowActivity实现window的各种回调一个Activity也对应一个PhoneWindow也对应一个View树

Docerview 就是View树的根这是一个View 他由PhoneWindow管理 下文的WindowManager也由phoneWindow管理

他还管理window的属性 WindowManagerlayoutparams

他是一个代理类他集成自ViewManager他的实现是WindowManagerImpl这是每个Activity都有一个但是他只是把工作委托给了 WindowManagerGlobal来实现 他负责添加删除窗口,更新窗口并控制窗口的补件属性WindowManagerLayoutparams

是进程唯一的负责这个进程的窗口管理他里边有三个集合保存这个进程所有窗口的数据这里的每个数据根据index得到的是同一个Activity属性所有的WindowManager的 *** 作都转到他这里来

private final ArrayList<View> mViews 每个view是个跟节点

private final ArrayList<ViewRootImpl> mRoots view对应的viewRoot

private final ArrayList<WindowManagerLayoutParams> mParams 窗口的layoutparams属性每个窗口一个

对于一个acitivity对象永远对应一个PhoneWindow,一个WindowManagerImpl,一个WMS端的APPWindowToken,一个AMS里的ActivityRecord(但是如果一个activity在栈里有多个对象,就有多个ActivityRecord和AppWindowToken),acitvity 的默认窗口的view树是DocerView

一个窗口 对应一个ViewRoot,一个View树一个WindowManagerLayoutParams,一IWindow(WMS回调app)一个WSM端的WindowSatate

但是一个Activity可以有多个窗口,因此对应WMS里可能有多个WindowSatate这些WindowState都对应一个AppWindowToken

一个Activity可能被加载多次因此在AMS中可能有多个ActivityRecord对应这个activit的多个对象

但是一个进程则对应一个WindowManagerGlobal一个ActivityThread(主线程)一个ApplicationThread(AMS调用app)一个iWindowSession(viewroot向WMS发消息)

这里的区别就是 app与AMS 的交互是以进程之间进行通信而App与WMS的交互则是以窗口作为通信基础

当Activity由AMS启动时ActivityThread 通过handleResumeActivity执行resume相关的 *** 作这个函数首先是执行activityresume, 此时activity 对应的view树已经建立完成(oncreate中建立,PhoneWindow也创建了)需要把activity的窗口添加到WMS中去管理

这里的wm是WindowManager是每个activity一个他内部会调用WindowManagerGlobaladdView

WindowManagerGlobaladdView

这里会为窗口创建ViewRootImpl 并把viewViewRootImplWindowMaLayoutParams都保存在WindowManagerGlobal中, 并通过ViewRootImpl向WMS添加窗口

如果这个窗口是子窗口(wparamstype >= WindowManagerLayoutParamsFIRST_SUB_WINDOW &&

wparamstype <= WindowManagerLayoutParamsLAST_SUB_WINDOW)

就把子窗口的token设为父窗口的token否则就是所属activity的token

在来个图

在这里我们看到我们通过mWindowManager = (WindowManager) mContextgetSystemService(ContextWINDOW_SERVICE); 拿到的并不是远程的WMS而是本地的WindowManagerImpl 他又把请求转发给WindowManagerGlobal ,而WindowManagerGlobal作为进程单实例又是吧请求转给对应窗口的ViewRootImplViewRootImpl通过WMS的IWindowSession 把数据发给WMS

ViewRootImpl用来沟通View和WMS并接受WMS的消息这是双向的binder通信作为整个空间树的根部,控件的测量,布局,绘制,输入时间的派发都由ViewRootImpl来触发

ViewRootImpl由WindowManagerGlobal创建,是在activityThreadhandleResumeActivity时,先执行activityresume在调用wmaddView 就会执行WindowManagerGlobaladdView里创建ViewRootImpl,此时是在ui线程中

ViewRootImpl里的mView属性host属性,就是view树

添加窗口时通过requestLayout();向ui线程发送消息最后回调到ViewRootImplperformTraversals他是整个ui控件树,measurelayoutdraw的集合

这里分为五个阶段

预测量阶段进行第一次测量,获得viewgetMeasuredWitdh/Height,此时是控件树期望的尺寸会执行View的onMeasure

布局阶段,根据预测量的结果,通过IWindowSessionrelayout向WMS请求调整窗口的尺寸这会使WMS对窗口重新布局,并把结果返回给ViewRootImpl

最终测量阶段, 预测量的结果是view树期望的结果WMS可能会进行调整,在这里WMS已经把结果通知了ViewRootImpl因此这里会窗口实际尺寸performTraversals进行布局view及子类的onMeasure会被回调

布局阶段 测量完成后获得空间的尺寸,布局要确定控件的位置,View及子类的onLayout会被回调

绘制阶段,使用WMS提供的surface进行绘制,View及子类的onDraw会被回调

通常我们看到的都是 先measure,在layout在draw 这里看到其实measure先得到期望值,在和WMS沟通WMS在调整后,返回确定值,在根据确定值进行mesure

measureHierarchy里会通过三次协商执行performMeasure 来确认合适的尺寸

performMeasure 会调用view 的measure 优会调用onMeasure 我们可重写onMeasure来实现测量而measure 方法是final的onMeasure 的结果通过setMeasuredDimension方法保存

对于view onMeasure比较容易 对于ViewGroup则还要遍历调用他所以子view的measure 并且需要考虑padding和子view 的margin padding是控件外内边距 margin 是控件外边距

ViewGroup需要先测量完子view在根据子view的测量值得到自己的宽高举例,如果只有一个子view那么ViewGroup的宽= 子view的宽+子view的margin+viewg的padding 至少是这个值

继续回到performTraversals

这里就是提前测量了一下得到控件树希望的尺寸大小,

通过relayoutWindow来布局窗口 ViewRootImpl 通过IWindowSession 来通知WMS进行窗口布局

这里主要下 调用WMS后WMS会调整窗口的尺寸 同时会生成surface返回给ViewRootImpl 因此后续的绘画就有了画布了可以看到最后的参数是mSurface这是本地的surface 这里会和wms的进行绑定

接下来继续performTraversals,绑定WMS返回的surface然后更新尺寸

最后进行最终测量 上边过程太乱了 了解下就行还是看常见的控件绘制流程

绘制由viewRootImplperformTraversals触发, 抽取出来后,就是这样

就是直接调用view树的根的measure方法 传入到View

该方法是final 意味着无法重写这里又会调用onMeasure

因此对于view在onMeasure中调整好高度,通过setMeasuredDimension设置好自己的测量宽高就可以了

对应ViewGroup则在onMeasure中,先要遍历子view调用他们的measure(注意一定是调用子类的measure,measure又会调用onMeasure), 子view宽高都知道后,在根据子view的宽高来设置自己也就是ViewGroup的宽高受子view影响

可以看到view的measure又调用了onMeasure, 如果是view 则可以直接重新onMeasure来设定大小而对于ViewGroup, 则需要重写onMeasure来先遍历子view设定大小然后再设定viewGroup的大小 ViewGroup并没有重写onMeasure因为每个ViewGroup要实现的效果不同,需要自己完成但ViewGroup提供了几个方法供ViewGroup的继承类来遍历子view

view的宽高由自己的layoutParams和父view提供的 widthMeasureSpec|heightMeasureSpec共同决定

View 自己的宽高,是保存在LayoutParams中对,以宽举例 LayoutParamswidth 有三种情况,精确值(就是指定大小),MATCH_PARENT WRAP_CONTENT,模式则有fuview提供有 unspecified,exactly,at_most三种

匹配如下

其实这个很好理解 如果子view自己指定了宽高就用他的值就可以如果子view是match_parent那就使用父view提供的宽高 如果子view是wrap_content,那就不能超过父view的值

看下ViewGroup为子view绘制而提供的方法,可以看到ViewGroup会减去padding和margin,来提供子view的宽高

上步measure过程未完成后,整个view书的 测量宽高都得到了也就是viewgetMeasuredWidth()和getMeasuredHeight()

performLayout中会调用mViewlayout 这样就把事件从ViewRootImpl传递到了view而layout中又会调用onLayoutViewGroup需要重写onLayout为子view进行布局,遍历调用子view的layout因此就完成整个view树的laylut过程

竖向的实现, 竖向的就行把view从上到下一次排开

这里注意区分measure过程是先得到子view的测量值,在设定父ViewGroup的值而layout过程则是先传入父view的左上右下值,来计算子view的左上右下的位置值这里应该具有普遍性但不知道是否绝对

performDraw 中的调用draw又调用mViewdraw然后就进入view树的绘制了

view的draw 又会调用onDraw ,viewGroup又调用dispatchDraw()把draw分发到子view里 绘制的画布就是canvas 这是从surfacelockCanvas中获得的一个区域

而在ViewGroupdispatchDraw中重要的一点是getChildDrawingOrder 表示子view的绘制顺序默认是与ziview的添加顺序一样我们也可以改变他最后绘制的会显示在最上边,而这也影响view的事件传递顺序

viewdraw 就是一层一层的画内容先画北京,在onDraw在画装饰什么的

canvastranslate(100,300)通过平移坐标系使之后的内容可以直接在新坐标系中绘制

这就是ViewGroup在向子view传递canvas的时候方便多了 会之前先对其ziview的左上角那么子view就可以直接从自己坐标轴的(0,0)开始绘制, 绘制完成后ViewGroup在还原原有坐标系

canvassave canvasrestore 用来保存还原坐标系

viewinvalidate

当某个view发送变化需要重绘时,通过viewinvalidate向上通知到ViewRootImpl从这个view到ViewRootImpl的节点都标记为藏区域dirty area ViewRootimpl再次从上到下重绘时,只绘制这些脏区域效率高

本来安卓兼容使用键盘,也支持,触摸二者的输入事件派发不一样使用键盘时会有个控件处于获得焦点状态处于触摸模式则由用户决定 因此控件分为两类任何情况下都能获得焦点如输入文本框只有在键盘 *** 作时才能获得焦点如菜单,按钮

安卓里有触摸模式当发送任意触摸时进入触摸模式当发送方向键和键盘或者执行ViewrequestRocusFromTouch时,退出触摸模式

获取焦点 viewrequest

先检查是否能获取焦点,

然后设置获取简单的标记,

向上传递到ViewRootimpl保证只能有一个控件获取焦点

通知焦点变化的监听者

更新view的drawable状态,

requestChildFocus会把焦点事件层层上报取消原来有焦点的控件最后的效果就是从viewrootimpl中到最终有焦点的view构成一条 mFoucued 标识的链条来个图就明白了每个view的mFocused总是指向他的直接下级

获取focus的传递是从底层view到顶层的ViewRootImpl而取消focus测试从顶层的ViewRootimpl到底层原来那个获得焦点的view

而如果是ViewGroup请求获取焦点,会根据FLAG_MASK_FOCUSABILITY特性来做不同方式,分别有先让自己获取焦点,或者安卓view的索引递增或者递减来匹配view

ViewRootImpl 中的WindowInputEventReceiver接受输入事件他会把事件包装成一个QueuedInputEvent然后追加到一个单链表的末尾接着重头到尾的处理输入事件,并通过deliverInputEvent完成分发这里会把单链表所有事件都处理完

deliverInput中又会把触摸事件执行到通过 ViewPreImeInputStageprocessKeyEvent 转入mViewdispatchPointerEvent(event)这里又进入 dispatchTouchEvent

MotionEvent是触摸事件的封装getAction可以拿到动作的类型和触控点索引号

getX(),getY()拿到动作的位置信息通过getPointID拿到触控点的id 动作以down 开头跟多个move最后是up

,当事件返回true表示事件被消费掉了

TextView属性汇总

android:autoLink设置是否当文本为URL链接/email/电话号码/map时,文本显示为可点击的链接。可选值(none/web/email/phone/map/all)

android:autoText如果设置,将自动执行输入值的拼写纠正。此处无效果,在显示输入法并输入的时候起作用。

android:bufferType指定getText()方式取得的文本类别。选项editable 类似于StringBuilder可追加字符,也就是说getText后可调用append方法设置文本内容。spannable 则可在给定的字符区域使用样式,参见这里1、这里2。

android:capitalize设置英文字母大写类型。此处无效果,需要d出输入法才能看得到,参见EditView此属性说明。

android:cursorVisible设定光标为显示/隐藏,默认显示。

android:digits设置允许输入哪些字符。如“1234567890+-/% ()”

android:drawableBottom在text的下方输出一个drawable,如。如果指定一个颜色的话会把text的背景设为该颜色,并且同时和background使用时覆盖后者。

android:drawableLeft在text的左边输出一个drawable,如。

android:drawablePadding设置text与drawable()的间隔,与drawableLeft、 drawableRight、drawableTop、drawableBottom一起使用,可设置为负数,单独使用没有效果。

android:drawableRight在text的右边输出一个drawable。

android:drawableTop在text的正上方输出一个drawable。

android:editable设置是否可编辑。

android:editorExtras设置文本的额外的输入数据。

android:ellipsize设置当文字过长时,该控件该如何显示。有如下值设置:”start”—-省略号显示在开头;”end” ——省略号显示在结尾;”middle”—-省略号显示在中间;”marquee” ——以跑马灯的方式显示(动画横向移动)

android:freezesText设置保存文本的内容以及光标的位置。

android:gravity设置文本位置,如设置成“center”,文本将居中显示。

android:hintText为空时显示的文字提示信息,可通过textColorHint设置提示信息的颜色。此属性在 EditView中使用,但是这里也可以用。

android:imeOptions附加功能,设置右下角IME动作与编辑框相关的动作,如actionDone右下角将显示一个“完成”,而不设置默认是一个回车符号。这个在EditView中再详细说明,此处无用。

android:imeActionId设置IME动作ID。

android:imeActionLabel设置IME动作标签。

android:includeFontPadding设置文本是否包含顶部和底部额外空白,默认为true。

android:inputMethod为文本指定输入法,需要完全限定名(完整的包名)。例如:comgoogleandroidinputmethodpinyin,但是这里报错找不到。

android:inputType设置文本的类型,用于帮助输入法显示合适的键盘类型。在EditView中再详细说明,这里无效果。

android:linksClickable设置链接是否点击连接,即使设置了autoLink。

android:marqueeRepeatLimit在ellipsize指定marquee的情况下,设置重复滚动的次数,当设置为 marquee_forever时表示无限次。

android:ems设置TextView的宽度为N个字符的宽度。这里测试为一个汉字字符宽度

android:maxEms设置TextView的宽度为最长为N个字符的宽度。与ems同时使用时覆盖ems选项。

android:minEms设置TextView的宽度为最短为N个字符的宽度。与ems同时使用时覆盖ems选项。

android:maxLength限制显示的文本长度,超出部分不显示。

android:lines设置文本的行数,设置两行就显示两行,即使第二行没有数据。

android:maxLines设置文本的最大显示行数,与width或者layout_width结合使用,超出部分自动换行,超出行数将不显示。

android:minLines设置文本的最小行数,与lines类似。

android:lineSpacingExtra设置行间距。

android:lineSpacingMultiplier设置行间距的倍数。如”12”

android:numeric如果被设置,该TextView有一个数字输入法。此处无用,设置后唯一效果是TextView有点击效果,此属性在EdtiView将详细说明。

android:password以小点””显示文本

android:phoneNumber设置为电话号码的输入方式。

android:privateImeOptions设置输入法选项,此处无用,在EditText将进一步讨论。

android:scrollHorizontally设置文本超出TextView的宽度的情况下,是否出现横拉条。

android:selectAllOnFocus如果文本是可选择的,让他获取焦点而不是将光标移动为文本的开始位置或者末尾位置。 TextView中设置后无效果。

android:shadowColor指定文本阴影的颜色,需要与shadowRadius一起使用。

android:shadowDx设置阴影横向坐标开始位置。

android:shadowDy设置阴影纵向坐标开始位置。

android:shadowRadius设置阴影的半径。设置为01就变成字体的颜色了,一般设置为30的效果比较好。

android:singleLine设置单行显示。如果和layout_width一起使用,当文本不能全部显示时,后面用“…”来表示。如android:text="test_ singleLine "

android:singleLine="true" android:layout_width="20dp"将只显示“t…”。如果不设置singleLine或者设置为false,文本将自动换行

android:text设置显示文本

android:textAppearance设置文字外。如 “android:attr/textAppearanceLargeInverse”这里引用的是系统自带的一个外观,表示系统是否有这种外观,否则使用默认的外观。可textAppearanceButton/textAppearanceInverse/textAppearanceLarge/textAppearanceLargeInverse/textAppearanceMedium/textAppearanceMediumInverse/textAppearanceSmall/textAppearanceSmallInverse

android:textColor设置文本颜色

android:textColorHighlight被选中文字的底色,默认为蓝色

android:textColorHint设置提示信息文字的颜色,默认为灰色。与hint一起使用。

android:textColorLink文字链接的颜色

android:textScaleX设置文字之间间隔,默认为10f。

android:textSize设置文字大小,推荐度量单位”sp”,如”15sp”

android:textStyle设置字形[bold(粗体) 0, italic(斜体) 1, bolditalic(又粗又斜) 2] 可以设置一个或多个,用“|”隔开

android:typeface设置文本字体,必须是以下常量值之一:normal 0, sans 1, serif 2, monospace(等宽字体) 3]

android:height设置文本区域的高度,支持度量单位:px(像素)/dp/sp/in/mm(毫米)

android:maxHeight设置文本区域的最大高度

android:minHeight设置文本区域的最小高度

android:width设置文本区域的宽度,支持度量单位:px(像素)/dp/sp/in/mm(毫米),与layout_width 的区别看这里。

android:maxWidth设置文本区域的最大宽度

android:minWidth设置文本区域的最小宽度

Android activity属性汇总

android:allowTaskReparenting

是否允许activity更换从属的任务,比如从短信息任务 切换到浏览器任务。

android:alwaysRetainTaskState

是否保留状态不变, 比如切换回home, 再从新打开, activity处于最后的状态

android:clearTaskOnLanunch

比如 P 是 activity, Q 是被P 触发的 activity, 然后返回Home, 从新启动 P, 是否显示 Q

android:configChanges

当配置list发生修改时,是否调用 onConfigurationChanged() 方法 比如 "locale|navigation|orientation"

android:enabled

activity 是否可以被实例化,

android:excludeFromRecents

是否可被显示在最近打开的activity列表里

android:exported

是否允许activity被其它程序调用

android:finishOnTaskLaunch

是否关闭已打开的activity当用户重新启动这个任务的时候

androidicon

android:label

android:launchMode

activity启动方式, "standard" "singleTop" "singleTask" "singleInstance"

其中前两个为一组, 后两个为一组

android:multiprocess

允许多进程

android:name

activity的类名, 必须指定

androidnHistory

是否需要移除这个activity当用户切换到其他屏幕时。 这个属性是 API level 3 中引入的

android:permission

android:process

一 个activity运行时所在的进程名,所有程序组件运行在应用程序默认的进程中,这个进程名跟应用程序的包名一致。中的元素process属性能够为所有组件设定一个新的默认值。但是任何组件都可以覆盖这个默认值,允许你将你的程序放在多进程中运行。 如果这个属性被分配的名字以:开头,当这个activity运行时, 一个新的专属于这个程序的进程将会被创建。 如果这个进程名以小写字母开头,这个activity将会运行在全局的进程中,被它的许可所提供。

android:screenOrientation

activity显示的模式, "unspecified" 默认值 "landscape" 风景画模式,宽度比高度大一些 "portrait" 肖像模式, 高度比宽度大。 "user" 用户的设置 "behind" "sensor" "nosensor"

android:stateNotNeeded

是否 activity被销毁和成功重启并不保存状态

android:taskAffinity

activity的亲属关系, 默认情况同一个应用程序下的activity有相同的关系

android:theme

activity的样式主题, 如果没有设置,则activity的主题样式从属于应用程序, 参见元素的theme属性

android:windowSoftInputMode

activity主窗口与软键盘的交互模式, 自从API level 3 被引入

活动的主窗口如何与包含屏幕上的软键盘窗口交互。这个属性的设置将会影响两件事情:

1>    软键盘的状态——是否它是隐藏或显示——当活动(Activity)成为用户关注的焦点。

2>    活动的主窗口调整——是否减少活动主窗口大小以便腾出空间放软键盘或是否当活动窗口的部分被软键盘覆盖时它的内容的当前焦点是可见的。

它的设置必须是下面列表中的一个值,或一个”state…”值加一个”adjust…”值的组合。在任一组设置多个值——多个”state…”values,例如&mdash有未定义的结果。各个值之间用|分开。例如: <activity android:windowSoftInputMode="stateVisible|adjustResize" >

在这设置的值(除"stateUnspecified"和"adjustUnspecified"以外)将覆盖在主题中设置的值

值 描述

"stateUnspecified" 软键盘的状态(是否它是隐藏或可见)没有被指定。系统将选择一个合适的状态或依赖于主题的设置。这个是为了软件盘行为默认的设置。

"stateUnchanged" 软键盘被保持无论它上次是什么状态,是否可见或隐藏,当主窗口出现在前面时。

"stateHidden" 当用户选择该Activity时,软键盘被隐藏——也就是,当用户确定导航到该Activity时,而不是返回到它由于离开另一个Activity。

"stateAlwaysHidden" 软键盘总是被隐藏的,当该Activity主窗口获取焦点时。

"stateVisible" 软键盘是可见的,当那个是正常合适的时(当用户导航到Activity主窗口时)。

"stateAlwaysVisible" 当用户选择这个Activity时,软键盘是可见的——也就是,也就是,当用户确定导航到该Activity时,而不是返回到它由于离开另一个Activity。

"adjustUnspecified" 它不被指定是否该Activity主窗口调整大小以便留出软键盘的空间,或是否窗口上的内容得到屏幕上当前的焦点是可见的。系统将自动选择这些模式中一种主要依赖于是否窗口的内容有任何布局视图能够滚动他们的内容。如果有这样的一个视图,这个窗口将调整大小,这样的假设可以使滚动窗口的内容在一个较小的区域中可见的。这个是主窗口默认的行为设置。

"adjustResize" 该Activity主窗口总是被调整屏幕的大小以便留出软键盘的空间。

"adjustPan" 该Activity主窗口并不调整屏幕的大小以便留出软键盘的空间。相反,当前窗口的内容将自动移动以便当前焦点从不被键盘覆盖和用户能总是看到输入内容的部分。这个通常是不期望比调整大小,因为用户可能关闭软键盘以便获得与被覆盖内容的交互 *** 作。

Android EditText 属性汇总

android:layout_gravity="center_vertical"

设置控件显示的位置:默认top,这里居中显示,还有bottom

android:hint="请输入数字!"

设置显示在空间上的提示信息

android:numeric="integer"

设置只能输入整数,如果是小数则是:decimal

android:singleLine="true"

设置单行输入,一旦设置为true,则文字不会自动换行。

android:password="true"

设置只能输入密码

android:textColor = "#ff8c00"

字体颜色

android:textStyle="bold"

字体,bold, italic, bolditalic

android:textSize="20dip"

大小

android:capitalize = "characters"

以大写字母写

android:textAlign="center"

EditText没有这个属性,但TextView有

android:textColorHighlight="#cccccc"

被选中文字的底色,默认为蓝色

android:textColorHint="#ffff00"

设置提示信息文字的颜色,默认为灰色

android:textScaleX="15"

控制字与字之间的间距

android:typeface="monospace"

字型,normal, sans, serif, monospace

android:background="@null"

空间背景,这里没有,指透明

android:layout_weight="1"

权重,控制控件之间的地位,在控制控件显示的大小时蛮有用的。

android:textAppearance="android:attr/textAppearanceLargeInverse"

文字外观,这里引用的是系统自带的一个外观,?表示系统是否有这种外观,否则使用默认的外观。不知道这样理解对不对?

通过EditText的layout xml文件中的相关属性来实现:

  1 密码框属性 android:password="true"  这条可以让EditText显示的内容自动为星号,输入时内容会在1秒内变成字样。

  2 纯数字 android:numeric="true" 这条可以让输入法自动变为数字输入键盘,同时仅允许0-9的数字输入

  3 仅允许 android:capitalize="cwj1987" 这样仅允许接受输入cwj1987,一般用于密码验证

  下面是一些扩展的风格属性

  android:editable="false" 设置EditText不可编辑

  android:singleLine="true" 强制输入的内容在单行

  android:ellipsize="end" 自动隐藏尾部溢出数据,一般用于文字内容过长一行无法全部显示时

---------------------

在官方文档中, Tooltip 显示文本可以自由的设置显示方向,但是偏移量设置官方 API 只给出了一个 offset 属性,默认值为 0 ,类型为 number 。并无具体示例。经过测试, offset 可以接受两个值,具体如下:

在 vue 中可以使用 watch 监听 data 中的属性,如果需要监听对象的属性,可以使用如下方式:

在表单中使用 DatePicker 返回数据时国际标准时间的格式,即: "2019-12-11T16:00:00000Z" ,但在提交表单的时候需要正常的格式,可以在 on-change 时间中做如下处理:

在一些按钮的点击 *** 作中,假如没有限制,用户多次点击,会向后台发送多次请求。

还有一种情况是:当页面加载时,假如数据没有加载完成,此时为了防止用户进行 *** 作,会显示一个遮罩:加载中。这个 *** 作和上面差不多,只是触发方式不同,一个是在生命周期中触发,一个是通过用户点击触发

html:

css:

js:

html:

js:

当你使用了遮罩的方式,并且在向后台发送请求之前进行了验证,验证提示是以Messaged窗显示的,当用户多次点击时,会重复出现多次提示信息。

html:

js:

css样式:d窗遮罩层在拉滚动条发现遮罩层没铺满屏幕

解决方式:把 absolute 换成 fixed

iview样式源码:

更改为 position: fixed;

自己写遮罩的话,原理也是相同。

网站导航

使用iview动态添加表单校验,触发 this$refs[name]validate 方法校验的时候,会有一部分非 String 类型表单项提示校验未通过,console中显示 async-validator: ["xxx is not a string"]

组件写法如下:

console错误提示如下:

去掉 :rules 规则中的 trigger 属性

再次触发 this$refs[name]validate 方法校验的时候恢复正常。

未知[吐血]

这种解决方法只是一种简单的临时解决方案,暂时不知道有没有别的问题。。。╮(╯▽╰)╭

你说的form表单验证吗,

如果是,你可以把验证规则卸载formItem 中用rules属性

只要动态修改rules里面的规则就可以了

<FormItem  label="快递规则" prop="idGoodsExpressRule" :rules="idGoodsExpressRulepropRules">thisidGoodsExpressRulepropRules = { required: true, message: '不能为空', trigger: 'blur' }

具体步骤:

方法一:设置readonly属性为true。

Html代码

1

方法二:设置disabled属性为true。

Html代码

1

方法三:在对象focus时立刻让它blur,使它无法获得焦点。

Html代码

1

提示:readonly和disabled的区别在于后者完全禁止与设置该属性的对象交互(表现为不可改写、不可提交等)。

,

以上就是关于深入理解android2-WMS,控件全部的内容,包括:深入理解android2-WMS,控件、Android属性汇总、Vue+iView实战及跳坑总结等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/9609566.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-30
下一篇 2023-04-30

发表评论

登录后才能评论

评论列表(0条)

保存