Android |📘 资源类型详解

41 阅读14分钟

📘 Android 资源类型详解

Android 应用中的资源(Resources)是指非代码部分的静态内容,如布局、字符串、图片、颜色、动画等。这些资源统一存放在 res/ 目录下,通过编译生成 R.java 类进行引用,支持多设备适配、国际化、主题切换等高级功能。

3.1 🖼️ 图片资源(Drawable 和 Mipmap)

3.1.1 🖼️ Drawable 资源(Drawable Resources)

📌 整体介绍

用于图像、背景、图标等视觉元素,支持位图(PNG/JPEG/WebP)、矢量图(VectorDrawable)、形状定义(Shape)、状态选择器(Selector)、图层叠加(Layer-list)等多种形式。

✅ 支持的格式及特点
格式优点缺点特点使用场景
PNG- 无损压缩,图像质量高
- 支持透明通道 (Alpha)
- 兼容性极好
- 文件体积较大(尤其对于照片类图像)
- 不适合存储复杂渐变或照片
保留所有原始数据,边缘清晰- 图标、按钮、Logo 等需要透明背景的 UI 元素
- 小尺寸、颜色简单的图形
-
JPEG- 有损压缩文件体积小
- 适合存储照片和复杂色彩图像
- 不支持透明度、动画
- 压缩会导致细节损失(产生噪点,不适合文字/锐利边缘图形)
通过合并相邻像素的颜色信息来压缩(彩色图像编码方案)- 背景图、用户头像、商品图片等照片类内容
- 对体积敏感无需透明的场景
- 网络摄影作品与生活照、色彩层次丰富的艺术画作
WebP- 同时支持有损 & 无损压缩
- 支持透明通道、动图
- 比 PNG/JPEG 体积更小(通常小 25%~35%)
- 部分旧工具链兼容性差采用预测编码等先进算法:有损时比 JPG 清晰,无损时比 PNG 小- 现代 App 中替代 PNG/JPEG 的首选
- 需要兼顾体积与透明度的场景(如带透明的照片图标)
Vector
(SVG/VectorDrawable)
- 矢量格式,无限缩放不失真
- 对于简单图形,文件体积极小
- 一套资源适配所有屏幕密度
- 灵活可控:可用代码编辑与交
- 不适合复杂图像(如照片)
- 复杂路径的绘制可能增加内存/CPU 开销
- 渲染性能在首次/复杂场景下可能低于位图
- 有学习门槛:需要理解其代码结构
- 与分辨率无关
- 本质是结构化文档
- 多尺寸应用的图标、简单图形
- Material Design 图标
- 需要多分辨率适配的静态图形
- 可进行路径变换的动画图形(需使用 AnimatedVectorDrawable
- 字体、插画与平面设计素材
- 数据可视化图表与地图

💡 官方推荐:优先使用 VectorDrawable 替代位图,减少 APK 体积并提升适配能力。

🗂️ 存放位置
res/
├── drawable-mdpi/    # 中等密度 (~160dpi)
├── drawable-hdpi/    # 高密度 (~240dpi)
├── drawable-xhdpi/   # 超高密度 (~320dpi)
├── drawable-xxhdpi/  # 超超高密度 (~480dpi)
└── drawable-xxxhdpi/ # 超超超高密度 (~640dpi)

⚠️ 若使用 VectorDrawable,则只需一份 drawable/ 文件,无需多密度版本。


🔧 使用方式
(1)🖼️ 示例图:

使用方式一

(2)XML Drawable 类型详解
直接引用位图或矢量图
<!-- XML -->
<ImageView
    android:src="@drawable/ic_launcher"
    android:background="@drawable/rounded_rectangle" />

<Button
    android:background="@drawable/button_selector" />
// Java
ImageView imageView = findViewById(R.id.image_view);
imageView.setImageResource(R.drawable.ic_launcher);
imageView.setBackgroundResource(R.drawable.rounded_rectangle);

Drawable drawable = ContextCompat.getDrawable(context, R.drawable.ic_launcher);
// Kotlin
val imageView: ImageView = findViewById(R.id.image_view)
imageView.setImageResource(R.drawable.ic_launcher)
imageView.background = ContextCompat.getDrawable(this, R.drawable.rounded_rectangle)
<shape>:定义几何形状

用途:创建矩形、椭圆、直线、圆环等,并可设置颜色、渐变、圆角、描边、内边距。

<!-- res/drawable/rounded_rectangle.xml -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="@color/primary_color" />
    <corners android:radius="@dimen/button_corner_radius" />
    <stroke android:width="1dp" android:color="@color/accent_color" />
    <padding
        android:left="8dp"
        android:top="4dp"
        android:right="8dp"
        android:bottom="4dp" />
</shape>

🖼️ 效果图:
Shape 示例


<selector>:状态选择器

根据 View 状态(按下、聚焦、启用等)切换不同 Drawable,常用于按钮反馈。

<!-- res/drawable/button_selector.xml -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/button_pressed" android:state_pressed="true" />
    <item android:drawable="@drawable/button_focused" android:state_focused="true" />
    <item android:drawable="@drawable/button_normal" />
</selector>
  • button_pressed.xml:按下时显示深蓝色
  • button_focused.xml:获得焦点时显示中蓝色
  • button_normal.xml:默认状态显示标准蓝色

🖼️ 动态效果:
Selector 动画


<layer-list>:图层列表

将多个 Drawable 堆叠,实现复合效果(如图标+背景、阴影、光泽)。

<!-- res/drawable/layered_icon.xml -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="oval">
            <solid android:color="@color/primary_color" />
        </shape>
    </item>
    <item
        android:drawable="@drawable/ic_icon"
        android:gravity="center" />
</layer-list>

🖼️ 效果图:
Layer List


<vector>:矢量图形

使用 SVG 路径语法定义可缩放图标,一套文件适配所有屏幕。

<!-- res/drawable/ic_arrow.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24"
    android:viewportHeight="24">
    <path
        android:fillColor="@color/primary_color"
        android:pathData="M12,2L1,21h22L12,2z" />
</vector>

🖼️ 效果图:
Vector 示例


<level-list>:等级列表

根据整数值(Level)切换 Drawable,适用于电量、信号强度、进度等场景。

<!-- res/drawable/battery_level.xml -->
<level-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:maxLevel="10" android:drawable="@drawable/battery_low" />
    <item android:maxLevel="50" android:drawable="@drawable/battery_medium" />
    <item android:maxLevel="100" android:drawable="@drawable/battery_full" />
</level-list>

Java 使用示例:

LevelListDrawable levelDrawable = (LevelListDrawable) getResources().getDrawable(R.drawable.battery_level, null);
levelDrawable.setLevel(75); // 设置为 75%
imageView.setImageDrawable(levelDrawable);

完整 Demo 代码:

package com.itzy.myapplication;

import android.os.Bundle;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import android.graphics.Color;
import android.graphics.drawable.LevelListDrawable;
import android.view.ViewGroup;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {
    private LevelListDrawable levelDrawable;
    private TextView levelText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        LinearLayout mainLayout = new LinearLayout(this);
        mainLayout.setOrientation(LinearLayout.VERTICAL);
        mainLayout.setLayoutParams(new LinearLayout.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.MATCH_PARENT));

        levelDrawable = (LevelListDrawable) getResources().getDrawable(R.drawable.battery_level, null);
        levelDrawable.setLevel(75);
        mainLayout.setBackground(levelDrawable);

        TextView titleText = new TextView(this);
        titleText.setText("Level List Drawable Demo");
        titleText.setTextSize(24);
        titleText.setTextColor(Color.BLACK);
        titleText.setPadding(50, 50, 50, 50);

        levelText = new TextView(this);
        levelText.setText("Battery Level: 75%");
        levelText.setTextSize(20);
        levelText.setTextColor(Color.BLACK);
        levelText.setPadding(50, 50, 50, 50);

        SeekBar levelSeek = new SeekBar(this);
        levelSeek.setMax(100);
        levelSeek.setProgress(75);
        levelSeek.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                levelDrawable.setLevel(progress);
                levelText.setText("Battery Level: " + progress + "%");
                mainLayout.invalidate();
            }
            @Override public void onStartTrackingTouch(SeekBar seekBar) {}
            @Override public void onStopTrackingTouch(SeekBar seekBar) {}
        });

        LinearLayout.LayoutParams seekParams = new LinearLayout.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        seekParams.setMargins(50, 50, 50, 100);
        levelSeek.setLayoutParams(seekParams);

        mainLayout.addView(titleText);
        mainLayout.addView(levelText);
        mainLayout.addView(levelSeek);
        setContentView(mainLayout);
    }
}

