Android控件的选择

Android的控件非常漂亮,但不得不承认,也有缺点就是控件功能的弱小。弱小得一个Radio只能放一个text,而没有value(key)可以存放。使的一个RadioGroup里的RadioButton可以,同时被选择。如果是选择性别男女 ,岂不成了半男不女的人了。

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

         下面我将带领大家进入Android自定义控件的世界。如果觉得我的帖子能够帮助大家的话,请大家给我灌点水。因为你们的跟帖是我源源不断的精神源泉啊。

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

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

               代码如下:

  1. public class MyRadioButton extends android.widget.RadioButton implements OnCheckedChangeListener {

  2. private String mValue;

  3. public MyRadioButton(Context context, AttributeSet attrs, int defStyle) {
  4.   super(context, attrs, defStyle);
  5. }

  6. public String getValue() {
  7.   return this.mValue;
  8. }

  9. public void setValue(String value) {
  10.   this.mValue = value;
  11. }
  12. public MyRadioButton(Context context, AttributeSet attrs) {
  13.   super(context, attrs);
  14.   try {
  15.    /**
  16.     * 跟values/attrs.xml里面定义的属性绑定
  17.     */
  18.    TypedArray a = context.obtainStyledAttributes(attrs,                         R.styleable.RadioButton);           this.mValue = a.getString(R.styleable.RadioButton_value); a.recycle();
  19.   } catch (Exception e) {
  20.    e.printStackTrace();
  21.   }
  22.   setOnCheckedChangeListener(this);
  23. }

  24. public MyRadioButton(Context context) {
  25.   super(context);
  26. }

  27. @Override
  28. public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
  29. MyRadioGroup group = (MyRadioGroup) getParent();
  30. group.setTheValue(this.getValue());
  31. Log.d("-------Main", "the new value is ===>"+this.getValue());
  32. }}
复制代码



         红色代码可以先不看。先看我们新加入的属性value,由于Android习惯属性命名以m开头。所以我们自定义控件就按照这个规则来写。不过对于setter、getter方法来说,不需要加入m。像上面的:属性名称mValue,setter:setValue(),getter:getValue()。当然,你也可以不按照Android的习惯来命名。

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

         

          2、XML中引用自定义控件

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

  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:fsms="http://schemas.android.com/apk/res/com.sinxiao.myview"    android:orientation="vertical"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    >    <com.sinxiao.view.MyRadioGroup android:id="@+id/radPayOrNot"  android:layout_width="wrap_content" android:layout_height="wrap_content" ><com.sinxiao.view.MyRadioButton android:id="@+id/isPayDepositTrue" fsms:value="true"      android:layout_width="wrap_content" android:layout_height="wrap_content"      android:text="@string/yes" android:textSize="18sp" ></com.sinxiao.view.MyRadioButton><com.sinxiao.view.MyRadioButton android:id="@+id/isPayDepositFalse" fsms:value="false"      android:layout_width="wrap_content" android:layout_height="wrap_content"      android:text="@string/no" android:textSize="18sp" ></com.sinxiao.view.MyRadioButton>        </com.sinxiao.view.MyRadioGroup></LinearLayout>
复制代码

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


        

          3、attrs.xml属性定义。

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

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

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

                 attrs.xml完整代码如下:


  1. <?xml version="1.0" encoding="utf-8"?>
  2. <resources>
  3. <declare-styleable name="RadioButton"><!-- 控件名称-->
  4.   <attr name="value" format="string"/><!-- 属性名称,类型-->
  5. </declare-styleable>
  6. </resources>
复制代码


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

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

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


  1. /**
  2.     * 跟values/attrs.xml里面定义的属性绑定
  3.     */
  4.   TypedArray a = context.obtainStyledAttributes(attrs,
  5.                  R.styleable.RadioButton);
  6.    this.mValue = a.getString(R.styleable.RadioButton_value);
  7.    a.recycle();
复制代码

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

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

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



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

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

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

                    代码如下:


  1. public class MyRadioGroup extends android.widget.RadioGroup implements OnCheckedChangeListener {

  2.          private String mValue;
  3.         
  4.          public MyRadioGroup(Context context, AttributeSet attrs) {
  5.           super(context, attrs);
  6.           this.setOnCheckedChangeListener(this);
  7.          }

  8.          public MyRadioGroup(Context context) {
  9.           super(context);
  10.           this.setOnCheckedChangeListener(this);
  11.          }
  12.          private String tag ="===myRadioGroup";
  13.          // 设置子控件的值
  14.          private void setChildValue(){
  15.           int n = this.getChildCount();
  16.           Log.d(tag, "the n is "+n);
  17.           for(int i=0;i<n;i++){
  18.            MyRadioButton radio = (MyRadioButton)this.getChildAt(i);
  19.            if(radio.getValue().equals(this.mValue)){
  20.             radio.setChecked(true);
  21.            }else{
  22.             radio.setChecked(false);
  23.            }
  24.           }
  25.          }
  26.          // 获取子类的值
  27.          private void getChildValue(){
  28.           int n = this.getChildCount();
  29.           for(int i=0;i<n;i++){
  30.            MyRadioButton radio = (MyRadioButton)this.getChildAt(i);
  31.            if(radio.isChecked()){
  32.             this.mValue=radio.getValue();
  33.            }
  34.           }
  35.          }
  36.         
  37.          public void setTheValue(String value) {
  38.           this.mValue = value;
  39.          }
  40.         
  41.          public String getTheValue(){
  42.           getChildValue();
  43.           return this.mValue;
  44.           }

  45.         @Override
  46.         public void onCheckedChanged(RadioGroup group, int checkedId) {
  47.                 setChildValue();
  48.         }
  49. }
复制代码


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

           方法非常简单,循环或者RadioGroup的子控件,检测哪个控件被checked,然后getValue,将此value赋值给RadioGroup的扩展属性value。当MyRadioButton发生改变的时候,向RadioGroup赋值,然后RadioGroup根据,value刷新界面。就实现了单选的效果。

       在这里不多说了。希望大家都能看懂。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值