Android.自定义控件的实现 (转载)

尊重他人劳动成果,转载请注明出处。

转自:http://kandy0619.blog.163.com/blog/static/64344345201012325939280/

  可能是一直都在做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 }

 

 红色代码可以先不看。先看我们新加入的属性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  <org.kandy.view.RadioButton android:id="@id/isPayDepositTrue" fsms:value="true"
2 android:layout_width="wrap_content" android:layout_height="wrap_content"
3 android:text="@string/yes" android:textSize="18sp">
4 </org.kandy.view.RadioButton>

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

        

          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点,绑定结束后可以在需要赋初始值的地方赋值。

 1 <ScrollView android:layout_width="fill_parent"
2 android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:fsms=http://schemas.android.com/apk/res/org.kandy>
4
5 <org.kandy.view.RadioButton android:id="@id/isPayDepositTrue" fsms:value="true"
6 android:layout_width="wrap_content" android:layout_height="wrap_content"
7 android:text="@string/yes" android:textSize="18sp">
8 </org.kandy.view.RadioButton>
9
10 </ScrollView>

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

 

             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。在这里不多说了。相信大家都能看懂。

 

 





转载于:https://www.cnblogs.com/nanhuchongzi/archive/2012/03/29/2422914.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/404319.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

React-Router面试题汇总

[react-router] React-Router怎么获取URL的参数&#xff1f; [react-router] 在history模式中push和replace有什么区别&#xff1f; [react-router] React-Router 4中&#xff1c;Router&#xff1e;组件有几种类型&#xff1f; [react-router] React-Router怎么设置重定向…

Eclipse中使用自己的makefile管理工程

From: http://blog.csdn.net/whz_zb/article/details/7101164 我用的环境&#xff1a; &#xff08;1&#xff09;系统&#xff1a; Ubuntu 11.04 &#xff08;2&#xff09;Eclipse CDT 1. 在建立工程的时候选择makefile工程。 2.将makefile文件和你写好的工程文件&#x…

Spring MVC遭遇checkbox的问题解决方式

Spring MVC遭遇checkbox的问题是&#xff1a;当checkbox全不选时候&#xff0c;则该checkbox域的变量为null&#xff0c;不能动态绑定到spring的controller方法的入參上&#xff0c;并抛出异常。 解决方式&#xff1a; 1、javascript方式提交&#xff0c;提交前拼提交參数串。拼…

[Redux/Mobx] redux和flux的区别是什么?

[Redux/Mobx] redux和flux的区别是什么&#xff1f; Flux: Store 包含状态和更改逻辑有多个 Store所有 Store 都互不影响且是平级的有单一调度器React 组件订阅 store状态是可变的 Redux: Store 和更改逻辑是分开的只有一个 Store带有分层 reducer 的单一 Store没有调度器的…

[转载]Python量化交易平台开发教程系列0-引言

原文出处&#xff1a;http://vnpy.org/2015/03/04/20150304_Python%E9%87%8F%E5%8C%96%E4%BA%A4%E6%98%93%E5%B9%B3%E5%8F%B0%E5%BC%80%E5%8F%91%E6%95%99%E7%A8%8B%E7%B3%BB%E5%88%970-%E5%BC%95%E8%A8%80/ 为什么用Python来开发量化交易平台 目前本人所在的公司一共有三款平台…

如何在 Ubuntu 12.04 Server 中安装图形用户界面

From: http://blog.163.com/crazy20070501126/blog/static/12865946520128301144531/ 使用ubuntu server安装lamp主机非常的方便&#xff0c;只要在安装系统的步骤中选择就是了 。但是很多时候我需要在图形界面下管理主机更加方便。今天的教程就是教大家安装图形界面。 【方法…

[Redux/Mobx] 在redux中,什么是store?

[Redux/Mobx] 在redux中&#xff0c;什么是store&#xff1f; 单一数据源&#xff0c;整个应用数据保存的地方 个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢迎大家一起讨论 主目录 与歌谣一起通关前端面试题

flask-whooshalchemy需要注意的一点

在学习mega—tutorial时全文搜索模块遇到了问题&#xff0c;那就是使用全文搜索查询出来的数据为空的列表&#xff0c;输出了sql语句后发现where后没有条件&#xff0c;困扰了许久&#xff0c;后来才发现是自己不细心&#xff0c;在进行全文索引时应该将数据库中的数据删除&…

[Redux/Mobx] Redux由哪些组件构成?

