【Android】res 资源目录及相关技术详解

415 阅读6分钟

res资源目录简介

在 Android 项目中,res目录是存放应用资源的核心位置,系统会为其中的资源自动生成对应的 ID,便于在代码中引用。其主要结构及用途如下:

  • res/drawable/ :存放图形资源,如位图(.png/.jpg)、XML 定义的图形(shape/selector/ 动画等)。
  • res/layout/ :存放布局文件(.xml),定义界面组件的排列方式。
  • res/values/ :存放常量值,如字符串(strings.xml)、颜色(colors.xml)、尺寸(dimens.xml)、样式(styles.xml)等。
  • res/mipmap/ :存放应用图标(.png),按不同屏幕密度(mdpi/hdpi/xhdpi 等)分类,适配不同设备。
  • res/raw/ :存放原始文件,如音频、字体等,读取时通过Resources.openRawResource()获取。
  • res/anim/ :存放补间动画(tween animation)定义文件。
  • res/transition/ :存放界面转场动画定义文件(Android 4.4+)。

shape绘制和使用

shape是 Android 中通过 XML 定义的几何图形,常用于自定义 View 的背景、边框等。

1. shape基本结构

在 drawable 目录下创建 XML 文件

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape=["rectangle"|"oval"|"line"|"ring"]>

    <!-- 填充颜色 -->
    <solid android:color="@color/colorPrimary" />

    <!-- 边框 -->
    <stroke
    android:width="2dp"
    android:color="@color/black"
    android:dashWidth="5dp"  <!-- 虚线线段长度仅line/ring有效 -->
    android:dashGap="3dp" /> <!-- 虚线间隔长度,仅line/ring有效 -->

    <!-- 圆角(仅rectangle有效) -->
    <corners
        android:radius="5dp"        <!-- 统一圆角半径 -->
        android:topLeftRadius="2dp" <!-- 单独设置各角圆角 -->
        android:topRightRadius="2dp"
        android:bottomLeftRadius="2dp"
        android:bottomRightRadius="2dp" />

    <!-- 内边距 -->
    <padding
        android:left="10dp"
        android:top="10dp"
        android:right="10dp"
        android:bottom="10dp" />

    <!-- 渐变(线性/径向) -->
    <gradient
        android:type=["linear"|"radial"|"sweep"]
        android:startColor="@color/color1"
        android:endColor="@color/color2"
        android:gradientRadius="50dp"  <!-- 径向渐变半径 -->
        android:angle="45"             <!-- 线性渐变角度,0为从左到右,90为从下到上 -->
        android:useLevel="false" />    <!-- 是否用于LevelListDrawable,默认false -->
</shape>

2. 应用示例

  1. drawable/btn_background.xml中定义 shape:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">

    <solid
        android:color="#89E44C" />

    <corners
        android:radius="5dp"/>

    <stroke
        android:width="2dp"
        android:color="#000000" />
</shape>
  1. 在布局文件中引用:
<android.widget.Button
    android:id="@+id/btn_background1"
    android:layout_width="200dp"
    android:layout_height="50dp"
    android:background="@drawable/btn_garound"/>

Android Button/TextView 背景增添动感效果

1. 使用渐变(gradient)实现动态视觉效果

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <gradient
        android:type="linear"
        android:startColor="#FF0000"
        android:endColor="#0000FF"
        android:angle="45" />

    <corners
        android:radius="10dp" />
</shape>

2. 结合selector实现点击动效

<!-- drawable/button_selector.xml -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 点击时的背景 -->
    <item android:state_pressed="true">
        <shape>
            <solid android:color="#FF0000" />
            <corners android:radius="8dp" />
        </shape>
    </item>
    <!-- 正常状态的背景 -->
    <item>
        <shape>
            <solid android:color="#0000FF" />
            <corners android:radius="8dp" />
        </shape>
    </item>
</selector>

3. 使用动画背景(帧动画)

  1. drawable/button_anim.xml中定义帧动画:
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="true"> <!-- 设置为 true 表示动画只播放一次,false 表示循环播放 -->

    <!-- 添加帧,每帧显示一张图片 -->
    <item android:drawable="@drawable/frame1" android:duration="200" /> <!-- 每帧显示 200 毫秒 -->
    <item android:drawable="@drawable/frame2" android:duration="200" />
    <item android:drawable="@drawable/frame3" android:duration="200" />
    <item android:drawable="@drawable/frame4" android:duration="200" />
    <item android:drawable="@drawable/frame5" android:duration="200" />

</animation-list>
Button btn = findViewById(R.id.btn_background4);
AnimationDrawable animationDrawable = (AnimationDrawable) btn.getBackground();
animationDrawable.start();

Android使用第三方字体

1. 准备字体文件

  • 将字体文件(.ttf/.otf)放入assets/fonts/目录(若没有则创建assets文件夹)。

2. 加载并应用字体

// 在Activity/Fragment中 
TextView textView = findViewById(R.id.text_view); 
// 从assets加载字体 Typeface typeface = 
Typeface.createFromAsset(getAssets(), "fonts/MyFont.ttf"); 
// 应用字体 
textView.setTypeface(typeface); 

