Android应用源码(物理)
应用资源概述
Android应用资源类型和存储方式
无法通过R资源清单类访问的原生资源,保存在assets目录下
可通过R资源清单类访问的资源,保存在res目录下
res目录下资源存储资源说明
/res/animator/:存放定义属性动画的XML文件
/res/anim/:存放定义补间动画的XML文件
/res/color/:存放定义不同状态下颜色列表的XML文件
/res/drawable/:存放各种位图文件,编译成各种Drawable对象的XML文件(BitmapDrawable、NinePatchDrawable、StateListDrawable、ShapeDrawable、AnimationDrawable、Drawable的其它各种子类对象)
/res/layout/:存放用户界面布局文件
/res/menu/:存放为应用程序定义的各种菜单资源(选项菜单、子菜单、上下文菜单)
/res/raw/:存放任意类型原生资源(音频、视频等),使用时通过调用Resource对象的openRawResource(int id)方法获取该资源的二进制输入流进而进行使用。
/res/values/:存放各种简单的XML文件(字符串值、整数值、颜色值、数组、尺寸、样式等),一般根据不同文件来存储不同类型的值。
/res/xml/:存放原生XML文件,通过Resource对象的getXML()方法进行访问。
资源使用
Java代码中使用资源清单项:[package_name.]R.resource_type.resource_name
// 获取图片资源
getWindow().setBackgroundDrawableResource(R.drawable.back);
// 获取字符串资源
getWindow().setTitle(getResources().getText(R.string.main_title))
Java代码中访问实际资源(通过Resources类对象调用下述方法)
getXXX(int id):根据资源清单ID来获取实际资源
getAssets():获取访问/assets/目录下资源的AssetManager对象
// 获取Resource对象
Resource res = Activity.this.getResources();
// 获取字符串资源
String titile = res.getText(R.string.main_title);
// 获取图片资源
Drawable logo = res.getDrawable(R.drawable.logo);
// 获取数组资源
int[] arr = res.getIntArray(R.array.books);
hello
#000000
字符串、颜色、尺寸资源
颜色值定义
Android颜色值常见的4种形式
#RGB:分别指定红、绿、蓝三原色的值(只支持0~f 16级颜色)来代表颜色
#ARGB:分别指定红、绿、蓝三原色的值(只支持0~f 16级颜色)及透明度(只支持0~f 16级颜色)来代表颜色
#RRGGBB:分别指定红、绿、蓝三原色的值(只支持00~ff 256级颜色)来代表颜色
#AARRGGBB:分别指定红、绿、蓝三原色的值(只支持00~ff 256级颜色)及透明度(只支持00~ff 256级颜色)来代表颜色
定义字符串、颜色、尺寸资源
字符串定义(/res/values/strings.xml)
手机号
颜色定义(/res/values/colors.xml)
#Fda222
尺寸定义(/res/values/dimens.xml)
16dp
使用字符串、颜色、尺寸资源
字符串、颜色、尺寸等资源使用前面已经说明,此处不做赘述。
数组资源
数组资源定义
- @drawable/ic_search_24dp
- @drawable/ic_search_24dp
- @drawable/ic_search_24dp
- 张三
- 李四
- 王五
- 21
- 35
- 11
数组资源使用
使用方法同字符串、颜色、尺寸等资源的使用类似,此处不做赘述。
Drawable资源
图片资源(XXX.png、XXX.jpg、XXX.gif)
使用方法同字符串、颜色、尺寸等资源的使用类似,此处不做赘述。
StateListDrawable资源
StateListDrawable用于组织多个Drawable对象,当使用StateListDrawable作为目标组件的背景、前景图片时,StateListDrawable对象所显示的Drawable对象会随目标组件状态的改变而自动切换。
StateListDarwable对象的XML文件根元素为 select 元素。该元素可以包含多个 item 子元素。该元素一般具有如下两种属性:
android:color 或者 android:drawable :指定颜色或者Drawable对象
android:state_xxx :指定一个特定状态
StateListDrawable的 item 子元素所支持的状态有如下几种:
android:state_active:代表是否处于激活状态
android:state_checkable:代表是否处于可勾选状态
android:state_checked:代表是否处于已经选状态
android:state_enabled:代表是否处于可用状态
android:state_first:代表是否处于开始状态
android:state_focused:代表是否处于已得到焦点状态
android:state_last:代表是否处于结束状态
android:state_middle:代表是否处于中间状态
android:state_pressed:代表是否处于已被按下状态
android:state_selected:代表是否处于已被选中状态
android:state_window_focused:代表窗口是否处于已得到焦点状态
示例:
LayerDrawable资源
LayerDrawable与StateListDarwable类似,也是包含一个Drawable数组,因此系统会按这些Drawable对象的数组顺序来绘制它们,索引最大的Drawable对象将会被绘制在最上面。
LayerDarwable对象的XML文件的根元素为 layer-list ,该元素可以包含多个 item 元素,一般可以指定如下属性:
android:drawable:指定作为LayerDrawable元素之一的Drawable对象。
android:id:为该Drawable对象指定一个标识。
android:buttom|top|left|button:它们用于指定一个长度值,用于指定该Drawable对象绘制到目标组件的指定位置。
示例:
-
-
-
ShapeDrawable资源
ShapeDrawable用于定义一个基本的几何图形(如矩形、圆等),定义ShapeDrawable的根元素是 shape ,shape可指定如下属性:
android:shape = [“rectangle”|“oval”|“line”|“ring”]
定义ShapeDrawable对象的完整语法:
-
-
ClipDrawable资源
ClipDrawable代表从其它位图上截取一个“图片片段”,在XML文件中定义ClipDrawable对象使用 clip 元素。一般可以指定如下属性:
android:drawable:指定截取的源Drawable对象
android:clipOrientation:指定截取方向,可设置水平截取或者竖直截取
android:gravity:指定截取时的对齐方式
clip元素的完整语法:
AnimationDrawable资源
AnimationDrawable代表一个动画,Android即支持传统的逐帧动画,也支持通过平移、变换计算出来的补间动画。定义补间动画的XML资源文件以 set 元素作为根元素,该元素有如下四个子元素:
alpha:设置透明度的改变
scale:设置图片进行缩放变换
translate:设置图片进行位移变换
rotate:设置图片进行旋转
定义补间动画的XML资源一般放置在/res/anmi/路径下。定义思路比较简单:设置一张图片的开始状态(透明度、位置、缩放比、旋转角度等),结束状态(类似开始状态的设置),动画的持续时间。Android系统会使用动画效果把这张图片从开始状态变换的结束状态。
补间动画语法:
private void initViewAnim() {
// 加载动画资源
animation = AnimationUtils.loadAnimation(this, R.anim.animation_drawable_example);
// 设置动画结束后保留结束状态
animation.setFillAfter(true);
}
case R.id.btn_anim:
// 开始动画
ivAnim.startAnimation(animation);
break;
属性动画资源
Animator代表一个属性动画,但它只是一个抽象类,通常会使用它的子类:AnimatorSet、ValueAnimator、ObjectAnimator、TimeAnimator等。
属性动画的XML文件以下述三个元素中的任意一个作为根元素:
set:它是一个父元素,用于包含 objectAnimator、animator、set 子元素,该元素定义的资源代表AnimatorSet对象。
objectAnimator:用于定义ObjectAnimator动画。
animator:用于定义ValueAnimator动画。
定义属性动画语法:
private class MyAnimationView extends View {
public MyAnimationView(Context context){
super(context);
// 加载动画资源
ObjectAnimator objectAnimator = (ObjectAnimator) AnimatorInflater.loadAnimator(
ResourceActivity.this,R.animator.property_animation_example);
objectAnimator.setEvaluator(new ArgbEvaluator());
// 对该View本身应用属性动画
objectAnimator.setTarget(this);
// 开始指定动画
objectAnimator.start();
}
}
private void initViewPropertyAnim() {
llAnim.addView(new MyAnimationView(this));
}
XML资源
定义原始XML资源
原始的XML资源一般保存在/res/xml/文件夹下,在Java程序中获取实际的XML文件,使用Resources的如下方法来获取:
XmlResourceParser getXml(int id):获取XML文档,并使用一个XmlPullParser来解析XML文档,该方法返回的是一个解析器对象(XmlResourceParser 是XmlPullParser的子类对象)。
InputStream openRawResource(int id):获取XML文档对应的输入流。
获取XML文档一般直接调用getXml(int id)方法获取,并对XML文档进行解析。Android默认使用内置的Pull解析器来解析XML文档。处理使用Pull解析器外,还可以使用DOM或者SAX对XML文档进行解析。
使用原始XML资源
java
android
javaee
// 根据 XML 资源的ID获取解析该资源的解析器
// XmlResoureParser是XmlPullParser的子类
XmlResourceParser xrp = getResources().getXml(R.xml.books);
StringBuilder sb = new StringBuilder("");
// 还没有到xml文档的结尾处
try {
while (xrp.getEventType() != XmlResourceParser.END_DOCUMENT) {
// 如果遇到开始标签
if (xrp.getEventType() == XmlResourceParser.START_TAG) {
// 获取该标签的标签名
String tagName = xrp.getName();
// 如果遇到book标签
if (tagName.equals("book")) {
// 根据属性名来获取属性值
String bookName = xrp.getAttributeValue(null, "price");
sb.append("价格:");
sb.append(bookName);
// 根据属性索引来获取属性值
String bookPrice = xrp.getAttributeValue(1);
sb.append(" 出版日期:");
sb.append(bookPrice);
sb.append(" 书名:");
// 获取文本节点的值
sb.append(xrp.nextText());
}
sb.append("\n");
}
// 获取解析器的下一个事件
xrp.next();
}
etXml.setText(sb.toString());
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
布局资源
Layout资源文件保存在/res/layout/文件夹下,在Java代码中和XML中的使用同其它资源类似。
菜单资源
菜单资源一般保存在/res/menu/文件夹下,以 menu 为根元素,子元素有如下两种:
item:定义菜单项
group:将多个item元素包装成一个菜单组。
item元素可以指定如下属性:
android:id:为菜单指定一个唯一标识
title:指定菜单项的标题
icon:指定菜单的图标
alphabeticShortcut:为菜单项指定字符串快捷键
numericShortcut:为菜单项指定数字快捷键
checkable:设置该菜单项是否可选
checked:设置该菜单项是否已经被选中
visible:设置该菜单项是否可见
enable:设置该菜单项是否可用
group元素可以指定如下属性:
checkableBehavier:指定该组菜单的选择行为,可指定为none(不选)、all(多选)、single(单选)三个值。
menuCategory:对菜单进行分类,指定菜单的优先级,有效值为container、system、secondary、alternative。
visible:指定改组菜单是否可见。
enable:指定改组菜单是否可用。
在程序中定义了菜单项资源后,接下来是重写onCreateOptionsMenu(用于创建选项菜单)、onCreateContextMenu(用以创建上下文菜单)方法,在这些方法中调用MenuInflater对象的inflate方法加载指定资源对应的菜单即可。
示例:
-
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// 装填R.menu.menu_main的菜单,并添加到menu中
MenuInflater inflater = new MenuInflater(this);
inflater.inflate(R.menu.menu_main,menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
// 装填R.menu.context对应的菜单,并添加到menu中
MenuInflater inflater = new MenuInflater(this);
inflater.inflate(R.menu.context,menu);
menu.setHeaderIcon(R.drawable.nvshengtouxiang);
menu.setHeaderTitle("请选择背景颜色");
}
/**
* 上下文菜单中菜单项被点击是触发该方法
* @param item
* @return
*/
@Override
public boolean onContextItemSelected(MenuItem item) {
// 勾选该菜单项
item.setChecked(true);
switch (item.getItemId()){
case R.id.red:
item.setChecked(true);
tvMenu.setBackgroundColor(Color.RED);
break;
case R.id.green:
item.setChecked(true);
tvMenu.setBackgroundColor(Color.GREEN);
break;
case R.id.blue:
item.setChecked(true);
tvMenu.setBackgroundColor(Color.BLUE);
break;
}
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.isCheckable()){
// 勾选该菜单项
item.setChecked(true);
}
// 判断单击的是那个菜单项,并有针对性的作出响应
switch (item.getItemId()){
case R.id.menu_01:
tvMenu.setText("menu_01");
break;
case R.id.menu_02:
tvMenu.setText("menu_02");
break;
case R.id.menu_03:
tvMenu.setText("menu_03");
break;
case R.id.plain_item:
tvMenu.setText("plain_item");
break;
}
return true;
}
样式资源
Style资源保存在/res/style/文件夹下,其根元素为 resource 元素,该元素可包含多个 style 子元素,每个 style 元素定义一个样式。style 一般可指定如下两个属性:
name:样式名
parent:指定该样式所继承的父样式,此时的继承符合Java的继承规则。
style元素可以包含多个 item 元素,每一个 item 元素定义一个格式项。
示例:
主题资源
与样式资源非常类似,保存在/res/values/目录下,以 resource 元素为根元素,style 元素为子元素。
其与样式资源的区别主要体现在:
主题不能作用于单个View,主题应对整个应用中的所有Activity起作用,或者对指定的Activity起作用。
主题定义的格式应该是改变窗口外观的格式,例如窗口标题、窗口外观等。
属性资源
属性资源文件保存在/res/values/文件夹下,其根元素也是 resource 元素,resource 元素包含下述两个子元素:
attr 子元素:定义一个属性
declare-styleable子元素:定义一个styleable对象,每个styleable对象就是一组attr属性集合
在自定义组件的构造器中通过AttributeSet对象来获取属性。
示例:
package com.fpp.status.customview;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.widget.ImageView;
import com.fpp.status.R;
import java.util.Timer;
import java.util.TimerTask;
/**
* @author fupengpeng
* @description 描述
* @data 2018/4/18 0018 15:26
*/
public class AlphaImageView extends ImageView {
// 图片透明度每次改变的大小
private int alphaDelta = 0;
// 记录图片当前的透明度
private int curAlpha = 0;
// 每隔多少毫秒透明度改变一次
private final int SPEED = 300;
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
if (msg.what == 0x123){
// 每次增加curAlpha的值
curAlpha += alphaDelta;
if (curAlpha > 255){
curAlpha = 255;
}
// 修改该ImageView的透明度
AlphaImageView.this.setAlpha(curAlpha);
}
}
};
public AlphaImageView(Context context, AttributeSet attrs){
super(context,attrs);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AlphaImageView);
// 获取duration参数
int duration = typedArray.getInt(R.styleable.AlphaImageView_duration,0);
// 计算图片透明度每次改变的大小
alphaDelta = 255 * SPEED / duration;
}
@Override
protected void onDraw(Canvas canvas) {
this.setImageAlpha(curAlpha);
super.onDraw(canvas);
final Timer timer = new Timer();
// 按固定间隔发送消息,通知系统改变图片的透明度
timer.schedule(new TimerTask() {
@Override
public void run() {
Message msg = new Message();
msg.what = 0x123;
if (curAlpha >= 255){
timer.cancel();
}else {
handler.sendMessage(msg);
}
}
},0,SPEED);
}
}
原始资源
除了上述各资源以外,Android可能还用到其他资源(例如声音等),而这些资源一般保存在下述两个目录下:
位于 /res/raw/ 目录下,Android SDK 会处理该目录下的原始资源,Android SDK 会在R清单类中为该目录下的资源生成一个索引项。其在Java代码中和XML中使用同上述资源类似。
位于 /assets/ 目录下,该目录下是更加彻底的原始资源,Android应用通过AssetManager来管理该目录下的原始资源。AssetManager是一个专门管理 /assets/ 目录下的原始资源的管理器类,一般使用 InputStream open(String fileName)方法(获取资源文件的输入流)和AssetFileDescriptor openFd(String fileName)方法(获取对资源文件进行描述的对应的AssetFileDescriptor对象,再通过AssetFileDescriptor对象获取原始资源。)来获取对应的资源文件。
示例:
// 播放assets文件夹下的声音文件
public void assets(View resource) {
// 获取应用的AssetManager
AssetManager am = getAssets();
try {
// 获取指定文件对应的AssetFileDescriptor
AssetFileDescriptor afd = am.openFd("haojiubujian.mp3");
MediaPlayer mediaPlayer2 = new MediaPlayer();
// 使用MediaPlayer加载指定的声音文件
mediaPlayer2.setDataSource(afd.getFileDescriptor());
mediaPlayer2.prepare();
// 播放声音
mediaPlayer2.start();
} catch (IOException e) {
e.printStackTrace();
}
}
// 播放raw文件夹下的声音文件
public void raw(View resource) {
// 直接根据声音文件的id来创建MediaPlayer
MediaPlayer mediaPlayer1 = MediaPlayer.create(this, R.raw.haojiubujian);
// 播放声音
mediaPlayer1.start();
}
/**
* 播放raw文件夹下视频文件
*/
private void playRawVideo() {
mVideoView.setVideoURI(Uri.parse("android.resource://" + getPackageName() + "/raw/" + R.raw.massif));
mVideoView.start();
}