Android应用程序使用View和ViewGroup来构建用户界面,它们都是继承自View类(或其子类)例如:Button、TextView、EditText等。各类View搭配上Style和Animation可以编织出非常丰富的UI,足以应付绝大部分的需求。但有时候我们也需要一些特别的View ,以带给用户与众不同的体验。

在此我打算写一个大长篇都是关于android View的,主要内容为:SDK上部分文章翻译(英文水平有限尽请拍砖);自定义的View、android源代码分析、开源View代码分析;各类App应用的界面模仿;以理论+代码示例+实践 的方式指导本系列博文的撰写。

——因为本人水平有限,而且写系列经常虎头蛇尾,所以这个系列就不写总目录了。如果哪天您发现本系列不在更新,而我又开始了另一个“大长篇”,那么请扔鸡蛋吧。(但是我们不退票!)

——出于前车之鉴,本系列中的源码将不提供打包服务。

言归正传,在我们编写android程序时一般是自定义以一个类继承自Activity 并且重写onCreate方法:

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}

setContentView()方法包含多个重载其中一个便是“setContentView(View view)”,也就是说可以直接通过一个View的实例来构建内容。我们尝试放入一个TextView,上面的代码变成了这样:

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.main);

TextView sayHello = new TextView(this);
sayHello.setText("Hello world! I'm a TextView.");
setContentView(sayHello);

}

运行这段代码,在模拟器上你应该可以看到以下结果:

如此简单不是吗?好吧让我们再让它丰富点:

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.main);
//TextView sayHello = new TextView(this);
//sayHello.setText("Hello world! I'm a TextView.");
setContentView(new SayHello(this));

}


class SayHello extends View{

public SayHello(Context context) {
super(context);
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint mPaint=new Paint() ;
mPaint.setTextSize(22f);
mPaint.setColor(Color.RED);
canvas.drawText("Hello world! I'm a TextView.", 0, 100, mPaint);
}
}

这次我们自定义了一个局部类SayHello 继承自View并且重写了 onDraw 方法(需要注意的是由于View没有无参构造函数所以我们为其指定实现哪一个构造函数)。在onDraw 方法中我们定义了一个Paint,现在你只需要理解它有绘画的功能即可,那么它要在哪里绘画呢?答案就是在Canvas上,可以把Canvas理解成画布。

现在我们设置mPaint的字体大小为22F 颜色为红色,然后在画布上写出“Hello world。。。”这几个红色的字,并且把onCreate里的setContentView 为setContentView(new SayHello(this));
最后在模拟器上你应该看到的是:

so cool! 不是吗?

不!不对,我们在Android的开发View不是这样的,它应该是通过 Xml.......@##¥%

好吧 让我们再把例子修改一下。

首先我们将SayHello 类提取出来,并且将它放入一个单独的类文件中,接下来就是重点:我们需要添加另外的一些构造函数以便给View传递参数,最好你看到的SayHello 类应该是这样的:

public class SayHello extends View {

public SayHello(Context context)
{
super(context);
}

public SayHello(Context context, AttributeSet attrs) {
this(context, attrs,0);
}

public SayHello(Context context, AttributeSet attrs,int defStyle)
{
super(context, attrs, defStyle);
}


@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint mPaint=new Paint() ;
mPaint.setTextSize(22f);
mPaint.setColor(Color.RED);
canvas.drawText("Hello world! I'm a TextView.", 0, 100, mPaint);
}

}

这里简单讲解一下新增的构造函数的作用,在新的构造函数中为View的构造函数传递了AttributeSet attrs,int defStyle两个参数,这代表着该View可以通过XML 来创建并且接受Style来设定样式。等到相关博文时会再具体讲解。

接下来,我们恢复Activity类里的onCreate方法让它看起来像这个样子:

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);


}

和一开始没啥两样对吧。

最后我们需要去修改布局文件main 在文件里加入以下 xml标签:

<com.××××.customview.SayHello
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
</com.××××.customview.SayHello>

(注意××××,代表SayHello类所在的包,这里需要的是全名)。

然后再次运行程序,你应该看到以下结果:

是不是和我们平常定义View时很像了?

你感觉得还不够,还缺乏些什么?

好吧,你很聪明,我们的Text应该是在XML上通过某个属性配置而成的,而不是写在代码里!

为了将SayHello的属性暴露到XMl上首先我们需要在res/value 文件夹下新建一个XMl文件,命名为:atts。

在里面添加如下代码:

<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="SayHello">
<attr name="content" format="string"></attr>
<attr name="text_color" format="color"></attr>
</declare-styleable>

</resources>

需要注意的是这里是没有智能提示的

然后我们需要修改SayHello类,还记得那个AttributeSet吗?我们将通过它来获取XML配置上的属性值。修改后的SayHello类代码是这样的:

private int mColor;
private String mContent;

public SayHello(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray typeArray = context.obtainStyledAttributes(attrs,
R.styleable.SayHello);
mColor=typeArray.getColor(R.styleable.SayHello_text_color, 0XFF00FF00);
mContent=typeArray.getString(R.styleable.SayHello_content);

}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint mPaint = new Paint();
mPaint.setTextSize(22f);
mPaint.setColor(mColor);
canvas.drawText(mContent, 0, 100, mPaint);
}

现在可以去XML上为哥哥属性添加值了,不过先别着急我们的得将命名空间告诉它。

在布局文件的根源是上(通常是Layout)添加: xmlns:SayHello="http://schemas.android.com/apk/res/com.XXXX.customview"

SayHello 可以为您任意想要定义的名字,它将作为属性的前缀使用就像android:Layout 一样而我们的为:SayHello:content,后半段http://schemas.android.com/apk/res/为固定值,紧接着的是你整个APP的包命名,你不知道自己包名称?赶去去 AndroidManifest.xml文件中看看吧(注意该包名需要保持和manifest中的 package 保持一致,否则会提示无法找到XML属性)。

最后我们终于可以在XML上定义自己想要的字体颜色的内容了:

<com.XXXX.customview.SayHello
android:layout_width="fill_parent"
android:layout_height="wrap_content"
SayHello:text_color="#1212f0"
SayHello:content="this is a xml attr view">
</com.XXXX.customview.SayHello>

运行程序您应该会看到以下结果:

这就是我们View 一般的定义方式和过程。

——启航。

//本笔记从 麦库中复制过来, 图片连不上,请见谅

更多相关文章

  1. C语言函数的递归(上)
  2. Android(安卓)更新UI的两种方法——handler和runOnUiThread() -
  3. Android(安卓)APP之间共享SharedPreference
  4. android.widget.Toast——快显信息
  5. Android(安卓)ImageSpan与TextView中的text居中对齐问题解决(无论
  6. Android使用Google提供的地图实现定位时LocationListener的各个
  7. lambda表达式介绍以及Android(安卓)Studio引入lambda
  8. Android(安卓)SettingProvider详解
  9. Android(安卓)Studio 中文乱码问题

随机推荐

  1. android launcher之管理对象LauncherAppl
  2. Android(安卓)时间选择器 PickerView,的详
  3. android 调试技巧
  4. Android(安卓)SDK最新问题
  5. Android(安卓)Studio部分汉化中文包
  6. Android获取当前的城市名的方法
  7. Android(安卓)Swich的基本用法,保存状态等
  8. android中利用 ViewPage 实现滑动屏
  9. Android(安卓)PinnedSectionListView实现
  10. https://maven.google.com 无法访问,无法