升级应用从API 8到API 26+后修复R.drawable图标变形问题
问题描述
我正在翻新一款有10余年历史的旧应用(原适配Android 2.2、4.1),该应用在旧版本系统中显示与功能均正常,但安装到Android 8.1设备后出现视觉异常:
- 在API 8/16系统中,
R.drawable图标/按钮显示正常(正常显示效果:
); - 在API 26/29系统中,同一图标显示变形(异常显示效果:
)。
负责该部分显示的main.xml代码如下:
<!-- horizontal row of 3 buttons (prev, pause/play, next) --> <LinearLayout android:id="@+id/prev_pauseplay_next_buttons" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center" android:orientation="horizontal" > <com.susu.mylib.core.MyButton android:id="@+id/btn_prev" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@android:drawable/ic_media_previous" /> <LinearLayout android:id="@+id/ll_pause_or_play_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" > <com.susu.mylib.core.MyButton android:id="@+id/btn_pause" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@android:drawable/ic_media_pause" android:layout_marginLeft="36dp" android:layout_marginRight="36dp" /> <com.susu.mylib.core.MyButton android:id="@+id/btn_play" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@android:drawable/ic_media_play" android:layout_marginLeft="36dp" android:layout_marginRight="36dp" android:visibility="gone" /> </LinearLayout> <!-- end ll_pause_or_play_button --> <com.susu.mylib.core.MyButton android:id="@+id/btn_next" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@android:drawable/ic_media_next" /> </LinearLayout> <!-- end prev_pauseplay_next_buttons -->
请问该问题产生的原因是什么?如何修复?另外,这些图标属于哪个Android SDK库或jar包?
问题解答
一、异常原因
- 系统图标资源变更:Android从API 21(Android 5.0)开始推行Material Design规范,内置的
@android:drawable/ic_media_*系列图标被替换为新设计风格的资源,尺寸、比例和旧版本差异明显。 - 背景缩放规则调整:高版本Android中,
Button背景Drawable的默认缩放逻辑改变,旧版本会保持图标原始比例适配按钮,高版本可能强制拉伸填满按钮区域,导致变形。 - 自定义控件适配缺失:你使用的
MyButton是自定义控件,未针对高版本Android的Drawable渲染逻辑做适配,比如未正确处理Drawable的边界或缩放模式。
二、修复方法
方法1:替换为自定义图标资源(推荐)
- 提取旧版本系统的
ic_media_previous、ic_media_pause、ic_media_play、ic_media_next图标,放入应用的res/drawable-*目录(按不同分辨率适配)。 - 修改布局中
android:background属性,引用应用自身的图标资源,示例:
此方法彻底摆脱系统版本依赖,保证全版本显示一致。android:background="@drawable/ic_media_previous"
方法2:设置Drawable缩放模式
- 在代码中为按钮背景Drawable指定缩放规则,保持图标比例:
MyButton btnPrev = findViewById(R.id.btn_prev); Drawable drawable = btnPrev.getBackground(); drawable.setScaleType(Drawable.ScaleType.CENTER_INSIDE); // 可选CENTER、FIT_CENTER btnPrev.setBackground(drawable); - 或改用
ImageView包裹图标作为按钮内容,更灵活控制缩放:<com.susu.mylib.core.MyButton android:id="@+id/btn_prev" android:layout_width="wrap_content" android:layout_height="wrap_content"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@android:drawable/ic_media_previous" android:scaleType="centerInside"/> </com.susu.mylib.core.MyButton>
方法3:使用兼容库图标
- 若坚持用系统图标,可替换为
AppCompat库的兼容资源,比如@drawable/abc_ic_media_previous_mtrl_alpha(需依赖appcompat-v7或更高版本库),这类图标在高版本系统中显示效果一致。
三、图标所属说明
这些@android:drawable/ic_media_*图标是Android系统框架的内置资源,并非单独的SDK库或JAR包:
- 旧版本Android(API 16及以下)中,它们存放在系统的
framework-res.apk文件里,属于系统资源的一部分。 - 开发环境中,这些图标随对应API级别的
platforms/android-XX/data/res目录提供,仅用于开发时引用,编译不会打包进应用,运行时直接调用系统资源。
内容的提问来源于stack exchange,提问作者WebViewer
相关产品推荐
相关产品推荐

