深入了解Android视图构造函数

来源:互联网 发布:c 编程 文件被截断 编辑:程序博客网 时间:2024/05/20 01:38

本文原创,转载请以链接形式注明地址:http://blog.csdn.net/xiaole0313/article/details/52493213

推荐阅读

1、Android面试经验大解密

2、Android的viewHolder模式解剖
3、Android中必须学习的七大开源项目(开发项目必看)
4、如何自学Android, 教大家玩爆Android(成为大神必看)
5、2016 Google hosts 持续更新【更新 于:2016-08-27】(免费翻墙必备)
6、Android面试经验总结(面试成功必备)
7、Android Studio 个性化设置(装逼必备)

8、Android Studio 2.2 正式起航(玩爆Android Studio 2.2必备)

Android Studio 2.2 新功能实例代码:
Android Studio 2.2新功能实例源码(玩爆Android Studio 2.2必备)


原文链接

作者:Dan Lew

译者:David

我经常看到混乱在Android视图构造函数。为什么有四个?每个参数做什么工作?我需要实现什么构造函数?

TL;博士

如果你只是想快速,实用的建议,这里有几个不错的准则:

  • 使用View(Context)创建Views的代码。
  • 覆盖View(Context, AttributeSet)膨胀时,Views从XML。
  • 忽略休息,因为你可能不会需要他们。

对于我那些还在 - 让我们在跳水。

构造函数的参数

在最有可能有四个构造函数的参数。一个简短的总结:

  • Context-使用视图(上下文)创建视图的代码。
  • AttributeSet - 在XML属性(XML从膨胀时)。
  • int defStyleAttr-默认样式应用到View(在主题定义)。
  • int defStyleResource-默认样式应用到View,如果defStyleAttr是未使用的。

除了Context​​,其它参数只用于配置的初始状态View基于XML属性(从布局,风格和主题)。

属性

让我们来谈谈你如何定义有效的XML属性开始。这是一个基本ImageView的XML:

<ImageView    android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:src="@drawable/icon"  />

你有没有想过在那里layout_widthlayout_heightsrc从何而来?这不是凭空; 你居然明确地声明这些属性的东西,系统应通过处理<declare-styleable>。例如,这里的地方src被定义为:

<declare-styleable name="ImageView">    <!-- Sets a drawable as the content of this ImageView. -->  <attr name="src" format="reference|color" />  <!-- ...snipped for brevity... --></declare-styleable>  

declare-styleable生成一个R.styleable.[name]外加R.styleable.[name]_[attribute]每个属性。例如,在上述产生R.styleable.ImageViewR.styleable.ImageView_src

什么是这些资源?基座R.styleable.[name]是所有的属性资源,该系统使用查找属性值的阵列。每个R.styleable.[name]_[attribute]仅仅是一个索引数组,这样就可以一次检索所有属性,然后逐个查找每个值。

如果你觉得它像一个游标,你可以考虑R.styleable.[name]为列清单查询和每R.styleable.[name]_[attribute]一个列索引。

欲了解更多有关declare-styleable,这里的官方文档上创建自己的。

AttributeSet

我们上面写的XML是考虑到View作为一个AttributeSet

通常你不访问AttributeSet直接,而是使用Theme.obtainStyledAttributes()。这是因为原始属性常常需要解决的参考和应用样式。例如,如果你定义style=@style/MyStyle在XML,此方法可以解决MyStyle,并增加了其属性的组合。最后,obtainStyledAttributes()返回一个TypedArray你可以用它来 ​​访问属性。

大大简化,这个过程是这样的:

public ImageView(Context context, AttributeSet attrs) {    TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ImageView, 0, 0);  Drawable src = ta.getDrawable(R.styleable.ImageView_src);  setImageDrawable(src);  ta.recycle();}

在这种情况下,我们传递两个参数obtainStyledAttributes()。第一是AttributeSet attrs,从XML属性。第二个是数组R.styleable.ImageView,它告诉哪些属性,我们要提取(以及以什么顺序)的方式。

随着TypedArray我们回来,我们现在可以访问单个属性。我们需要使用R.styleable.ImageView_src使我们正确地索引数组中的属性。

(回收TypedArrays是很重要的,也因此我把它样品以上。)

通常你一次提取多个属性。事实上,实际的ImageView实施远比什么上面所示(因为更为复杂的ImageView本身有它关心更多的属性)。

你可以阅读更多关于提取属性的官方文档。

主题属性

阿里纳斯,完整性:本AttributeSet不是我们得到了我们的价值的唯一场所使用时,从obtainStyledAttributes()最后一节。属性也可以存在于主题。

这种情况很少了发挥作用View的通胀,因为你的主题不应该设置喜欢的属性src,但如果你用它可以起到一定的作用obtainStyledAttributes(),用于检索主题的属性(这是有用的,但这篇文章的讨论范围之内)。

默认样式属性

