Android资源与属性备忘单

MercedesK05 7年前
   <p>几天前我偶然发现了我Android开发早期时制作的一份学习备忘单,是为理解如何处理Android资源和主题属性的语法而整理的。</p>    <p>令人意外的是,我发现它对现在的我非常有用,因此决定整理成更适合博客的形式并分享给大家。</p>    <p>知道我们今天要讨论的话题了,那么请看下面,通过xml布局设置一个view的background color的几种方法:</p>    <pre>  <code class="language-xml">android:background="@color/colorPrimary"    android:background="@com.myapp:color/colorPrimary"    android:background="?colorPrimary"    android:background="?attr/colorPrimary"    android:background="?com.myapp:attr/colorPrimary"    android:background="?com.myapp:colorPrimary"    android:background="?android:colorPrimary"    android:background="?android:attr/colorPrimary"</code></pre>    <p>够刺激,是吧?好吧,我希望可以把它拆解一下,这样就可以不那么吓人了。</p>    <h3>引用资源(resources) vs 引用样式属性(style attribute)</h3>    <p>先打断一下话题讲一下Android的基础,因为在进一步解释之前,理解 @ 和 ? 之间的区别是很重要的。</p>    <p>当我们使用@ -我们是引用一个实际的值(color, string, dimension,等等)。这个资源必须有具体的值,这种情况下我们知道自己处理的具体值。</p>    <p>比如</p>    <p>app/src/main/res/values/color.xml</p>    <pre>  <code class="language-xml"><?xml version="1.0" encoding="utf-8"?>    <resources>        <color name="colorPrimary">#3F51B5</color>  </resources></code></pre>    <p>因此当我们想在xml中引用它的时候(android:background="@color/colorPrimary"),不管这个activity是什么主题的,background都将被设置为#3F51B5 。</p>    <p>反之,当你看到? 标记-那就意味着我们在尝试引用一个style attribute ,其值取决于当前使用的主题。在特定的主题下我可以重写这个属性,因此不需要改变xml布局,只需应用恰当的主题就是了:</p>    <pre>  <code class="language-xml"><resources>        <style name="AppTheme" parent="Theme.AppCompat.Light">          <item name="colorPrimary">#F00</item>      </style>  </resources></code></pre>    <pre>  <code class="language-xml"><TextView        android:id="@+id/my_text"      android:layout_width="wrap_content"      android:layout_height="wrap_content"      android:background="?colorPrimary"/></code></pre>    <p>在这种情况下,我们询问Android:“嘿,把当前主题下定义的colorPrimary属性的值给我”。所以我们很难告诉你background到底会是什么颜色,因为它取决于这个布局所属的activity应用的主题。</p>    <h3>语法</h3>    <p>现在,让我们来看看引用资源的语法到底是什么样的。</p>    <p>引用resources (@)</p>    <p>@[包名:]资源类型/资源名</p>    <ul>     <li> <p>包名 - 可选项,即这个资源所属的包的名称(默认就是你app的包名);预留的包-android,用于与系统一起发布的资源。</p> </li>     <li> <p>资源类型 - R的子集,即资源的类型(attr, color, string, dimen,等等)</p> </li>     <li> <p>资源名 - 我们要引用的资源的名称</p> </li>    </ul>    <p>让我们先举2个例子:</p>    <pre>  <code class="language-xml">android:background="@color/colorPrimary"    android:background="@com.myapp:color/colorPrimary"</code></pre>    <p>这两个都是引用相同的资源,因为默认包名就是自己app的包名,所以可以不写出来:</p>    <ul>     <li> <p>package(可选) = com.myapp</p> </li>     <li> <p>资源类型 = color</p> </li>     <li> <p>资源名 = colorPrimary</p> </li>    </ul>    <p>你可能会想,安卓不是预先定义了一些系统级别的资源吗?是的,比如可以这样引用一些内置的颜色:</p>    <pre>  <code class="language-xml">android:background="@android:color/holo_orange_dark"</code></pre>    <p>这个例子拆解开来就是:</p>    <ul>     <li> <p>package = android - 引用内置的资源</p> </li>     <li> <p>资源类型 = color</p> </li>     <li> <p>资源名 = holo_orange_dark</p> </li>    </ul>    <p>请注意:</p>    <p>现在,许多开发者都使用AppCompat(如果你还没有,那么建议你这样做),而AppCompat通常定义了自己的资源。虽然AppCompat属于谷歌自己发布的lib,但是它并不是系统的一部分。实际上,那些资源整合到了你的app中,因此不需要使用android关键字来引用。</p>    <p>例子:</p>    <pre>  <code class="language-xml">android:background="?selectableItemBackground"</code></pre>    <p>这里,即使我们app中并没有自定义的属性名selectableItemBackground(注意这里没有使用 android: 前缀),我们仍然可以引用它,因为我们通过AppCompat把它“添加”到了我们的app中。</p>    <p>引用样式属性(?)</p>    <p>你猜怎么着,它的语法相当类似于引用resources:</p>    <p>?[包名:][资源类型/]资源名称</p>    <p>只是有点小区别:</p>    <p>引用样式属性的时候唯一允许的资源类型是attr。所以实际上Android打包工具允许我们省略资源类型,因此实际上它是一个可选项。</p>    <p>所以从Android的角度来看,下面的表述方式其实完全是一样的:</p>    <pre>  <code class="language-xml">android:background="?com.myapp:attr/colorPrimary" //verbose format    android:background="?com.myapp:colorPrimary" //attr is skipped since its optional    android:background="?attr/colorPrimary" //package is skipped since its optional    android:background="?colorPrimary"  // package & attr is skipped</code></pre>    <p>就如你看到的那样,其实语法是超级简单的,再也不会困惑了!</p>    <p> </p>    <p>来自:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2017/0324/7720.html</p>    <p> </p>