一、Animation动画对象的创建
我们通常以这样的形式创建一个Animation动画对象:
Animation mAnimationScale = AnimationUtils.loadAnimation(this, R.anim.scale);
这里调用了AnimationUtils.class的loadAnimation()方法来创建动画对象,那么他的创建流程是怎么样的呢?我们跟进去看看,该方法的源码如下:
public static Animation loadAnimation(Context context, @AnimRes int id) throws NotFoundException {
XmlResourceParser parser = null;
try {
parser = context.getResources().getAnimation(id);
return createAnimationFromXml(context, parser);
} catch (XmlPullParserException ex) {
NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" + Integer.toHexString(id));
rnf.initCause(ex);
throw rnf;
} catch (IOException ex) {
NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" + Integer.toHexString(id));
rnf.initCause(ex);
throw rnf;
} finally {
if (parser != null) parser.close();
}
}
这里我们可以看到虽然代码一大堆,但有实质作用的代码就这三行:
XmlResourceParser parser = null;还有try{}语句块里面的两行,仅此而已,其他的都是在处理异常。我们不追究他。
XmlResourceParser,在查看他的源码之前,我们来猜一猜他是做什么的。按照字面意思来,他意为:xml资源解析。点进去一看,其实他就一个接口:
public interface XmlResourceParser extends XmlPullParser, AttributeSet, AutoCloseable {
public void close();
}
里面除了一个 close()空方法,什么也没有做。
我们继续看下一段重要代码:
parser = context.getResources().getAnimation(id);
这里通过Resources.class的getAnimation(id)方法返回XmlResourceParser对象:
public XmlResourceParser getAnimation(@AnimRes int id) throws NotFoundException {
return loadXmlResourceParser(id, "anim");
}
而loadXmlResourceParser()方法有两个参数,一个是id,也就是我们通过xml创建的动画的id;另一个是一个字符串:“anim”,不自在各位看官看到这个字符串的第一反应是什么,我的直接反应就是:他是xml动画所存放的位于res文件夹下面的一个文件夹:
再来看loadXmlResourceParser()方法:
@NonNull
XmlResourceParser loadXmlResourceParser(@AnyRes int id, @NonNull String type) throws NotFoundException {
final TypedValue value = obtainTempTypedValue();
try {
final ResourcesImpl impl = mResourcesImpl;
impl.getValue(id, value, true);
if (value.type == TypedValue.TYPE_STRING) {
return impl.loadXmlResourceParser(value.string.toString(), id,
value.assetCookie, type);
}
throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id) + " type #0x" + Integer.toHexString(value.type) + " is not valid");
} finally {
releaseTempTypedValue(value);
}
}
这里就是确认我们的动画xml文件是不是在指定的anim文件夹下,若否抛出异常。然后,解析我们的xml动画,返回一个XmlResourceParser对象。
然后我们继续看获得Parser对象后的createAnimationFromXml()方法:
private static Animation createAnimationFromXml(Context c, XmlPullParser parser) throws XmlPullParserException, IOException {
return createAnimationFromXml(c, parser, null, Xml.asAttributeSet(parser));
}
这里很简单,仅仅调用了createAnimationFromXml()方法。那我们再往createAnimationFromXml(c, parser, null, Xml.asAttributeSet(parser))里面看:
private static Animation createAnimationFromXml(Context c, XmlPullParser parser, AnimationSet parent, AttributeSet attrs) throws XmlPullParserException, IOException {
Animation anim = null;
int type;
int depth = parser.getDepth();
while (((type=parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
if (type != XmlPullParser.START_TAG) {
continue;
}
String name = parser.getName();
if (name.equals("set")) {
anim = new AnimationSet(c, attrs);
createAnimationFromXml(c, parser, (AnimationSet)anim, attrs);
} else if (name.equals("alpha")) {
anim = new AlphaAnimation(c, attrs);
} else if (name.equals("scale")) {
anim = new ScaleAnimation(c, attrs);
} else if (name.equals("rotate")) {
anim = new RotateAnimation(c, attrs);
} else if (name.equals("translate")) {
anim = new TranslateAnimation(c, attrs);
} else {
throw new RuntimeException("Unknown animation name: " + parser.getName());
}
if (parent != null) {
parent.addAnimation(anim);
}
}
return anim;
}
这个方法的代码稍长,不过不急,我们捡重要的看。
**首先是创建一个Animation变量anim。
然后,通过parser.getName()获取动画的种类名称name。
最后再让name与5种常见的动画种类做匹配并new出对应种类的动画(set,alpha, scale, rotate, translate):
if (name.equals("set")) {
anim = new AnimationSet(c, attrs);
createAnimationFromXml(c, parser, (AnimationSet)anim, attrs);
} else if (name.equals("alpha")) {
anim = new AlphaAnimation(c, attrs);
} else if (name.equals("scale")) {
anim = new ScaleAnimation(c, attrs);
} else if (name.equals("rotate")) {
anim = new RotateAnimation(c, attrs);
} else if (name.equals("translate")) {
anim = new TranslateAnimation(c, attrs);
} else {
throw new RuntimeException("Unknown animation name: " + parser.getName());
}
如果name与上面的5种都不配不上,那么就抛出异常:
throw new RuntimeException("Unknown animation name: " + parser.getName());
若匹配到其中一种,就创建该种动画,并将对象anim返回。自此,动画Animation的对象完成创建。