🖼️ 动态演示:
Level List 动画


<ripple>:水波纹反馈

提供 Material Design 风格的触摸涟漪效果。

<!-- res/drawable/ripple_bg.xml -->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="?attr/colorControlHighlight">
    <item android:drawable="@color/white" />
</ripple>

🖼️ 效果图:
Ripple 动画


📊 Drawable 类型总结表
种类XML 标签主要用途
BitmapDrawable<bitmap>包装位图,设置平铺等
ShapeDrawable<shape>创建纯色/渐变的几何形状
LayerDrawable<layer-list>组合多个 Drawable 实现复杂效果
StateListDrawable<selector>根据视图状态切换 Drawable
LevelListDrawable<level-list>根据整数值等级切换 Drawable
VectorDrawable<vector>创建可缩放的矢量图标
AnimatedVectorDrawable<animated-vector>为矢量图添加动画
RippleDrawable<ripple>提供 Material Design 水波纹反馈
ClipDrawable<clip>裁剪 Drawable(用于进度条)

3.1.2 🖼️ Mipmap 资源(Mipmap Resources)

📌 整体介绍

专门用于存放应用启动图标(Launcher Icon)

✅ 优势
  • 系统在 launcher 界面会使用不同密度的 mipmap 资源,获得更好缩放效果
  • 即使 APK 分包(split by density),mipmap 资源也不会被移除,确保图标始终可用
