• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
百分百
http://www.qrw100.com
博客园    首页    新随笔    联系   管理    订阅  订阅

Android.自定义控件的实现

可能是一直都在做Web的富客户端开发的缘故吧,在接触Android之后,发现其控件实在惨不忍睹(不知道是否说得过于偏激),我所说的惨不忍睹的意思不是说控件难看,Android的控件非常漂亮,这是我们公司公认的,但是最大的缺点在于控件功能非常弱小。弱小得一个Radio只能放一个text,而没有value(key)可以存放。这就是为什么我说惨不忍睹的原因。

         但是这不能怪google,毕竟才刚刚发展起来,Android提供的只是一个最基本的控件实现,而非一个完整、强大的实现。可幸的是,Android提供了自定义控件的实现。有了自定义控件,我们就可以再Android的基础控件上实现我们想要的功能了。经过一天的摸索,我终于实现了我第一个自定义的组合控件——RadioButton组合RadioGroup!

         下面我将带领大家进入Android自定义控件的世界。如果觉得我的文章能够帮助大家的话,请大方留下你的一些话语。因为你们的留言是我分享经验的精神源泉!谢谢!

         1、设置自定义控件:Android自带的RadioButton只能存放text,这不符合我们的需求,我们需要一个可以同时存放key-value对应的键值。所以我们要编写一个自定义控件能存放key-value。

               设计思路:新建一个类叫org.kandy.view.RadioButton,继承自android.wedget.RadioButton,重写父类的所有构造方法。这样我们就实现了一个跟父类一摸一样的控件。在此基础上加入我们需要的功能:加入一个属性value,用来存放RadioButton的key。

               代码如下:

 

  1. public class RadioButton extends android.widget.RadioButton { 
  2.  
  3.  private String mValue; 
  4.  
  5.  public RadioButton(Context context, AttributeSet attrs, int defStyle) { 
  6.   super(context, attrs, defStyle); 
  7.  } 
  8.   
  9.  public String getValue() { 
  10.   return this.mValue; 
  11.  } 
  12.  
  13.  public void setValue(String value) { 
  14.   this.mValue = value; 
  15.  } 
  16.  public RadioButton(Context context, AttributeSet attrs) { 
  17.   super(context, attrs); 
  18.   try { 
  19.    /** 
  20.     * 跟values/attrs.xml里面定义的属性绑定 
  21.     */ 
  22.    TypedArray a = context.obtainStyledAttributes(attrs, 
  23.                  R.styleable.RadioButton); 
  24.    this.mValue = a.getString(R.styleable.RadioButton_value); 
  25.    a.recycle(); 
  26.   } catch (Exception e) { 
  27.    e.printStackTrace(); 
  28.   } 
  29.   
  30.  } 
  31.  
  32.  public RadioButton(Context context) { 
  33.   super(context); 
  34.  } 
  35.  
  36.   
  37. } 
  38.  红色代码可以先不看。先看我们新加入的属性value,由于Android习惯属性命名以m开头。所以我们自定义控件就按照这个规则来写。不过对于setter、getter方法来说,不需要加入m。像上面的:属性名称mValue,setter:setValue(),getter:getValue()。当然,你也可以不按照Android的习惯来命名。

             这样,我们就可以使用这个自定义控件了。而且可以给它设置一个value,加上父类的text属性。我们就可以在RadioButton中加入key-value的键值了。当然,这里面的key对应是控件的value属性,value是对应控件的text属性。完了?没有。自定义控件才刚开始了。

            

              2、XML中引用自定义控件

              在XML中加入自定义控件其实很简单。只需要在控件名字前加入包名即可。如下:

     

     

      <org.kandy.view.RadioButton android:id="@id/isPayDepositTrue" fsms:value="true"
          android:layout_width="wrap_content" android:layout_height="wrap_content"
          android:text="@string/yes" android:textSize="18sp">
     </org.kandy.view.RadioButton>


              同样,红色部分可以先不看,也不需要加入到代码中,这个时候加入会报错,请注意。

           

              3、attrs.xml属性定义。

              在我们的思想中,既然我在自定义控件中加入了一个新的属性,那么我就应该能够在xml中引用它,并对它赋初始值。我当初也是这样想的。可是却无从下手。就是这一点,折腾了我一个下午。

               正解:res/values/attrs.xml中定义属性,在自定义控件中获取这个属性,然后跟自定义控件的属性相绑定。

                    attrs.xml如果没有,就新建一个。这里只存放自定义控件中需要的属性,在我看来,这个文件是一个中介,负责将layout/xx.xml里面的对这个变量的引用和自定义控件里面的属性绑定起来。

                     attrs.xml完整代码如下:

     

      <?xml version="1.0" encoding="utf-8"?>
    <resources>
     <declare-styleable name="RadioButton"><!-- 控件名称-->
      <attr name="value" format="string"/><!-- 属性名称,类型-->
     </declare-styleable>
    </resources>


                   如果res下没有错误的话,在R中应该就会生成这些资源的id。这样我们就能在自定义控件中引用他们。

    4、控件属性与XML定义绑定。

               这下子我们又回到了自定义控件的编写上来了。先看看我们在第一点提到的红色字体部分。这一部分就是实现控件属性与XML定义绑定的代码。

     

     

      /**
        * 跟values/attrs.xml里面定义的属性绑定
        */
       TypedArray a = context.obtainStyledAttributes(attrs,
                     R.styleable.RadioButton);
       this.mValue = a.getString(R.styleable.RadioButton_value);
       a.recycle();


     

                TypedArray其实就是一个存放资源的Array,首先从上下文中获取到R.styleable.RadioButton这个属性资源的资源数组。attrs是构造函数传进来,应该就是对应attrs.xml文件。a.getString(R.styleable.RadioButton_value);这句代码就是获取attrs.xml中定义的属性,并将这个属性的值传给本控件的mValue.最后,返回一个绑定结束的信号给资源:a.recycle();绑定结束。

     

                  5、在xml中对控件赋初始值。

                 请看第2点,绑定结束后可以在需要赋初始值的地方赋值。

     

      <ScrollView android:layout_width="fill_parent"
     android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:fsms=http://schemas.android.com/apk/res/org.kandy>

                <org.kandy.view.RadioButton android:id="@id/isPayDepositTrue" fsms:value="true"
          android:layout_width="wrap_content" android:layout_height="wrap_content"
          android:text="@string/yes" android:textSize="18sp">
         </org.kandy.view.RadioButton>

    </ScrollView>


                红色部分首先声明命名空间。命名空间为fsms.路径是http://schemas.android.com/apk/res/这一部分是不变的,后面接的是R的路径:org.kandy.R。然后在自定义控件的xml描述中就可以这样使用fsms:value="true"。这样就实现了自定义控件的初始化赋值。

  39. 6、RadioGroup、RadioButton组合控件的实现

                      上面是自定义控件的实现,下面将要说的是组合控件的实现。在组合控件中,最经常用到的应该就是RadioGroup和RadioButton。RadioButton的实现已经在上面介绍了。下面要介绍RadioGroup的自定义控件和功能扩展:

                        代码如下:

     

     

    1. public class RadioGroup extends android.widget.RadioGroup { 
    2.  
    3.  private String mValue; 
    4.   
    5.  public RadioGroup(Context context, AttributeSet attrs) { 
    6.   super(context, attrs); 
    7.  } 
    8.  
    9.  public RadioGroup(Context context) { 
    10.   super(context); 
    11.  } 
    12.  // 设置子控件的值 
    13.  public void setChildValue(){ 
    14.   int n = this.getChildCount(); 
    15.   for(int i=0;i<n;i++){ 
    16.    final RadioButton radio = (RadioButton)this.getChildAt(i); 
    17.    if(radio.getValue().equals(this.mValue)){ 
    18.     radio.setChecked(true); 
    19.    }else{ 
    20.     radio.setChecked(false); 
    21.    } 
    22.   } 
    23.  } 
    24.  // 获取子类的值 
    25.  public void getChildValue(){ 
    26.   int n = this.getChildCount(); 
    27.   for(int i=0;i<n;i++){ 
    28.    RadioButton radio = (RadioButton)this.getChildAt(i); 
    29.    if(radio.isChecked()){ 
    30.     this.mValue=radio.getValue(); 
    31.    } 
    32.   } 
    33.  } 
    34.   
    35.  public void setValue(String value) { 
    36.   this.mValue = value; 
    37.   setChildValue(); 
    38.  } 
    39.   
    40.  public String getValue(){ 
    41.   getChildValue(); 
    42.   return this.mValue; 
    43.  } 
    44. } 



               RadioGroup只做两件事:获取子控件(RadioButton)所选择的值;设置子控件要选择的值。

               方法非常简单,循环或者RadioGroup的子控件,检测哪个控件被checked,然后getValue,将此value赋值给RadioGroup的扩展属性value。在这里不多说了。相信大家都能看懂。

posted @ 2011-11-04 15:45  爱尚美  阅读(199)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3