[Redux/Mobx] Redux由哪些组件构成&#xff1f; (这道题应该本意是Redux由哪些部分组成) State&#xff1a;Redux中的数据Reducer&#xff1a;这是Redux的核心&#xff0c;内部处理接受到action后到返回新的state的逻辑&#xff1b;reducer可以进行嵌套&#xff0c;一个store…

linux下添加用户的命令--useradd

From: http://hi.baidu.com/amenmen/item/010142991caf6bd87b7f0101 给你一整比较完整的方案你试下&#xff0c;看有用没。。 [rootlinux ~]# useradd [-u UID] [-g initial_group] [-G other_group] \ > -[Mm] [-c 说明栏] [-d home] [-s shell] username 参数&…

Maven实战(Maven+Nexus建立私服【Linux系统】)

准备工作 下载及配置Maven3&#xff1a;http://www.cnblogs.com/leefreeman/archive/2013/03/05/2944519.html 下载Nexus&#xff1a;http://nexus.sonatype.org/downloads/ 安装配置Nexus Nexus提供了两种安装方式&#xff0c;一种是内嵌Jetty的bundle&#xff0c;只要你有JRE…

[Redux/Mobx] 在React中你是怎么对异步方案进行选型的?

[Redux/Mobx] 在React中你是怎么对异步方案进行选型的&#xff1f; 小项目使用简单的redux-thunk方案,增加的代码量极少&#xff0c;只有两个api&#xff0c;上手成本低大项目使用基于redux-saga的dva.js&#xff0c;它简化了redux-saga的操作&#xff0c;使用上更加直观&…

青少年如何使用 Python 开始游戏开发

From: http://www.oschina.net/translate/beginning-game-programming-for-teens-with-python 这是一篇由教程团队成员Julian Meyer发表的文章,一个12岁的python开发人员。你可以在Google和Twitter上找到他。 你可曾想过如何创建视频游戏吗&#xff1f;它不像你想象的那么复杂…

[Redux/Mobx] Redux中异步action和同步action最大的区别是什么?

[Redux/Mobx] Redux中异步action和同步action最大的区别是什么&#xff1f; 同步action&#xff1a;执行了dispatch函数之后&#xff0c;对应的reducer纯函数立即得到执行&#xff0c;reducer执行完了之后&#xff0c;state立即就改变了&#xff0c;此时用store.getState函数&…

求解ax + by = c 这类方程

基础知识&#xff1a; 1.对于任意的axbyc&#xff0c; 如果我们知道有一组解x0, y0; 那么 x1 x0kb(bb/gcd(a,b)), y1 y0-ka(aa/gcd(a,b)); 求解ax by c 的过程如下&#xff1a; 1.首先我们利用Egcd求出axbyg(g gcd(a,b))的解。 利用此算法我们可以求出三个数g, x, y 2.然后…

ubuntu server修改系统时区和系统时间

From: http://gaoke0820.blog.163.com/blog/static/2166496520121118113743252/ 修改系统时区&#xff1a; sudo nano /etc/timezone 输入&#xff1a;Asia/Shanghai 也可以使用以下命令打开交互式界面来更改系统时区&#xff1a; sudo dpkg-reconfigure tzdata 修改系统时间&…

Vue3中的混入(mixins)

本文主要介绍Vue3中的混入&#xff08;mixins&#xff09;。 目录 一、在普通写法中使用混入&#xff1a;二、在setup写法中使用混入&#xff1a; 混入是Vue中一种用于在组件中共享可复用功能的特性。在Vue 3中&#xff0c;混入的使用方式有所改变。 一、在普通写法中使用混入…

[Redux/Mobx] redux它的三个原则是什么?

[Redux/Mobx] redux它的三个原则是什么&#xff1f; 单一数据源: 整个应用的只有一个store&#xff0c;store的state存在于唯一的object tree上state只读&#xff1a;state不可操作&#xff0c;要修改state&#xff0c;需要触发action&#xff0c;让reducer函数中返回一个全新…

android 打电话

startActivity(new Intent(Intent.ACTION_CALL, Uri.parse("tel:xxxxxxxxxxx")));转载于:https://www.cnblogs.com/hsji/p/5192191.html

[Redux/Mobx] redux-saga和redux-thunk有什么本质的区别?

[Redux/Mobx] redux-saga和redux-thunk有什么本质的区别&#xff1f; saga 自己基本上完全弄了一套 asyc 的事件监听机制。虽然好的一方面是将来可以扩展成 worker 相关的模块&#xff0c;甚至可以做到 multiple threads 同时执行&#xff0c;但代码量大大增加。如果只是普通的…