前言
上篇文章我们介绍的View动画的基础用法,其中还有很多地方需要我们理解和应用。比如:pivot属性偏移规则、动画实际应用等....
pivot属性
pivot属性取值 | 含义 |
---|---|
10 | 距离动画所在view自身左边缘偏移10像素 |
10% | 距离动画所在view自身左边缘偏移值是整个view宽度的10% |
10%p | 距离动画所在view自身左边缘偏移值是整个父view宽度的10% |
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:interpolator="@android:anim/linear_interpolator"
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="0.0"
android:pivotY="0.0"/>
这个动画的含义是在1000毫秒内 匀速的 旋转View 从0°开始-360°结束度,中轴点X坐标为0.0,中轴点Y坐标为0.0
ezgif.com-video-to-gif (1).gif
我去 他不是该自己转个圈吗?怎么会这样!what?
哈哈 没毛病,View的X轴和Y轴是从左边顶点开始计算的
不明白的看图!
如果我们想要它转一圈怎么办?那我们就改把pivot属性设置为:
android:pivotX="50%"
android:pivotY="50%"
让X轴和Y轴偏移到View的2/1处,它就会围绕着View中心点旋转了。
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:interpolator="@android:anim/linear_interpolator"
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="50%"/>
ezgif.com-video-to-gif (3).gif
我们马上可以联想到pivotX="50%p",就是在父View中间转一圈?试一试~!
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:interpolator="@android:anim/linear_interpolator"
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%p"
android:pivotY="0.0"/>
ezgif.com-video-to-gif.gif
哈哈,怎么移动到屏幕外了?
其实它不是相对于父View的0.0,0.0点偏移。。而是View本身的中轴点X坐标的0.0点 + 父View的width *50 % 的50%所以就会偏移到屏幕外边。光说不顶用啊!去验证一下!
我们就通过源码来解析下把
我们先通过java代码创建一个Rotate动画
RotateAnimation rotateAnimation=new RotateAnimation(0.0f,360.0f,
Animation.RELATIVE_TO_PARENT,0.5f,Animation.RELATIVE_TO_PARENT,0.5f);
相当于XML属性
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%p"
android:pivotY="50%p"
他调用的构造方法为
public RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue,
int pivotYType, float pivotYValue) {
mFromDegrees = fromDegrees;
mToDegrees = toDegrees;
mPivotXValue = pivotXValue;
mPivotXType = pivotXType;
mPivotYValue = pivotYValue;
mPivotYType = pivotYType;
initializePivotPoint();
}
然后除了简单的赋值外,它调用initializePivotPoint(); 方法。
/**
* Called at the end of constructor methods to initialize, if possible, values for
* the pivot point. This is only possible for ABSOLUTE pivot values.
*/
private void initializePivotPoint() {
if (mPivotXType == ABSOLUTE) {
mPivotX = mPivotXValue;
}
if (mPivotYType == ABSOLUTE) {
mPivotY = mPivotYValue;
}
}
通过这个方法注释我们知道了
Called at the end of constructor methods to initialize
它会在构造函数的最后调用方法initialize();
This is only possible for ABSOLUTE pivot values.
这个方法只适用于mPivotYType == ABSOLUTE的情况下
@Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
mPivotX = resolveSize(mPivotXType, mPivotXValue, width, parentWidth);
mPivotY = resolveSize(mPivotYType, mPivotYValue, height, parentHeight);
}
这个方法就很简单了
直接去调用了resolveSize()方法,我们就去看看resolveSize()方法怎么实现的吧!
/**
* Convert the information in the description of a size to an actual
* dimension
*
* @param type One of Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
* Animation.RELATIVE_TO_PARENT.
* @param value The dimension associated with the type parameter
* @param size The size of the object being animated
* @param parentSize The size of the parent of the object being animated
* @return The dimension to use for the animation
*/
protected float resolveSize(int type, float value, int size, int parentSize) {
switch (type) {
case ABSOLUTE:
return value;
case RELATIVE_TO_SELF:
return size * value;
case RELATIVE_TO_PARENT:
return parentSize * value;
default:
return value;
}
}
这样就很清楚的知道他的套路了
调用处:resolveSize(mPivotXType, mPivotXValue, width, parentWidth);
case RELATIVE_TO_SELF:
return size * value;
//TYPE为RELATIVE_TO_SELF 就是 它的width*PivotXValue
case RELATIVE_TO_PARENT:
return parentSize * value;
//RELATIVE_TO_PARENT 就是 它的parentWidth*PivotXValue
我们得出结论:
android:pivotX="50%p"
就是从他View X中轴点+parentSize * value
父View的宽度*50%+当前View的X点
网友评论