您可能已经注意到,我曾经0在过去的两个参数obtainStyledAttributes(),他们实际上是两个资源引用- defStyleAttrdefStyleRes。我打算把重点放在第一个在这里。

defStyleAttr是,到目前为止,对于最令人困惑的参数obtainStyledAttributes()。根据它的文档:

在包含于,对于TypedArray提供默认值的样式资源的引用当前主题的属性。

哇,这是一个拗口。在简单的英语,这是一个方法,能够定义一个基本样式为所有Views特定类型的。例如,你可以设置textViewStyle你的主题,如果你想修改所有应用的TextViews一次。如果不存在,你必须手动每个样式TextView代替。

让我们通过它的实际工作原理,使用TextView作为一个例子。

首先,它是一个属性(在此情况下,R.attr.textViewStyle)。这里就是Android平台的定义textViewStyle

<resources>    <declare-styleable name="Theme">    <!-- ...snip... -->    <!-- Default TextView style. -->    <attr name="textViewStyle" format="reference" />    <!-- ...etc... -->  </declare-styleable></resource>  

同样,我们使用declare-styleable,但这次来定义可以在主题中存在的属性。在这里,我们说textViewStyle是一个reference-那就是,它的价值仅仅是一个资源的引用。在这种情况下,它应该是一个风格的基准。

接下来我们要设置textViewStyle在当前主题。默认的Android主题如下:

<resources>    <style name="Theme">    <!-- ...snip... -->    <item name="textViewStyle">@style/Widget.TextView</item>    <!-- ...etc... -->  </style></resource>  

然后,主题有您要设置ApplicationActivity,通常通过清单:

<activity    android:name=".MyActivity"  android:theme="@style/Theme"  />

现在,我们可以使用它obtainStyledAttributes()

TypedArray ta = theme.obtainStyledAttributes(attrs, R.styleable.TextView, R.attr.textViewStyle, 0);  

最终的结果是,不是由限定任何属性AttributeSet与该样式填充textViewStyle引用。

唷!除非你是铁杆,你并不需要了解所有这些实现细节。这主要是有这样的Android框架能够让你定义的各种基本样式Views在你的主题。

默认样式资源

defStyleRes比它的兄弟简单得多。这仅仅是一个样式资源(即@style/Widget.TextView)。通过主题没有复杂的间接。

从风格属性defStyleRes应用于如果defStyleAttr是未定义的(无论是作为0或它未在主题设置)。

优先权

现在,我们有一堆的方法来推导通过属性的值obtainStyledAttributes()。下面是他们的优先顺序,从最高到最低:

  1. 在定义的任何值AttributeSet
  2. 在定义的样式资源AttributeSet(即style=@style/blah)。
  3. 由指定的默认样式属性defStyleAttr
  4. 由指定的默认样式资源defStyleResource(如果没有defStyleAttr)。
  5. 价值观的主题。

换句话说,你直接在XML中设置的任何属性将首先使用。但也有其他地方的这些属性可以,如果你不自行设置检索各种。

查看构造

这篇文章应该是约View构造,对不对?

有四种人总,每一个加入一个参数:

View(Context)View(Context, AttributeSet)View(Context, AttributeSet, defStyleAttr)View(Context, AttributeSet, defStyleAttr, defStyleRes)  

重要提示:在最后一个21 API加入,让你,除非你有minSdkVersion 21,你应该避免它现在。(如果您想使用defStyleRes只是叫obtainStyledAttributes()自己,因为它总是被支持。)

级联,所以如果你调用一个,最终调用(通过超级)。级联也意味着你只需要覆盖您所使用的构造函数。一般来说,这意味着你只需要实现前两个(一个用于代码构造,另一个用于XML通货膨胀)。

我通常设置我的自定义Views如下所示:

SomeView(Context context) {    this(context, null);}SomeView(Context context, AttributeSet attrs) {    // Call super() so that the View sets itself up properly  super(context, attrs);  // ...Setup View and handle all attributes here...}

在这两个参数的构造函数,你可以使用obtainStyledAttributes()任何你想要的方式。实现一个默认样式的快速方法是只提供defStyleRes给它; 这样你就不需要经过痛苦的是对接defStyleAttr(这更多的是一种框架,工具和通常没必要为一个单一的应用程序)。

无论如何,我希望这不仅有助于你的理解来看,构造函数还时检索属性是如何看待建筑!

【GitHub】https://github.com/xiaole0310
【csdn博客】http://blog.csdn.net/xiaole0313
【新浪微博】http://weibo.com/u/5439466748
【知乎】http://www.zhihu.com/people/yang-shou-le
【简书】http://www.jianshu.com/users/7334e04e7e08/latest_articles
【Email】ysle0313@gmail.com

Android Studio 2.2 新功能实例代码:
Android Studio 2.2新功能实例源码(玩爆Android Studio 2.2必备)


1 0
原创粉丝点击