🗂️ 存放位置
res/mipmap-mdpi/
res/mipmap-hdpi/
res/mipmap-xhdpi/
res/mipmap-xxhdpi/
res/mipmap-xxxhdpi/

3.1.3 🆚 对比:drawable/ vs mipmap/

特性drawable/mipmap/
用途通用图片资源仅用于 launcher icon
密度分包优化会被移除未用密度不会被移除
缩放质量一般✅ 更适合 launcher 缩放
官方建议所有非图标资源必须用于应用图标

Google 明确要求:应用图标必须放在 mipmap/


3.2 📄 布局资源(Layout Resources)

3.2.1 📌 用途与位置

  • 用途:定义 UI 界面结构,
  • 位置res/layout/
  • 文件类型.xml这些定义Ui界面的XML文件通常用于搭建程序的各个界面。

3.2.2 🔗 使用方式

<!-- activity_main.xml -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />
</LinearLayout>
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main) // 加载布局
        
        val textView = findViewById<TextView>(R.id.textView) // 通过ID获取视图
        textView.text = "Hello Android!"
    }
}

3.2.3 🌐 限定符适配

  • layout-land/:横屏
  • layout-port/:竖屏
  • layout-sw600dp/:最小宽度 ≥600dp(7寸平板)
  • layout-sw720dp/:10寸平板
Configuration config = getResources().getConfiguration();
Log.d("Config", "Orientation: " + config.orientation);
Log.d("Config", "Smallest width: " + config.smallestScreenWidthDp + "dp");

3.2.4 📊 布局类型对比

布局类型特点使用场景
LinearLayout线性排列简单列表、表单
RelativeLayout相对位置复杂布局(已逐步被 ConstraintLayout 取代)
ConstraintLayout约束关系现代复杂布局首选
FrameLayout层叠布局单个子视图或层叠(如 Fragment 容器)
GridLayout网格布局网格状排列
TableLayout表格布局表格数据展示

3.3 值资源(Values/)

