原文地址:

http://li53262182.blog.163.com/blog/static/12839338720091113382422/


Android button原理

2009-12-01 15:38:02|分类: android相关 |字号订阅

在Android中Button是非常常用的一个View控件,原本以为Button实现的代码肯定很多,但是看了原来着实吃了一惊.Button的源码几乎仅仅对继承的TextView类做了一个小小的修改,仅仅是加了一个Style. 一个Style就能够实现Button的显示效果样式么?Android的Style机制真的很强大.

首先来看一下ButtonView的实现代码:

        
  1. *<p><strong>XMLattributes</strong></p>
  2. *<p>
  3. *See{@linkandroid.R.styleable#ButtonButtonAttributes},
  4. *{@linkandroid.R.styleable#TextViewTextViewAttributes},
  5. *{@linkandroid.R.styleable#ViewViewAttributes}
  6. *</p>
  7. */
  8. ublicclassButtonextendsTextView{
  9. publicButton(Contextcontext){
  10. this(context,null);
  11. }
  12. publicButton(Contextcontext,AttributeSetattrs){
  13. this(context,attrs,com.android.internal.R.attr.buttonStyle);
  14. }
  15. publicButton(Contextcontext,AttributeSetattrs,intdefStyle){
  16. super(context,attrs,defStyle);
  17. }

可以看到,Button继承了TextView之后,仅仅是添加了一个默认的Style —

com.android.internal.R.attr.buttonStyle

我们知道,button其实在TextView的基础之上增加了按钮的背景效果以及按钮按下去的press效果。这么一个Style文件可以搞定这件事情么?顺着这个style找下去,在Android的源码中找到style.xml,并找到相关的定义:

        
  1. <stylename="Widget.Button">
  2. <itemname="android:background">@android:drawable/btn_default</item>
  3. <itemname="android:focusable">true</item>
  4. <itemname="android:clickable">true</item>
  5. <itemname="android:textSize">20sp</item>
  6. <itemname="android:textStyle">normal</item>
  7. <itemname="android:textColor">@android:color/button_text</item>
  8. <itemname="android:gravity">center_vertical|center_horizontal</item>
  9. </style>

这里定义了好多style相关的属性,其他的属性都好理解,这个backgroud属性难道仅仅是一个drawable图片?如果仅仅是一个图片的化,怎么能够实现button各种状态下表现出不同背景的功能呢?还是来看看这个drawable到底是什么东西。

到drwable目录中发现这个btn_default原来也是一个xml文件,内容如下:

        
  1. <selectorxmlns:android="http://schemas.android.com/apk/res/android">
  2. ?<itemandroid:state_window_focused="false"android:state_enabled="true"
  3. android:drawable="@drawable/btn_default_normal"/>
  4. ?<itemandroid:state_window_focused="false"android:state_enabled="false"
  5. android:drawable="@drawable/btn_default_normal_disable"/>
  6. <itemandroid:state_pressed="true"
  7. android:drawable="@drawable/btn_default_pressed"/>
  8. <itemandroid:state_focused="true"android:state_enabled="true"
  9. android:drawable="@drawable/btn_default_selected"/>
  10. <itemandroid:state_enabled="true"
  11. android:drawable="@drawable/btn_default_normal"/>
  12. <itemandroid:state_focused="true"
  13. android:drawable="@drawable/btn_default_normal_disable_focused"/>
  14. <item
  15. android:drawable="@drawable/btn_default_normal_disable"/>
  16. </selector>

其实drawable在Android中有很多种,最普通的就是一个图片。而这里用到的是StateListDrawable。当Android的解析器解析到上面的xml时,会自动转化成一个StateListDrawable类的实例。这个类的一些核心代码如下:

        
  1. publicclassStateListDrawableextendsDrawableContainer{
  2. publicStateListDrawable()
  3. {
  4. this(null);
  5. }
  6. /**
  7. *Addanewimage/stringIDtothesetofimages.
  8. *@paramstateSet-AnarrayofresourceIdstoassociatewiththeimage.
  9. *SwitchtothisimagebycallingsetState().
  10. *@paramdrawable-Theimagetoshow.
  11. */
  12. publicvoidaddState(int[]stateSet,Drawabledrawable){
  13. if(drawable!=null){
  14. mStateListState.addStateSet(stateSet,drawable);
  15. //incasethenewstatematchesourcurrentstate...
  16. onStateChange(getState());
  17. }
  18. }
  19. ...
  20. }

xml里面每一个Item就对应一种状态,而每一个有state_的属性就是一个状态的描述,drawable则是真正的drawable图片(这个其实也可以是其他类型的Drawable实例)。

当把这个实例付给View作为Background的时候,View会根据不同的state来切换不同状态的图片,从而实现了Press等诸多效果。简单看一下View中有关状态切换的代码如下:

各种View的状态列表:

        
  1. /**
  2. *Theorderhereisveryimportantto{@link#getDrawableState()}
  3. */
  4. privatestaticfinalint[][]VIEW_STATE_SETS={
  5. EMPTY_STATE_SET,//00000
  6. WINDOW_FOCUSED_STATE_SET,//00001
  7. SELECTED_STATE_SET,//00010
  8. SELECTED_WINDOW_FOCUSED_STATE_SET,//00011
  9. FOCUSED_STATE_SET,//00100
  10. FOCUSED_WINDOW_FOCUSED_STATE_SET,//00101
  11. FOCUSED_SELECTED_STATE_SET,//00110
  12. FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET,//00111
  13. ENABLED_STATE_SET,//01000
  14. ENABLED_WINDOW_FOCUSED_STATE_SET,//01001
  15. ENABLED_SELECTED_STATE_SET,//01010
  16. ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET,//01011
  17. ENABLED_FOCUSED_STATE_SET,//01100
  18. ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET,//01101
  19. ENABLED_FOCUSED_SELECTED_STATE_SET,//01110
  20. ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET,//01111
  21. PRESSED_STATE_SET,//10000
  22. PRESSED_WINDOW_FOCUSED_STATE_SET,//10001
  23. PRESSED_SELECTED_STATE_SET,//10010
  24. PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET,//10011
  25. PRESSED_FOCUSED_STATE_SET,//10100
  26. PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET,//10101
  27. PRESSED_FOCUSED_SELECTED_STATE_SET,//10110
  28. PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET,//10111
  29. PRESSED_ENABLED_STATE_SET,//11000
  30. PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET,//11001
  31. PRESSED_ENABLED_SELECTED_STATE_SET,//11010
  32. PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET,//11011
  33. PRESSED_ENABLED_FOCUSED_STATE_SET,//11100
  34. PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET,//11101
  35. PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET,//11110
  36. PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET,//11111
  37. };

设置background的代码:

        
  1. /**
  2. *SetthebackgroundtoagivenDrawable,orremovethebackground.Ifthe
  3. *backgroundhaspadding,thisView'spaddingissettothebackground's
  4. *padding.However,whenabackgroundisremoved,thisView'spaddingisn't
  5. *touched.Ifsettingthepaddingisdesired,pleaseuse
  6. *{@link#setPadding(int,int,int,int)}.
  7. *
  8. *@paramdTheDrawabletouseasthebackground,ornulltoremovethe
  9. *background
  10. */
  11. publicvoidsetBackgroundDrawable(Drawabled){
  12. ...
  13. if(d.isStateful()){
  14. d.setState(getDrawableState());
  15. }
  16. d.setVisible(getVisibility()==VISIBLE,false);
  17. mBGDrawable=d;
  18. ...
  19. invalidate();
  20. }

红色的部分就是首先判断这个Drawable对象是否支持state切换,当然我们这里的drawable是支持的。然后设置状态,达到切换图片的效果。

所以,以后作一些图片需要根据状态切换不同的效果可以用这个方法啦。。。





更多相关文章

  1. android 按钮点击效果 imageview button imagebutton均可
  2. Android ImageView图片拖动效果
  3. 一个不错的启动菜单显示屏动画效果
  4. Android基于ViewFilpper实现文字LED显示效果示例
  5. android耳机状态的检测
  6. Android多线程下载远程图片
  7. Android 仿滴滴首页嵌套滑动效果
  8. Android 实现变色状态栏

随机推荐

  1. css样式来源和选择器入门
  2. CSS样式来源和优先级/CSS选择器与权重
  3. 用户注册表单与简单后台
  4. 20220706第三节CSS样式选择器的应用场景
  5. 自定义样式的来源和优先级/css常用选择器
  6. 图文列表与课程表
  7. 自定义样式的来源与优先级及选择器与权重
  8. CSS选择器中优先级和权重区别
  9. CSS的样式来源与样式选择器
  10. VSCode中Emmet的快捷操作