// 或在XML中通过app:fontFamily引用(需使用AppCompatTextView)
<!-- 布局文件中 -->
<androidx.appcompat.widget.AppCompatTextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="自定义字体"
    app:fontFamily="@font/my_font" /> <!-- @font需对应res/font/目录下的字体资源 -->

3. 在 res/font 目录中定义字体资源(Android 8.0 + 推荐方式)

  1. res/下创建font目录,放入字体文件my_font.ttf
  2. res/font/my_font.xml中定义:
<font-family xmlns:android="http://schemas.android.com/apk/res/android">
    <font
        android:font="@font/my_font"
        android:fontStyle="normal"
        android:fontWeight="400" />
</font-family>

Android 适配问题解决方案

1. 屏幕尺寸与密度适配

  • 使用 dp/sp 单位dp(密度无关像素)用于尺寸,sp(缩放无关像素)用于文字,系统会根据屏幕密度自动转换为像素。

  • 配置多维度资源:在res/下创建不同后缀的资源目录,如:

    • drawable-mdpi/drawable-hdpi/drawable-xhdpi/:适配不同密度屏幕。
    • layout-sw600dp/:适配最小宽度≥600dp 的平板设备。
  • 使用 ConstraintLayout:通过约束关系实现响应式布局,减少对多布局文件的依赖。

2. 版本兼容性适配

  • 使用 AppCompat 库:通过androidx.appcompat.widget.AppCompatTextView等组件兼容低版本特性(如字体、动画)。
  • 动态权限处理:针对 Android 6.0 + 的运行时权限(如相机、存储),使用ActivityCompat.requestPermissions()申请。
  • 适配刘海屏 / 折叠屏:通过WindowInsetsController处理安全区域,或在AndroidManifest.xml中配置:
<application> 
    <meta-data android:name="android.max_aspect" 
               android:value="2.4" /> 
    <!-- 限制最大纵横比,适配刘海屏 --> 
</application>

3. 字体与布局适配技巧

  • 避免硬编码尺寸:在dimens.xml中定义尺寸变量,如:
<resources>
    <dimen name="padding_small">8dp</dimen>
    <dimen name="text_size_normal">16sp</dimen>
</resources>
  • 使用 ViewBinding / 数据绑定:减少 findViewById 操作,同时通过数据驱动布局,动态调整显示效果。

相关问题

  1. Android 项目中 res 目录的标准结构是怎样的?各子目录(如 drawable、layout、values 等)的作用分别是什么?

  2. 什么是「屏幕密度适配」?res 目录如何通过不同后缀的子目录(如 drawable-mdpi、drawable-hdpi)实现适配?

  3. res 与 assets 目录的区别是什么?各自的应用场景有哪些?

  4. 在 Android 中,资源 ID 是如何生成和管理的?R 文件的作用是什么?

  5. 如何减少 res 资源对应用安装包大小的影响?常见的优化手段有哪些?

  6. drawable 目录下支持哪些资源类型?请列举至少 5 种,并说明其用途。

  7. 如何使用 XML 定义 shape 资源?请描述 shape 中常见标签(如 <solid><stroke><corners>)的作用。

  8. 如何绘制带渐变效果的 shape?请说明线性渐变(linearGradient)和径向渐变(radialGradient)的区别。

  9. 如何用 shape 实现虚线边框?需要注意哪些属性配置?

  10. StateListDrawable(状态选择器)的作用是什么?如何为 Button 定义不同点击状态的背景?

  11. Android 中常用的布局类型有哪些?各自的特点和适用场景是什么?

  12. 什么是 Style 和 Theme?两者的区别是什么?如何通过 Theme 统一应用的视觉风格?

  13. 如何在布局文件中引用自定义 Style?请举例说明。

  14. ConstraintLayout 相比传统布局(如 RelativeLayout)有哪些优势?如何优化复杂布局的性能?

  15. 什么是布局复用?如何通过 <include><merge> 和 <ViewStub> 标签实现布局复用?

  16. 如何实现 Android 应用的屏幕适配?请说明尺寸单位(dp、sp、px)的区别和使用场景。

  17. 什么是「屏幕适配的今日头条方案」?其原理与传统适配方式有何不同?

  18. 如何在不同语言环境下适配字符串资源?strings.xml 如何支持多语言切换?

  19. 图片资源的适配策略有哪些?如何使用 WebP 或 VectorDrawable 优化图片资源?

  20. 运行时资源匹配(Runtime Resource Overlay,RRO)的原理是什么?适用于哪些场景?

  21. 如何在 res 中定义自定义属性(declare-styleable)?请举例说明在自定义 View 中如何使用。

  22. 如何在 Android 项目中引入第三方字体?请描述从资源导入到代码应用的完整流程。

  23. 如何使用 AnimatedVectorDrawable 实现动画效果?相比帧动画(Frame Animation)有哪些优势?

  24. 动态获取资源的方式有哪些?getResources().getXXX() 方法在使用时需要注意什么?

  25. 在 AndroidX 中,资源迁移(如 android.support 到 androidx)有哪些常见问题?如何解决?