一、View Animation动画源码简析——Animation对象获取。

一、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的对象完成创建。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值