这节我们主要讲解自定义View的其中的三个步骤:设计我们的所需的属性、实现我们的View和在xml中引用我们的View,注重为什么这样设计的思想。
首先,我们要了解google是怎么实现一个控件的,比如我们最熟悉的LinearLayout,我们使如何使用它的呢?我们会在XML文件中定义一个LinearLayout,再为它写上相应的属性,比如:android:layout_width
和android:layout_height
等,这样我们就可以使用LinearLayout,如下图:
但是google使如何定义它的源文件的呢?就是为什么这样写就可以使用一个控件。我们知道LinearLayout是继承ViewGroup,它重写了ViewGroup的一些方法来满足自己的一些需求,但是这些属性又是从哪里来的呢,我们可以从android源码的attrs.xml文件中可以看到下面几句话:
我们首先需要一个atts.xml文件,用来配置我们所需要的属性,然后我们需要重写控件来满足自己的要求,最后一步就是在xml文件使用我们的控件。下面以一个小案例具体实现以上自定义控件的步骤,实现效果图文章最后图。
我们该怎么做
-
设计我们所需要的属性
这里我们将TobBar分为三个部分,中间显示标题,还有左右button。为标题我们设计了 标题的颜色,大小和文本,为左右button设计了button颜色,button文本和背景颜色属性。
-
实现我们的“View”
这里TobBar继承自RelativeLayout ,代码如下:
public class TopBar extends RelativeLayout {
private Button leftButton, rightButton;
private TextView tvTitle;
private int leftTextColor;
private Drawable leftBackgroung;
private String leftText;
private int rightTextColor;
private Drawable rightBackgroung;
private String rightText;
private float titleTextSize;
private int titleTextColor;
private String title;
private RelativeLayout.LayoutParams leftParsms,rightParsms,titleParams;
//下面我们就需要将上面的是三个控件放进我们的ViewGroup中去
//实例化左按钮的布局属性
leftParsms = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
//设置左按钮靠左显示
leftParsms.addRule(RelativeLayout.ALIGN_PARENT_LEFT,TRUE);
//将左按钮添加到本自定义控件中
addView(leftButton,leftParsms);
//同上
rightParsms = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
rightParsms.addRule(RelativeLayout.ALIGN_PARENT_RIGHT,TRUE);
addView(rightButton,rightParsms);
titleParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,LayoutParams.MATCH_PARENT);
titleParams.addRule(RelativeLayout.CENTER_IN_PARENT,TRUE);
addView(tvTitle,titleParams);
}
}
* 引用我们View
我们首先看一下怎么使用一个系统控件的,TextView为例,如下代码:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
由上面设置一个系统控件为例,我们可以得知,首先我们要声明一个控件名称,接着下面便是 android:来引用一个属性,并给它赋值。其实这个android就是布局文件头部的引用文件,即下面一行代码:
xmlns:android="http://schemas.android.com/apk/res/android"
所以我们根据系统为例来引用我们自定义的组件。
使用自定义的控件的属性首先添加命名空间,如下:
xmlns:custom="http://schemas.android.com/apk/res-auto"
其中custom可以任意指定,但不能与系统的命名空间相同,在android studio中如上 用res-auto,在eclipse中res后需要完整的包名。引用自定义控件代码如下:
<com.example.mytopbar.TopBar
android:id="@+id/topbar"
android:layout_width="match_parent"
android:layout_height="40dp"
custom:leftBackground="#16c7ca"
custom:leftText="Back"
custom:leftTextColor="#FFFFFF"
custom:rightBackground="#16c7ca"
custom:rightText="More"
custom:rightTextColor="#FFFFFF"
custom:title="自定义标题"
custom:titleTextColor="#123412"
custom:titleTextSize="10sp">
</com.example.mytopbar.TopBar>
---
**注:这里有个地方需要注意一下,就是AS中Button默认大写问题。如果在布局文件中添加一个Button组件**
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="100sp"
android:text="aaaaa"
android:textSize="20sp" />
**结果如下图:**
![](http://upload-images.jianshu.io/upload_images/3045727-5866ae38e59622e9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
**本来我们设置的text属性为“aaaaa”,但是结果确实大写“AAAAA”,这是因为android主题Theme.AppCompat中,在5.0以上的API的时候,Button的默认属性是字母全部大写。解决方案:**
* 使用5.0以下的API,则不会有这个问题
* 在不想大写的控件中添加属性(关闭全部大写属性):
android:textAllCaps="false"
(目测自定义的组件便没有这个属性,只能用第一种方法或者下面的一种方法)
* 如果在其他控件中,比如我们上面的自定义组件中有自定的属性--leftText、rightText,在该组件中就没有上面所说的textAllCaps属性,那么我们也可以在values-->style.xml文件中style块内添加下面一行代码:
<item name="android:textAllCaps">false</item>
这样我们就可以把所有的组件都不会自动大写
---
做完以上的工作,我们TopBar的静态部分已经完成,如下图:
![](http://upload-images.jianshu.io/upload_images/3045727-dffef0c4a240ae11.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
下面实现Button的点击事件,就不在详述了,读者可以自行实现一些点击事件。本文最后附上工程源码(其实是一个Android UI模板设计的源码),里面简单的实现了一些点击事件,读者可以自行理解。
**[工程源码](http://download.csdn.net/detail/cs9426478/9652456)**