3.3.1 🧾 字符串资源(strings.xml

📌 用途

集中管理文本,支持国际化、格式化、复数、HTML、数组,避免硬编码。。

📁 位置
res/values/strings.xml       // 默认
res/values-en/strings.xml    // 英文
res/values-zh/strings.xml    // 中文
📌 示例
<resources>
    <!-- 普通字符串 -->
    <string name="app_name">我的应用</string>
    <string name="welcome_message">欢迎使用</string>
    
    <!-- 带参数的格式化字符串 -->
    <string name="greeting">你好, %1$s! 你有 %2$d 条新消息</string>
    
    <!-- HTML 格式字符串 -->
    <string name="html_text"><![CDATA[欢迎来到<b>我的应用</b><br/>这是<u>下划线文本</u>]]></string>
    
    <!-- 复数形式 -->
    <plurals name="item_count">
        <item quantity="one">%d 个项目</item>
        <item quantity="other">%d 个项目</item>
    </plurals>
    
    <!-- 字符串数组 -->
    <string-array name="fruits">
        <item>苹果</item>
        <item>香蕉</item>
        <item>橙子</item>
    </string-array>
</resources>
🔗 使用方式对比
  • 在布局中

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />
    
  • 在代码中

    val text = getString(R.string.hello_world)
    val formattedText = getString(R.string.welcome_message, "张三", 5)
    
使用场景XML 中使用Java 中使用Kotlin 中使用
普通字符串@string/app_namegetString(R.string.app_name)同左
格式化字符串不支持getString(R.string.greeting, "John", 5)同左
HTML 字符串不支持Html.fromHtml(getString(R.string.html_text))同左
复数形式不支持getResources().getQuantityString(R.plurals.item_count, count, count)resources.getQuantityString(...)
字符串数组不支持getResources().getStringArray(R.array.fruits)resources.getStringArray(...)

🖼️ 国际化切换演示: “切换系统语言“

<!-- values/strings.xml -->
<resources>
    <string name="app_name">我的应用</string>
    <string name="hello_world">你好,世界!</string>
    <string name="welcome_message">欢迎,%1$s!你有%2$d条新消息。</string>
</resources>

<!-- values-en/strings.xml (英文翻译) -->
<resources>
    <string name="app_name">My Application</string>
    <string name="hello_world">Hello World!</string>
    <string name="welcome_message">Welcome, %1$s! You have %2$d new messages.</string>
</resources>

请添加图片描述


3.3.2 🎨 颜色资源(colors.xml

统一管理颜色值,支持十六进制、ARGB、状态选择器(如按钮按下变色)。

📌 示例
<!-- values/colors.xml -->
<resources>
    <color name="color_primary">#3F51B5</color>
    <color name="color_primary_dark">#303F9F</color>
    <color name="color_accent">#FF4081</color>
    <color name="text_color">#212121</color>
</resources>

<!-- values-night/colors.xml (深色主题) -->
<resources>
    <color name="color_primary">#1A237E</color>
    <color name="text_color">#FFFFFF</color>
</resources>
🔗 使用方式
<TextView android:textColor="@color/text_color" />
// Java 中使用
int primaryColor = ContextCompat.getColor(context, R.color.primary_color);
view.setBackgroundColor(primaryColor);
// Kotlin 中使用
val primaryColor = ContextCompat.getColor(this, R.color.primary_color)
val accentColor = getColor(R.color.accent_color) // API 23+
📊 颜色格式
格式示例说明
#RGB#F00红绿蓝,各1位
#ARGB#8F00透明度+红绿蓝,各1位
#RRGGBB#FF0000红绿蓝,各2位
#AARRGGBB#80FF0000透明度+红绿蓝,各2位

3.3.3 📏 尺寸资源(dimens.xml

定义 UI 中的尺寸(如 padding、textSize),便于统一维护和适配。

📌 示例
<!-- values/dimens.xml -->
<resources>
    <dimen name="padding_small">8dp</dimen>
    <dimen name="padding_medium">16dp</dimen>
    <dimen name="text_size_large">18sp</dimen>
    <dimen name="button_corner_radius">4dp</dimen>
</resources>

<!-- values-sw600dp/dimens.xml (平板) -->
<resources>
    <dimen name="padding_medium">24dp</dimen>
    <dimen name="text_size_large">22sp</dimen>
</resources>
🔗 使用方式
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="@dimen/text_size_large"
    android:padding="@dimen/padding_medium" />
// Java 中使用
float textSize = getResources().getDimension(R.dimen.text_size_medium);
int padding = getResources().getDimensionPixelSize(R.dimen.padding_medium);
// Kotlin 中使用
val textSize = resources.getDimension(R.dimen.text_size_medium)
val padding = resources.getDimensionPixelSize(R.dimen.padding_medium)
📊 尺寸单位说明
单位描述使用场景
dp密度无关像素布局尺寸、边距、填充
sp缩放无关像素文字大小(随系统字体缩放)
px物理像素不推荐
pt点 (1/72英寸)印刷品相关
mm毫米精确物理尺寸
in英寸精确物理尺寸
  • dp(Density-independent Pixels)密度无关像素
    • 描述:这是一种虚拟像素单位,主要用于Android开发中,它根据屏幕密度自动调整实际物理像素的数量。一个dp在160 dpi的屏幕上等于一个物理像素(px)。
    • 使用场景:布局尺寸、边距、填充等,用于确保应用界面在不同分辨率和屏幕尺寸的设备上都能保持一致的视觉效果。
  • sp(Scale-independent Pixels)缩放无关像素
    • 描述:类似于dp,但是还会根据用户的字体大小偏好进行缩放。这是为了适应用户可能设置的更大或更小的文字显示需求。
    • 使用场景:专门用于文字大小设定,以确保文本内容能够根据用户的偏好适当地缩放。
  • px(Pixels)物理像素
    • 描述:表示屏幕上的实际物理像素点。由于不同设备的屏幕密度差异很大,直接使用px作为单位会导致在不同设备上显示的效果不一致。
    • 使用场景:通常不推荐使用px来定义UI元素的尺寸,除非是在特定情况下需要固定物理像素的情况。
  • pt(Points)点 (1/72英寸)
    • 描述:传统印刷业使用的单位,1点等于1/72英寸。尽管在数字屏幕设计中不如dp或sp常用,但在某些涉及打印输出的设计时仍然是重要的单位。
    • 使用场景:与印刷品相关的设计工作,如创建PDF文档或设计将被打印出来的材料。
  • mm(Millimeters)毫米
    • 描述:国际单位制中的长度单位,1毫米等于千分之一米。这种单位提供了一种精确的物理尺寸测量方法。
    • 使用场景:当你需要基于具体的物理尺寸来设计时使用,例如在制造需要严格尺寸控制的产品原型时。
  • in(Inches)英寸
    • 描述:另一种常用的物理长度单位,在很多国家用于日常测量。1英寸等于25.4毫米。
    • 使用场景:同样适用于需要精确物理尺寸的应用场合,特别是在那些同时使用英制单位的项目中。

3.3.4 🎭 样式主题资源(styles.xml

📌 整体介绍
  • Style:应用于单个 View 的属性集合
  • Theme:应用于整个 Activity 或 App 的 Style,可继承
📁 位置
res/values/styles.xml
res/values/themes.xml
📌 示例
  • View 属性(textColor, background 等)
  • 主题属性(colorPrimary, windowBackground 等)
<!-- values/styles.xml -->
<resources>
    <!-- 应用主题 -->
    <style name="AppTheme" parent="Theme.MaterialComponents.Light.DarkActionBar">
        <item name="colorPrimary">@color/color_primary</item>
        <item name="colorPrimaryDark">@color/color_primary_dark</item>
        <item name="colorAccent">@color/color_accent</item>
    </style>
    
    <!-- 自定义控件样式 -->
    <style name="PrimaryButton" parent="Widget.MaterialComponents.Button">
        <item name="android:textColor">@android:color/white</item>
        <item name="backgroundTint">@color/color_primary</item>
        <item name="cornerRadius">@dimen/button_corner_radius</item>
    </style>
</resources>
🔗 使用方式
<!-- 应用主题 AndroidManifest.xml  -->
<application
    android:theme="@style/AppTheme">
    
<!-- Activity 中应用样式 -->
<Button
    style="@style/PrimaryButton"
    android:text="确认" />

<!-- TextView 应用文本样式 -->
<TextView
    style="@style/HeadingText"
    android:text="标题" />
// Java、Kotlin 中设置主题
setTheme(R.style.AppTheme);
🆚 样式 vs 主题
特性样式 (Style)主题 (Theme)
作用范围单个 View整个 Activity/Application
继承方式parent 属性parent 属性
应用方式style 属性android:theme 属性
常用场景按钮样式、文本样式应用整体外观
🔗 使用方式2
<!-- res/values/styles.xml -->
<resources>
    <!-- 基础主题 -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:windowBackground">@color/window_background</item>
    </style>
    
    <!-- 控件样式 -->
    <style name="PrimaryButton" parent="Widget.AppCompat.Button">
        <item name="android:background">@drawable/button_primary</item>
        <item name="android:textColor">@android:color/white</item>
        <item name="android:textSize">@dimen/text_size_medium</item>
        <item name="android:padding">@dimen/padding_medium</item>
    </style>
    
    <!-- 文本样式 -->
    <style name="HeadingText">
        <item name="android:textSize">20sp</item>
        <item name="android:textStyle">bold</item>
        <item name="android:textColor">@color/primary_color</item>
    </style>
    
    <!-- 对话框主题 -->
    <style name="CustomDialog" parent="Theme.AppCompat.Light.Dialog">
        <item name="colorAccent">@color/accent_color</item>
    </style>
</resources>

3.4 📋 菜单资源(Menu)

用于定义应用栏、上下文菜单和弹出菜单。

  • 使用: 在 Activity/Fragment 中,重写 onCreateOptionsMenu 并 inflate: menuInflater.inflate(R.menu.main_menu, menu)
  • 元素: <menu>, <item>, <group>

📁 位置

res/menu/

📌 示例

<!-- res/menu/main_menu.xml -->
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    
    <!-- 普通菜单项 -->
    <item
        android:id="@+id/action_settings"
        android:icon="@drawable/ic_settings"
        android:title="@string/action_settings"
        app:showAsAction="ifRoom" />
    
    <!-- 带子菜单的项 -->
    <item
        android:id="@+id/action_more"
        android:title="@string/action_more"
        app:showAsAction="always">
        <menu>
            <item
                android:id="@+id/action_help"
                android:title="@string/action_help" />
            <item
                android:id="@+id/action_about"
                android:title="@string/action_about" />
        </menu>
    </item>
    
    <!-- 复选框菜单项 -->
    <item
        android:id="@+id/action_toggle"
        android:title="@string/action_toggle"
        android:checkable="true" />
    
</menu>

🔗 使用方式

Java
// Java 中创建选项菜单
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main_menu, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.action_settings:
            // 处理设置操作
            return true;
        case R.id.action_help:
            // 处理帮助操作
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}
Kotlin
// Kotlin 中创建选项菜单
override fun onCreateOptionsMenu(menu: Menu): Boolean {
    menuInflater.inflate(R.menu.main_menu, menu)
    return true
}

override fun onOptionsItemSelected(item: MenuItem): Boolean {
    return when (item.itemId) {
        R.id.action_settings -> {
            // 处理设置操作
            true
        }
        R.id.action_help -> {
            // 处理帮助操作
            true
        }
        else -> super.onOptionsItemSelected(item)
    }
}

📊 菜单类型对比

菜单类型显示位置创建方式适用场景
OptionsMenuActionBaronCreateOptionsMenu()主要操作
ContextMenu长按视图registerForContextMenu()上下文操作
PopupMenu任意位置PopupMenu临时操作

3.5 🎞️ 动画资源(Animation Resources)

📁 目录结构

res/
├── anim/      # 补间动画(Tween)
└── animator/  # 属性动画(Property)

📊 动画类型对比

动画类型目录特点适用场景
补间动画anim/视图动画、性能好简单变换(淡入、滑动)
属性动画animator/真实属性变化、更灵活复杂动画、交互动画

3.5.3 补间动画示例(res/anim/

<!-- res/anim/fade_in.xml -->
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true">
    
    <alpha
        android:fromAlpha="0.0"
        android:toAlpha="1.0"
        android:duration="1000" />
        
    <scale
        android:fromXScale="0.5"
        android:toXScale="1.0"
        android:fromYScale="0.5"
        android:toYScale="1.0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:duration="1000" />
        
</set>

<!-- res/anim/slide_in_left.xml -->
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:fromXDelta="-100%"
        android:toXDelta="0"
        android:duration="500" />
</set>

3.5.4 属性动画示例(res/animator/

<!-- res/animator/scale_animator.xml -->
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
        android:propertyName="scaleX"
        android:duration="1000"
        android:valueFrom="1.0"
        android:valueTo="1.5" />
    <objectAnimator
        android:propertyName="scaleY"
        android:duration="1000"
        android:valueFrom="1.0"
        android:valueTo="1.5" />
</set>

3.5.5 🔗 使用方式

Java
// Java 中使用补间动画
Animation fadeIn = AnimationUtils.loadAnimation(this, R.anim.fade_in);
view.startAnimation(fadeIn);

// Java 中使用属性动画
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.scale_animator);
set.setTarget(view);
set.start();
Kotlin
// Kotlin 中使用补间动画
val fadeIn = AnimationUtils.loadAnimation(this, R.anim.fade_in)
view.startAnimation(fadeIn)

// Kotlin 中使用属性动画
val set = AnimatorInflater.loadAnimator(this, R.animator.scale_animator) as AnimatorSet
set.setTarget(view)
set.start()

3.6 其他资源类型

3.6.1 📂 原始文件资源(Raw Resources)

存放原始文件(如音频、配置),编译时不处理,保持原样。

  • 位置res/raw/
  • ✅ 能存储.mp3, .json, .txt 等任意文件
  • 限制:不能有子目录;文件名需符合命名规则
🔗 使用方式
// 存储位置: res/raw/
// 使用方式:
InputStream inputStream = getResources().openRawResource(R.raw.data_file);
MediaPlayer mediaPlayer = MediaPlayer.create(this, R.raw.sound_effect);

3.6.2 📄 XML 文件资源

  • 位置res/xml/
  • 用途:自定义配置(如 PreferenceScreen)
// 存储位置: res/xml/
// 使用方式:
XmlResourceParser parser = getResources().getXml(R.xml.config);

3.6.3 🔤 字体资源

  • 位置res/font/
  • 格式.ttf, .otf
  • 字体族: 可以在 res/font/ 下创建一个 XML 文件,定义字体的不同风格(正常、粗体、斜体)及其对应的字体文件,系统会自动选择。
使用方式
<TextView android:fontFamily="@font/my_font" />
Typeface typeface = ResourcesCompat.getFont(this, R.font.roboto_regular);
textView.setTypeface(typeface);
// 使用方式:
TextView textView = findViewById(R.id.text_view);
Typeface typeface = ResourcesCompat.getFont(this, R.font.roboto_regular);
textView.setTypeface(typeface);
字体族定义
<!-- res/font/roboto.xml -->
<font-family xmlns:android="http://schemas.android.com/apk/res/android">
    <font
        android:fontStyle="normal"
        android:fontWeight="400"
        android:font="@font/roboto_regular" />
    <font
        android:fontStyle="italic"
        android:fontWeight="400"
        android:font="@font/roboto_italic" />
</font-family>

3.6.4 🗃️ Assets 资源

  • 位置assets/不在 res/
  • 特点:支持子目录;不生成 R.id
🔗 使用方式
InputStream is = getAssets().open("data/config.json");
String[] files = getAssets().list("");
val is = assets.open("data/config.json")
val files = assets.list("")
🆚 raw vs assets
特性res/raw/assets/
生成 R.id
子目录支持
编译检查❌(运行时报错)
适用场景简单固定资源复杂资源包(游戏、HTML)

3.6.5 🔢 数值资源(Integer, Bool, Array)

  • 存储常量数值、开关标志、数组,便于配置管理。

  • 位置

    • res/values/integers.xml
    • res/values/bools.xml
🔗 使用方式
Java
int max = getResources().getInteger(R.integer.max_retry);
boolean debug = getResources().getBoolean(R.bool.is_debug);
int[] primes = getResources().getIntArray(R.array.prime_numbers);
Kotlin
val max = resources.getInteger(R.integer.max_retry)
val debug = resources.getBoolean(R.bool.is_debug)
val primes = resources.getIntArray(R.array.prime_numbers)

ets().list("");


```kotlin
val is = assets.open("data/config.json")
val files = assets.list("")
🆚 raw vs assets
特性res/raw/assets/
生成 R.id
子目录支持
编译检查❌(运行时报错)
适用场景简单固定资源复杂资源包(游戏、HTML)

3.6.5 🔢 数值资源(Integer, Bool, Array)

  • 存储常量数值、开关标志、数组,便于配置管理。

  • 位置

    • res/values/integers.xml
    • res/values/bools.xml
🔗 使用方式
Java
int max = getResources().getInteger(R.integer.max_retry);
boolean debug = getResources().getBoolean(R.bool.is_debug);
int[] primes = getResources().getIntArray(R.array.prime_numbers);
Kotlin
val max = resources.getInteger(R.integer.max_retry)
val debug = resources.getBoolean(R.bool.is_debug)
val primes = resources.getIntArray(R.array.prime_numbers)