SOUI 属性动画 (PropertyAnimator)¶
概述¶
SOUI 属性动画(SPropertyAnimator)是基于 Android ObjectAnimator 设计的动画类,可以直接操作控件的各种属性。它是 SValueAnimator 的子类,专门用于对控件属性进行动画处理,是 SOUI 动画系统中最常用的动画类型之一。
属性动画通过 SPropertyValuesHolder 来持有和计算属性值,使得开发者可以轻松地对控件的任何属性进行动画处理。
核心概念¶
SPropertyValuesHolder¶
SPropertyValuesHolder 是属性值持有者,负责:
- 存储动画的关键帧值
- 计算特定时间点的属性值
- 管理属性名称和类型
支持的数据类型¶
属性动画支持多种数据类型:
- 整数(INT)
- 浮点数(FLOAT)
- 字节(BYTE)
- 短整型(SHORT)
- 颜色(COLORREF)
- 布局尺寸(LAYOUTSIZE)
- 位置(POSITION)
主要方法¶
| 方法 | 描述 |
|---|---|
| ofFloat(IWindow pWnd, LPCWSTR propertyName, const float values, int valueCount) | 创建浮点属性动画 |
| ofInt(IWindow pWnd, LPCWSTR propertyName, const int values, int valueCount) | 创建整数属性动画 |
| ofLayoutSize(IWindow pWnd, LPCWSTR propertyName, const SLayoutSize values, int valueCount) | 创建布局尺寸属性动画 |
| ofPosition(IWindow pWnd, LPCWSTR propertyName, const void values, int valueCount, int valueSize) | 创建位置属性动画 |
| ofPropertyValuesHolder(IWindow pWnd, IPropertyValuesHolder *propertyHolders, int holderCount) | 使用属性值持有者创建动画 |
| GetTarget() | 获取动画目标控件 |
| SetPropertyValuesHolder(IPropertyValuesHolder *pHolder) | 设置单个属性值持有者 |
| SetPropertyValuesHolders(IPropertyValuesHolder **pHolders, int count) | 设置多个属性值持有者 |
使用示例¶
基础属性动画¶
// 透明度动画 - 从完全透明到完全不透明
float alphaValues[] = {0.0f, 1.0f};
IPropertyAnimator* alphaAnimator = SPropertyAnimator::ofFloat(
pWindow,
LayoutProperty::ALPHA,
alphaValues,
2
);
alphaAnimator->setDuration(500);
alphaAnimator->start(pTimelineHandler);
// 宽度动画 - 从100dp到300dp
SLayoutSize widthValues[] = {
SLayoutSize(100.0f, dp),
SLayoutSize(300.0f, dp)
};
IPropertyAnimator* widthAnimator = SPropertyAnimator::ofLayoutSize(
pWindow,
LayoutProperty::WIDTH,
widthValues,
2
);
widthAnimator->setDuration(1000);
widthAnimator->start(pTimelineHandler);
多属性动画¶
// 同时动画宽度和高度
SLayoutSize widthValues[] = {
SLayoutSize(100.0f, dp),
SLayoutSize(200.0f, dp)
};
SLayoutSize heightValues[] = {
SLayoutSize(50.0f, dp),
SLayoutSize(100.0f, dp)
};
// 创建属性值持有者
IPropertyValuesHolder* pWidthHolder = SPropertyValuesHolder::ofLayoutSize(
LayoutProperty::WIDTH, widthValues, 2);
IPropertyValuesHolder* pHeightHolder = SPropertyValuesHolder::ofLayoutSize(
LayoutProperty::HEIGHT, heightValues, 2);
IPropertyValuesHolder* holders[] = { pWidthHolder, pHeightHolder };
// 创建多属性动画器
IValueAnimator* pAnimator = SPropertyAnimator::ofPropertyValuesHolder(
pWindow, holders, 2);
if (pAnimator)
{
pAnimator->setDuration(1200);
pAnimator->start(pTimelineHandler);
pAnimator->Release();
}
pWidthHolder->Release();
pHeightHolder->Release();
路径动画¶
路径动画是属性动画的重要应用,允许控件沿着指定路径移动:
// 定义路径上的关键点
AnchorPos pos[] = {
{ APT_Left_Top, SLayoutSize(0, SLayoutSize::px), SLayoutSize(0, SLayoutSize::px), 0, 0 }, // 起点
{ APT_Center_Center, SLayoutSize(150, SLayoutSize::px), SLayoutSize(100, SLayoutSize::px), -0.5f, -0.5f }, // 中点
{ APT_Right_Bottom, SLayoutSize(300, SLayoutSize::px), SLayoutSize(0, SLayoutSize::px), 0, 0 } // 终点
};
// 创建路径动画
IPropertyAnimator* pathAnimator = SPropertyAnimator::ofPosition(
pWindow, // 目标控件
LayoutProperty::POSITION, // 属性名
pos, // 关键点数组
ARRAYSIZE(pos), // 关键点数量
sizeof(AnchorPos) // 数据结构大小
);
pathAnimator->setDuration(2000); // 设置动画时长为2秒
pathAnimator->start(pTimelineHandler);
复杂路径动画¶
在实际应用中,我们经常需要同时对多个属性进行动画处理:
// 定义位置关键点
AnchorPos pos[] = {
{ APT_Left_Top, SLayoutSize(0, SLayoutSize::px), SLayoutSize(0, SLayoutSize::px), 0, 0 },
{ APT_Center_Center, SLayoutSize(150, SLayoutSize::px), SLayoutSize(100, SLayoutSize::px), -0.5f, -0.5f },
{ APT_Right_Bottom, SLayoutSize(300, SLayoutSize::px), SLayoutSize(0, SLayoutSize::px), 0, 0 }
};
// 创建位置属性持有者
IPropertyValuesHolder* pPosHolder = SPropertyValuesHolder::ofPosition(
LayoutProperty::POSITION,
pos,
ARRAYSIZE(pos),
sizeof(AnchorPos)
);
// 定义透明度关键点
BYTE alpha[] = { 255, 128, 0 }; // 从不透明到半透明再到完全透明
IPropertyValuesHolder* pAlphaHolder = SPropertyValuesHolder::ofByte(
WindowProperty::ALPHA,
alpha,
3
);
// 将多个属性持有者组合成一个动画
IPropertyValuesHolder* holders[] = { pPosHolder, pAlphaHolder };
IValueAnimator* animator = SPropertyAnimator::ofPropertyValuesHolder(
pWindow, // 目标控件
holders, // 属性持有者数组
ARRAYSIZE(holders) // 属性持有者数量
);
animator->setDuration(2000);
animator->start(pTimelineHandler);
// 记得释放资源
pPosHolder->Release();
pAlphaHolder->Release();
权重动画示例¶
// 权重动画 - 从0.5到2.0
float values[] = { 0.5f, 2.0f };
IValueAnimator* pAnimator = SPropertyAnimator::ofFloat(
pWindow,
LayoutProperty::WEIGHT,
values,
2
);
if (pAnimator)
{
pAnimator->setDuration(1500);
pAnimator->start(pTimelineHandler);
pAnimator->Release();
}
propanimator_demo 示例¶
在 propanimator_demo 示例中,我们可以看到多种属性动画的使用:
void CMainDlg::OnBtnAnimation()
{
SWindow * pWnd_left_top = FindChildByName(L"win_left_top");
SWindow * pWnd_right_top = FindChildByName(L"win_right_top");
SWindow * pWnd_left_bottom = FindChildByName(L"win_left_bottom");
SWindow * pWnd_right_bottom = FindChildByName(L"win_right_bottom");
SWindow * pWnd_center = FindChildByName(L"win_center");
AnchorPos anchorPos[5];
_GetWindowAnchorPos(pWnd_left_top, anchorPos+0);
_GetWindowAnchorPos(pWnd_right_top, anchorPos+1);
_GetWindowAnchorPos(pWnd_left_bottom, anchorPos+2);
_GetWindowAnchorPos(pWnd_right_bottom, anchorPos+3);
_GetWindowAnchorPos(pWnd_center, anchorPos+4);
// 动画:左上角窗口到中心再到左下角
AnchorPos pos[] = {
anchorPos[0],
anchorPos[4],
anchorPos[2]
};
IPropertyAnimator *pAnimator = SPropertyAnimator::ofPosition(
pWnd_left_top,
LayoutProperty::POSITION,
pos,
ARRAYSIZE(pos),
sizeof(AnchorPos)
);
// 设置权重,控制关键帧的动画时间分布
float weights[] = { 1.0f, 5.0f }; // 第二段动画比第一段慢5倍
pAnimator->GetPropertyValuesHolderByIndex(0)->SetKeyFrameWeights(weights, ARRAYSIZE(weights));
pAnimator->setDuration(2000);
pAnimator->start(this);
pAnimator->Release();
}
关键帧权重¶
通过 SetKeyFrameWeights 方法可以设置关键帧的权重,控制动画在不同关键帧之间的过渡时间:
// 设置关键帧权重,让动画在第二个关键帧停留更长时间
float weights[] = { 1.0f, 5.0f }; // 第二段动画比第一段慢5倍
pAnimator->GetPropertyValuesHolderByIndex(0)->SetKeyFrameWeights(weights, ARRAYSIZE(weights));
最佳实践¶
- 使用合适的属性名称:确保属性名称与控件支持的属性匹配
- 合理设置关键帧:根据动画需求设置适当数量的关键帧
- 控制动画时长:确保动画时长符合用户体验需求
- 使用权重优化动画:通过权重调整动画在关键帧间的过渡
- 及时释放资源:使用完毕后及时释放动画对象
- 避免过度动画:不要对太多属性同时进行动画,以免影响性能
总结¶
SPropertyAnimator 是 SOUI 中最常用的动画类型,它直接操作控件的属性,使得动画实现变得简单而强大。通过 SPropertyValuesHolder,可以灵活地控制动画的关键帧和过渡效果。开发者可以使用它来实现各种复杂的属性动画,包括位置、尺寸、透明度等的动画效果。