@android, ?attr/ 和 ?android 的区别

个人总结:把attr当做变量的声明,使用的时候需要再不同的Theme中定义,也就是赋值。最后使用的时候使用?attr/变量名,引用相关具体值。

摘自:Android中 @和?区别以及?attr/**与@style/**等的区别:
https://blog.csdn.net/xx326664162/article/details/64125654?depth_1-utm_source

@和?的区别

 style="?android:attr/progressBarStyleHorizontal"
 style="@android:style/Widget.ProgressBar.Horizontal"
  
  
  • 1
  • 2

在设置style的时候既可以使用@也可以使用?,他们有什么区别呢??

  • 使用@表示使用固定的style,而不会跟随Theme改变,这style可以在对应的style.xml中找到。
  • 使用?表示从Theme中查找引用的资源名,这个google叫预定义样式,用在多主题时的场景,属性值会随着主题而改变。(?需要和attr配合使用)

例如上面的progressBarStyleHorizontal:
查看\platforms\android23\data\res\values\themes.xml文件,可以看到在不同的theme中,progressBarStyleHorizontal引用的style是不同的。看下面的示例:

在Theme中:

<item name="progressBarStyleHorizontal">@style/Widget.ProgressBar.Horizontal</item>
  
  
  • 1

在Theme.Holo中为

 <item name="progressBarStyleHorizontal">@style/Widget.Holo.ProgressBar.Horizontal</item>
  
  
  • 1

style和attr使用区别

style

<!--使用自定义的style-->
@style/Widget.AppCompat.ProgressBar.Horizontal
<!--使用系统自带的style-->
@android:style/Widget.ProgressBar.Horizontal
  
  
  • 1
  • 2
  • 3
  • 4

attr

<!--使用自定义的  ,下面两种方式等效-->
"?attr/属性"
"?属性"
<!--使用系统自带的 ,下面两种方式等效-->
"?android:属性"
"?android:attr/属性"

  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

另外:

当引用系统自带的style和attr时

"@android:style/主题""@style/android:主题"等同

"?android:attr/属性""?attr/android:属性"等同
  
  
  • 1
  • 2
  • 3

自定义随主题改变的属性

个人总结:把attr当做变量的声明,使用的时候需要再不同的Theme中定义,也就是赋值。最后使用的时候使用?attr/变量名,引用相关具体值。

1、 如果是自定义控件,请在style.xml中或attrs.xml中声明属性:(声明后,才可以在xml文件中该控件中使用该属性)

<declare-styleable name="SunnyAttr">
    <attr name="sunnyTextColor" format="reference"/>
    <attr name="sunnyBgColor" format="reference"/>
    <attr name="sunnyTextColorWhite" format="color"/>
    <attr name="sunnyTextColorRed" format="reference"/>
    <attr name="textColor" format="reference"></attr>
</declare-styleable>
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

如代码第五行所示,必须指明format为reference。这样自定义控件的属性就可以在xml使用,如果不明白,查看这里

2、 在Theme中使用自定义的属性,可以在多个主题中定义不同的属性值(在Theme中赋值,但是要在AndroidManifest.xml中使用该Theme才能生效,否则会报错。最后获取的值就是从这儿获取的。具体的值是引用的下面3的)

<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    <item name="sunnyTextColorRed">@color/sunnyTextColorRed</item>
</style>
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

3、 在对应的属性color,drawable等里面加入相应的资源(被引用的属性资源。)

<color name="sunnyTextColorRed">#FFFF0000</color>
  
  
  • 1

4、这样就可以在xml中使用自定义控件的自定义属性,这个属性会随着主题而改变:(引用2处)

见下面第五行代码

<com.smartbracelet.sunny.sunnydemo3.SunnyTextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:text="设置界面"
    app:sunnyTextColor="?attr/sunnyTextColorRed"
    />
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

https://blog.csdn.net/s13383754499/article/details/102568854

1,@android: 引用安卓内建的系统资源

除了引用自己应用中的资源外,我们还可以通过指定引用时的包名为 android 来获取安卓平台下的一些系统资源,举个例子:

android:background=“@android:drawable/ic_menu_delete
  
  

我们知道当新建一个项目的时候,必须在 gradle 中设置 compileSdkVersion 来指定编译我们应用的 SDK 版本,这也决定了我们能调用哪个 level 的 API,同时也表明了哪个 level 的系统资源可供我们使用,比如如果指定的 compileSdkVersion 是 27,那么我们调用的就是 Android 8.1 下的系统资源。

2,?attr/: 引用应用内的属性资源

通过这种方式可以让我们间接地使用应用内的某些资源。我们知道当我们自定义View的时候,一般会需要自定义一些属性资源,通常我们会在 values/ 文件夹下建一个 attrs 文件,在这里保存一些我们自己的 style 属性,其实这些属性就可以通过 ?attr/ 这种方式来引用了。比如我在 styles 里定义了一个属性:

<attr name="colorReallyGreen" format="color"/>
  
  

 定义完之后,我就可以直接在 layout 中通过引用的方式去使用这个属性了:

android:background="?attr/colorReallyGreen"
  
  

当然,要想让该属性起作用还需要在 Theme 下指定值:

                                                   在当前 Theme 下为自定义属性赋值

另外,由于在 layout 中,可以自动识别出当前所需的是属性资源,所以可以省略 attr/ 而直接使用 ?colorReallyGreen 就可以了。 

3,?android: 引用系统内建的属性资源

了解了前两种资源引用的方式后,?android 这种引用资源的方式也就不难理解了。与 ?attr/ 类似,通过这种方式可以直接访问到安卓内建的属性资源,只不过是省略了 attr/ 而已。比如给 TextView 引用一个系统内的 style buttonStyleSmall

<TextView
    style="?android:buttonStyleSmall"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="You Are Beautiful" />

然后 TextView 就变成了这样:

                        引用了安卓内建属性作为 style 的 TextView

当然如果你尝试去掉 android 包名之后,发现该属性还是可以起作用,说明应用内也是可以引用这个资源的。那么这是不是意味着绝大部分属性资源都不需要加 android 包名呢?其实我觉得是这样的,因为加了包名之后其实限制反而会更多,比如有些内建属性资源是针对某个 API level 以上的 Android 平台才可以使用的,当然这也与你当前使用的 Theme 有关。

发布了272 篇原创文章 · 获赞 165 · 访问量 21万+

猜你喜欢

转载自blog.csdn.net/qq_32534441/article/details/104852107