`
ithinkfeed
  • 浏览: 93324 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

Button 原理 转载

阅读更多

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

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

  1. * <p><strong>XML attributes</strong></p> 
  2. * <p>  
  3. * See {@link android.R.styleable#Button Button Attributes},  
  4. * {@link android.R.styleable#TextView TextView Attributes},   
  5. * {@link android.R.styleable#View View Attributes} 
  6. * </p> 
  7. */ 
  8. ublic class Button extends TextView { 
  9.    public Button(Context context) { 
  10.        this(context, null); 
  11.    } 
  12.  
  13.    public Button(Context context, AttributeSet attrs) { 
  14.        this(context, attrs, com.android.internal.R.attr.buttonStyle); 
  15.    } 
  16.  
  17.    public Button(Context context, AttributeSet attrs, int defStyle) { 
  18.        super(context, attrs, defStyle); 
  19.    } 

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

com.android.internal.R.attr.buttonStyle

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

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

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

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

  1. <selector xmlns:android="http://schemas.android.com/apk/res/android"> 
  2. ?    <item android:state_window_focused="false" android:state_enabled="true" 
  3.         android:drawable="@drawable/btn_default_normal" /> 
  4. ?    <item android:state_window_focused="false" android:state_enabled="false" 
  5.         android:drawable="@drawable/btn_default_normal_disable" /> 
  6.     <item android:state_pressed="true"  
  7.         android:drawable="@drawable/btn_default_pressed" /> 
  8.     <item android:state_focused="true" android:state_enabled="true" 
  9.         android:drawable="@drawable/btn_default_selected" /> 
  10.     <item android:state_enabled="true" 
  11.         android:drawable="@drawable/btn_default_normal" /> 
  12.     <item android: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. public class StateListDrawable extends DrawableContainer { 
  2.     public StateListDrawable() 
  3.     { 
  4.         this(null); 
  5.     } 
  6.  
  7.     /** 
  8.      * Add a new image/string ID to the set of images. 
  9.      * @param stateSet - An array of resource Ids to associate with the image. 
  10.      * Switch to this image by calling setState().  
  11.      * @param drawable -The image to show. 
  12.      */ 
  13.     public void addState(int[] stateSet, Drawable drawable) { 
  14.         if (drawable != null) { 
  15.             mStateListState.addStateSet(stateSet, drawable); 
  16.             // in case the new state matches our current state... 
  17.             onStateChange(getState()); 
  18.         } 
  19.     } 
  20. ... 

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

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

各种View的状态列表:

  1. /** 
  2.  * The order here is very important to {@link #getDrawableState()} 
  3.  */ 
  4. private static final int[][] VIEW_STATE_SETS = { 
  5.     EMPTY_STATE_SET,                                           // 0 0 0 0 0 
  6.     WINDOW_FOCUSED_STATE_SET,                                  // 0 0 0 0 1 
  7.     SELECTED_STATE_SET,                                        // 0 0 0 1 0 
  8.     SELECTED_WINDOW_FOCUSED_STATE_SET,                         // 0 0 0 1 1 
  9.     FOCUSED_STATE_SET,                                         // 0 0 1 0 0 
  10.     FOCUSED_WINDOW_FOCUSED_STATE_SET,                          // 0 0 1 0 1 
  11.     FOCUSED_SELECTED_STATE_SET,                                // 0 0 1 1 0 
  12.     FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET,                 // 0 0 1 1 1 
  13.     ENABLED_STATE_SET,                                         // 0 1 0 0 0 
  14.     ENABLED_WINDOW_FOCUSED_STATE_SET,                          // 0 1 0 0 1 
  15.     ENABLED_SELECTED_STATE_SET,                                // 0 1 0 1 0 
  16.     ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET,                 // 0 1 0 1 1 
  17.     ENABLED_FOCUSED_STATE_SET,                                 // 0 1 1 0 0 
  18.     ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET,                  // 0 1 1 0 1 
  19.     ENABLED_FOCUSED_SELECTED_STATE_SET,                        // 0 1 1 1 0 
  20.     ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET,         // 0 1 1 1 1 
  21.     PRESSED_STATE_SET,                                         // 1 0 0 0 0 
  22.     PRESSED_WINDOW_FOCUSED_STATE_SET,                          // 1 0 0 0 1 
  23.     PRESSED_SELECTED_STATE_SET,                                // 1 0 0 1 0 
  24.     PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET,                 // 1 0 0 1 1 
  25.     PRESSED_FOCUSED_STATE_SET,                                 // 1 0 1 0 0 
  26.     PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET,                  // 1 0 1 0 1 
  27.     PRESSED_FOCUSED_SELECTED_STATE_SET,                        // 1 0 1 1 0 
  28.     PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET,         // 1 0 1 1 1 
  29.     PRESSED_ENABLED_STATE_SET,                                 // 1 1 0 0 0 
  30.     PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET,                  // 1 1 0 0 1 
  31.     PRESSED_ENABLED_SELECTED_STATE_SET,                        // 1 1 0 1 0 
  32.     PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET,         // 1 1 0 1 1 
  33.     PRESSED_ENABLED_FOCUSED_STATE_SET,                         // 1 1 1 0 0 
  34.     PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET,          // 1 1 1 0 1 
  35.     PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET,                // 1 1 1 1 0 
  36.     PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET, // 1 1 1 1 1 
  37. }; 

设置background的代码:

  1. /** 
  2.  * Set the background to a given Drawable, or remove the background. If the 
  3.  * background has padding, this View's padding is set to the background's 
  4.  * padding. However, when a background is removed, this View's padding isn't 
  5.  * touched. If setting the padding is desired, please use 
  6.  * {@link #setPadding(int, int, int, int)}. 
  7.  *  
  8.  * @param d The Drawable to use as the background, or null to remove the 
  9.  *        background 
  10.  */ 
  11. public void setBackgroundDrawable(Drawable d) { 
  12.          
  13.         ... 
  14.  
  15.         if (d.isStateful()) { 
  16.             d.setState(getDrawableState()); 
  17.         } 
  18.         d.setVisible(getVisibility() == VISIBLE, false); 
  19.         mBGDrawable = d; 
  20.          
  21.     ... 
  22.  
  23.     invalidate(); 

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

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



最近转了很多别人的东西 有空我自己也会写一些。每个人多进步一点点 加起来就是一个大大的步子。

分享到:
评论

相关推荐

    好看的button样式

    通过分析和修改这些代码,开发者可以深入理解CSS的工作原理,提升自己的前端技能。 对于初学者,了解CSS选择器、盒模型、颜色理论、文本和边框属性等基础知识至关重要。而对于经验丰富的开发者,这些样式可能提供了...

    点击Button,对button进行旋转

    在Button的布局文件(例如activity_main.xml)中,为Button添加一个id,如`android:id="@+id/myButton"`。 3. **实现点击事件处理**: 在对应的Activity中,找到Button并设置OnClickListener。当按钮被点击时,...

    button按钮样式美化

    在网页设计中,按钮(Button)是用户交互的重要元素,其样式美化对于提升用户体验和页面整体视觉效果至关重要。本文将详细讲解如何使用CSS(Cascading Style Sheets)来美化页面上的button控件。 首先,CSS是一种...

    SplitButton 分裂按钮 WPF

    在WPF(Windows Presentation Foundation)中,SplitButton是一种特殊的按钮控件,它结合了普通按钮和下拉菜单的功能。SplitButton的设计理念是为了提供更丰富的交互体验,用户不仅可以点击按钮执行主要操作,还可以...

    android 自定义各种风格button

    然而,系统默认的Button样式可能无法满足所有设计需求,因此,开发者常常需要自定义Button的各种风格,包括颜色、形状、边框、文字样式等。本文将深入探讨如何在Android中自定义各种风格的Button。 首先,我们可以...

    gtk之button的设置

    本文将详细讲解如何在GTK中设置和使用`Button`控件,结合提供的可执行代码,帮助你深入理解其工作原理。 首先,我们需要了解GTK中的基本概念。GTK采用事件驱动模型,当用户与界面交互时,如点击按钮,会产生相应的...

    自绘Button 修改Button背景

    "自绘Button 修改Button背景"这个标题表明我们将探讨如何利用`WM_DRAWITEM`消息来改变Button的默认外观。 `WM_DRAWITEM`是Windows消息系统中的一个关键消息,它在窗口控件(如Button)需要被绘制时发送。当用户界面...

    WPFButton样式

    在Windows Presentation Foundation (WPF) 中,按钮控件(Button)是用户界面中常见的元素,用于触发一个操作或事件。WPF 提供了强大的样式和模板功能,允许开发者自定义按钮的外观,以满足各种设计需求。本资源...

    ListView的Button点击更改Button本身背景

    当我们需要在ListView的每一项中包含一个Button,并实现点击Button时改变Button自身的背景,这就涉及到自定义Adapter、事件监听以及对View状态的理解。 首先,我们需要创建一个自定义的Adapter,因为ListView默认的...

    listView上增加button点击事件

    首先,我们需要理解ListView的工作原理。ListView通过Adapter来填充数据,并使用ViewHolder模式提高性能,避免不必要的视图创建。在Adapter中,我们通常会创建一个自定义的布局文件,该文件包含了ListView每一项应有...

    button_st.rar_Button_ST_STButton_button_button st_mfc button

    各种风格的VC BUTTON,对mfc button进行封装

    QML的Button自定义样式

    在QML中用ButtonStyle来自定义Button的样式,用到了states属性

    透明Button 透明Button

    4. **编程动态设置**:在Java或Kotlin代码中,可以动态地改变Button的背景,如`button.setBackgroundResource(R.drawable.transparent_button)`,其中`transparent_button`是一个定义了透明背景的Drawable资源。...

    多个Button监听源码

    本文将深入探讨如何实现多个Button的监听器,并通过源码分析来理解其工作原理。 首先,Button监听的基本原理是通过设置OnClickListener来捕获点击事件。在Java中,我们通常使用匿名内部类的方式来实现监听器: ```...

    自定义Button控件,继承Button控件App源码

    本文将深入探讨如何根据给定的标题和描述,实现一个自定义的Button控件,它将继承系统提供的Button类,并添加新的功能或视觉效果。我们将讨论以下几个关键知识点: 1. **自定义控件基础**: 自定义控件通常是为了...

    超炫button按钮动画效果

    在Android开发中,按钮(Button)是用户界面中不可或缺的元素,它承载着用户与应用交互的核心功能。本文将深入探讨如何实现“超炫button按钮动画效果”以及相关的Activity切换动画,让您的应用界面更具吸引力。 ...

    微信小程序button标签open-type属性原理解析

    这篇文章主要介绍了微信小程序button标签open-type属性原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 open-type (微信开放能力):合法值中的其中之一...

    ASP.net开发经典button样式

    在ASP.NET开发中,按钮(Button)控件是不可或缺的一部分,它用于用户与网页进行交互,触发特定的事件。创建经典且美观的button样式不仅能够提升用户体验,还能为网站增添专业感。本教程将深入探讨如何在ASP.NET中...

    ListCtrl - button

    实现这样的功能需要对MFC和Windows API有深入理解,特别是Owner-Drawn控件的原理和消息处理机制。调试过程中,利用Visual Studio的调试器查看消息循环和消息队列会有很大帮助。此外,熟悉C++对象模型和面向对象编程...

    button自适应高度和自动换行

    在网页设计中,按钮(Button)的样式和布局是用户体验中的关键元素。"button自适应高度和自动换行"这个主题主要关注如何让按钮在不同屏幕尺寸和内容长度下保持良好的视觉效果。以下是对这个主题的详细解释: 一、...

Global site tag (gtag.js) - Google Analytics