Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
Docs
提交
42ea48d9
D
Docs
项目概览
OpenHarmony
/
Docs
1 年多 前同步成功
通知
159
Star
292
Fork
28
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
Docs
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
未验证
提交
42ea48d9
编写于
5月 11, 2023
作者:
O
openharmony_ci
提交者:
Gitee
5月 11, 2023
浏览文件
操作
浏览文件
下载
差异文件
!18122 新增案例【不需要翻译】
Merge pull request !18122 from duangavin123/master
上级
c7e71f41
27e72dc4
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
439 addition
and
0 deletion
+439
-0
zh-cn/third-party-cases/Readme-CN.md
zh-cn/third-party-cases/Readme-CN.md
+2
-0
zh-cn/third-party-cases/figures/background.png
zh-cn/third-party-cases/figures/background.png
+0
-0
zh-cn/third-party-cases/figures/frameanimation.gif
zh-cn/third-party-cases/figures/frameanimation.gif
+0
-0
zh-cn/third-party-cases/figures/man.png
zh-cn/third-party-cases/figures/man.png
+0
-0
zh-cn/third-party-cases/figures/navigation-drawer.gif
zh-cn/third-party-cases/figures/navigation-drawer.gif
+0
-0
zh-cn/third-party-cases/figures/navigation-drawer1.PNG
zh-cn/third-party-cases/figures/navigation-drawer1.PNG
+0
-0
zh-cn/third-party-cases/figures/navigation-drawer2.png
zh-cn/third-party-cases/figures/navigation-drawer2.png
+0
-0
zh-cn/third-party-cases/how-to-develop-frame-animation.md
zh-cn/third-party-cases/how-to-develop-frame-animation.md
+278
-0
zh-cn/third-party-cases/navigation-drawer.md
zh-cn/third-party-cases/navigation-drawer.md
+159
-0
未找到文件。
zh-cn/third-party-cases/Readme-CN.md
浏览文件 @
42ea48d9
...
...
@@ -13,6 +13,8 @@
-
[
如何为同一组件在不同场景下绑定不同的业务逻辑
](
different-operations-for-one-component.md
)
-
[
如何实现列表项滑动显示快捷菜单
](
listitem-slide-to-display-menu.md
)
-
[
如何在网格组件中通过拖拽交换子组件的位置
](
griditem-drag-and-drop.md
)
-
[
如何实现逐帧动画
](
how-to-develop-frame-animation.md
)
-
[
如何实现抽屉式导航
](
navigation-drawer.md
)
### 网络管理
-
[
如何请求并加载网络图片
](
how-to-load-images-from-internet.md
)
...
...
zh-cn/third-party-cases/figures/background.png
0 → 100644
浏览文件 @
42ea48d9
13.9 KB
zh-cn/third-party-cases/figures/frameanimation.gif
0 → 100644
浏览文件 @
42ea48d9
269.5 KB
zh-cn/third-party-cases/figures/man.png
0 → 100644
浏览文件 @
42ea48d9
7.1 KB
zh-cn/third-party-cases/figures/navigation-drawer.gif
0 → 100644
浏览文件 @
42ea48d9
110.7 KB
zh-cn/third-party-cases/figures/navigation-drawer1.PNG
0 → 100644
浏览文件 @
42ea48d9
10.3 KB
zh-cn/third-party-cases/figures/navigation-drawer2.png
0 → 100644
浏览文件 @
42ea48d9
6.1 KB
zh-cn/third-party-cases/how-to-develop-frame-animation.md
0 → 100644
浏览文件 @
42ea48d9
# 如何实现逐帧动画
## 场景说明
逐帧动画是常见的一种动画呈现形式,本例就为大家介绍如何通过translate(),setInterval(),clearAllInterval()等方法实现逐帧动画。
## 效果呈现
本例最终效果如下:
-
点击“run”按钮,火柴人开始走动。
-
点击“stop”按钮,火柴人停止走动。
![
frameanimation
](
figures/frameanimation.gif
)
## 运行环境
-
IDE:DevEco Studio 3.1 Beta1
-
SDK:Ohos_sdk_public 3.2.11.9 (API Version 9 Release)
## 实现思路
本例的实现有两个关键点:
-
将连续走动的火柴人拆分为多帧静态图像,在固定的时间间隔内逐帧将图像移动到动画窗口,间隔时间要小于肉眼可察觉的时间。循环上述动作,就可以实现火柴人的走动动画。
火柴人静态图像如下:
!
[
man
](
figures/man.png
)
-
将背景图片以固定速度相对于火柴人走动方向反方向移动,从而实现火柴人向前走动的效果。
背景图如下:
![
background
](
figures/background.png
)
本例使用translate()控制火柴人的移动,用backgroundImagePosition()控制背景图的移动。另外,通过setInterval()设置火柴人移动的时间间隔,通过clearAllInterval()清除移动。
## 开发步骤
1.
搭建UI框架。
使用两个Row组件分别呈现背景图和火柴人,第二个Row组件作为第一个Row组件的子组件,父Row组件的背景设置为背景图,子Row组件中添加Image组件用来呈现火柴人单帧图像。
```
ts
@
Entry
@
Component
export
default
struct
frameAnimation
{
build
()
{
Column
()
{
// 父Row组件
Row
()
{
// 子Row组件
Row
()
{
// 通过Image组件显示火柴人图像
Image
(
$r
(
"
app.media.man
"
)).
height
(
60
).
width
(
545.16
)
}.
width
(
100
)
.
justifyContent
(
FlexAlign
.
Start
)
.
alignItems
(
VerticalAlign
.
Top
)
// 截取显示与背景同等大小的区域,控制单个火柴人显示在画面中
.
clip
(
true
)
}
// 添加背景图像
.
backgroundImage
(
$r
(
"
app.media.background
"
))
// 保持宽高比进行缩小或者放大,使得图片两边都大于或等于显示边界。
.
backgroundImageSize
(
ImageSize
.
Cover
)
.
width
(
'
100%
'
)
.
height
(
130
)
.
justifyContent
(
FlexAlign
.
Center
)
.
alignItems
(
VerticalAlign
.
Bottom
)
Row
()
{
// 添加跑动按钮
Button
(
'
run
'
)
.
margin
({
right
:
10
})
.
type
(
ButtonType
.
Normal
)
.
width
(
75
)
.
borderRadius
(
5
)
// 添加停止按钮
Button
(
'
stop
'
)
.
type
(
ButtonType
.
Normal
)
.
borderRadius
(
5
)
.
width
(
75
)
.
backgroundColor
(
'
#ff0000
'
)
}.
margin
({
top
:
30
,
bottom
:
10
})
}.
width
(
'
100%
'
).
width
(
'
100%
'
).
padding
({
top
:
30
})
}
}
```
2.
添加火柴人和背景图片的移动逻辑。
通过状态变量设定火柴人和背景图片的位置,位置变化时可以实时刷新UI界面。
```
ts
// 火柴人位置变量
@
State
manPostion
:
{
x
:
number
,
y
:
number
}
=
{
x
:
0
,
y
:
0
}
// 背景图位置变量
@
State
treePosition
:
{
x
:
number
,
y
:
number
}
=
{
x
:
0
,
y
:
0
}
```
给火柴人和背景图片添加位置属性。
```
ts
Row
()
{
Row
()
{
Image
(
$r
(
"
app.media.man
"
))
.
height
(
60
)
.
width
(
545.16
)
// 通过translate实现火柴人的位移。绑定manPosition,用来改变火柴人位置。
.
translate
(
this
.
manPostion
)
}
...
}
.
backgroundImage
(
$r
(
"
app.media.background
"
))
.
backgroundImageSize
(
ImageSize
.
Cover
)
// 通过backgroundImagePosition实现背景图片的位移。绑定treePosition,用来改变背景图片的位置。
.
backgroundImagePosition
(
this
.
treePosition
)
...
```
3.
为''run''按钮和"stop"按钮绑定控制逻辑。
构建火柴人和背景图片移动的方法,用来设定火柴人和背景图片每次移动的距离。这里要注意火柴人每次移动的距离等于两个火柴人之间的间隔距离(像素值)。
```
ts
// 火柴人移动方法
manWalk
()
{
if
(
this
.
manPostion
.
x
<=
-
517.902
)
{
this
.
manPostion
.
x
=
0
}
else
{
// 每次移动的距离为火柴人静态图像之间的间隔距离
this
.
manPostion
.
x
-=
129.69
}
}
// 背景移动方法
treesMove
()
{
if
(
this
.
treePosition
.
x
<=
-
1215
)
{
this
.
treePosition
.
x
=
0
}
else
{
this
.
treePosition
.
x
-=
20
}
}
```
创建doAnimation()方法调用上述两个方法,以便在后续的定时器中使用。
```
ts
doAnimation
()
{
this
.
manWalk
()
this
.
treesMove
()
}
```
通过setInterval为“run”按钮绑定走动逻辑。
```
ts
Button
(
'
run
'
)
.
margin
({
right
:
10
})
.
type
(
ButtonType
.
Normal
)
.
width
(
75
)
.
borderRadius
(
5
)
.
onClick
(()
=>
{
this
.
clearAllInterval
()
// 创建定时器,调用doAnimation方法,启动动画
let
timer
=
setInterval
(
this
.
doAnimation
.
bind
(
this
),
100
)
this
.
timerList
.
push
(
timer
)
})
```
通过clearAllInterval为“stop”按钮绑定停止逻辑。
```
ts
Button
(
'
stop
'
)
.
type
(
ButtonType
.
Normal
)
.
borderRadius
(
5
)
.
width
(
75
)
.
backgroundColor
(
'
#ff0000
'
)
.
onClick
(()
=>
{
// 清理定时器,停止动画
this
.
clearAllInterval
()
})
```
## 完整代码
本例完整代码如下:
```
ts
@
Entry
@
Component
export
default
struct
frameAnimation
{
// 火柴人位置变量
@
State
manPostion
:
{
x
:
number
,
y
:
number
}
=
{
x
:
0
,
y
:
0
}
// 背景图位置变量
@
State
treePosition
:
{
x
:
number
,
y
:
number
}
=
{
x
:
0
,
y
:
0
}
// 定时器列表,当列表清空时,动画停止
private
timerList
:
number
[]
=
[]
// 火柴人移动方法
manWalk
()
{
if
(
this
.
manPostion
.
x
<=
-
517.902
)
{
this
.
manPostion
.
x
=
0
}
else
{
this
.
manPostion
.
x
-=
129.69
}
}
// 背景移动方法
treesMove
()
{
if
(
this
.
treePosition
.
x
<=
-
1215
)
{
this
.
treePosition
.
x
=
0
}
else
{
this
.
treePosition
.
x
-=
20
}
}
// 销毁所有定时器
clearAllInterval
()
{
this
.
timerList
.
forEach
((
timer
:
number
)
=>
{
clearInterval
(
timer
)
})
this
.
timerList
=
[]
}
doAnimation
()
{
this
.
manWalk
()
this
.
treesMove
()
}
build
()
{
Column
()
{
// 父Row组件
Row
()
{
// 子Row组件
Row
()
{
// 通过Image组件显示火柴人图像
Image
(
$r
(
"
app.media.man
"
))
.
height
(
60
)
.
width
(
545.16
)
// 通过translate实现火柴人的位移。绑定manPosition变量,用来改变火柴人位置。
.
translate
(
this
.
manPostion
)
}
.
width
(
100
)
.
justifyContent
(
FlexAlign
.
Start
)
.
alignItems
(
VerticalAlign
.
Top
)
// 截取显示与背景同等大小的区域,控制单个火柴人显示在画面中
.
clip
(
true
)
}
// 添加背景图像
.
backgroundImage
(
$r
(
"
app.media.background
"
))
// 保持宽高比进行缩小或者放大,使得图片两边都大于或等于显示边界。
.
backgroundImageSize
(
ImageSize
.
Cover
)
// 通过backgroundImagePosition实现背景图片的位移。绑定treePosition,用来改变背景图片的位置。
.
backgroundImagePosition
(
this
.
treePosition
)
.
width
(
'
100%
'
)
.
height
(
130
)
.
justifyContent
(
FlexAlign
.
Center
)
.
alignItems
(
VerticalAlign
.
Bottom
)
Row
()
{
// 添加跑动按钮
Button
(
'
run
'
)
.
margin
({
right
:
10
})
.
type
(
ButtonType
.
Normal
)
.
width
(
75
)
.
borderRadius
(
5
)
.
onClick
(()
=>
{
this
.
clearAllInterval
()
let
timer
=
setInterval
(
this
.
doAnimation
.
bind
(
this
),
100
)
this
.
timerList
.
push
(
timer
)
})
// 添加停止按钮
Button
(
'
stop
'
)
.
type
(
ButtonType
.
Normal
)
.
borderRadius
(
5
)
.
width
(
75
)
.
backgroundColor
(
'
#ff0000
'
)
.
onClick
(()
=>
{
this
.
clearAllInterval
()
})
}.
margin
({
top
:
30
,
bottom
:
10
})
}.
width
(
'
100%
'
).
width
(
'
100%
'
).
padding
({
top
:
30
})
}
}
```
## 参考
-
[
Timer (定时器)
](
../application-dev/reference/apis/js-apis-timer.md
)
-
[
图形变换
](
../application-dev/reference/arkui-ts/ts-universal-attributes-transformation.md
)
-
[
背景设置
](
../application-dev/reference/arkui-ts/ts-universal-attributes-background.md
)
zh-cn/third-party-cases/navigation-drawer.md
0 → 100644
浏览文件 @
42ea48d9
# 如何实现抽屉式导航
## 场景介绍
由于用户所需功能逐渐增多,传统的标签式导航在个别场景已经无法满足用户需求。当导航栏的空间放不下过多页签时,可以采用抽屉式导航,本例将为大家介绍如何通过SideBarContainer组件实现抽屉式导航。
## 效果呈现
本例最终实现效果如下:
![
navigation-drawer
](
figures/navigation-drawer.gif
)
## 运行环境
-
IDE:DevEco Studio 3.1 Beta1
-
SDK:Ohos_sdk_public 3.2.11.9 (API Version 9 Release)
## 实现思路
-
通过SideBarContainer组件提供容器,通过子组件定义侧边栏和内容区,第一个子组件表示侧边栏,第二个子组件表示内容区。
-
调用showSideBar属性来设置不显示侧边栏,controlButton属性来控制完成侧栏的展示/收起。
![](
figures/navigation-drawer1.PNG
)![](
figures/navigation-drawer2.png
)
## 开发步骤
1.
创建内容区域文本组件。
首先创建内容区,具体代码块如下:
```
ts
...
// 内容区
Column
()
{
Text
(
"
内容区域
"
)
.
width
(
"
100%
"
)
.
height
(
"
100%
"
)
.
fontSize
(
30
)
.
textAlign
(
TextAlign
.
Center
)
}
.
width
(
"
100%
"
)
.
height
(
"
100%
"
)
.
backgroundColor
(
"
#bbaacc
"
)
...
```
2.
通过SideBarContainer所支持的showSideBar属性来设置不显示侧边栏,controlButton属性来控制完成侧栏的展示/收起。
具体代码块如下:
```
ts
...
.
showSideBar
(
false
)
//默认不展示侧边栏,展示icon,用户点击调出
.
controlButton
({
left
:
10
,
// 图标距离左侧宽度
top
:
20
,
// 图标距离顶部高度
height
:
30
,
// 图标高度
width
:
30
,
// 图标宽度
icons
:
{
shown
:
$r
(
'
app.media.back
'
),
// 侧边栏展示时图标
hidden
:
$r
(
'
app.media.sidebar_shown
'
),
// 侧边栏收起时图标
switching
:
$r
(
'
app.media.sidebar_shown
'
)
// 侧边栏切换过程图标
}
})
...
```
3.
创建侧边栏文本组件。
具体代码如下:
```ts
...
struct SideBarContainerExample {
@ State navList: Array<string> = ["我的会员", "我的收藏", "我的相册", "我的文件",]
build() {
SideBarContainer(SideBarContainerType.Embed) {
// 侧边栏内容
Column() {
ForEach(this.navList, (item) => {
Text(item)
.width("100%")
.fontSize(20)
.textAlign(TextAlign.Start)
.padding({ top: 20 })
})
}
.height("100%")
.padding({ top: 60, left: 50 })
.backgroundColor("#aabbcc")
}
...
}
}
```
## 完整代码
示例完整代码如下:
```
ts
@
Entry
@
Component
struct
SideBarContainerExample
{
@
State
navList
:
Array
<
string
>
=
[
"
我的会员
"
,
"
我的收藏
"
,
"
我的相册
"
,
"
我的文件
"
,]
build
()
{
// Embed:侧边栏占据内容空间 Overlay:侧边栏悬浮于内容之上
SideBarContainer
(
SideBarContainerType
.
Embed
)
{
// 侧边栏内容
Column
()
{
ForEach
(
this
.
navList
,
(
item
)
=>
{
Text
(
item
)
.
width
(
"
100%
"
)
.
fontSize
(
20
)
.
textAlign
(
TextAlign
.
Start
)
.
padding
({
top
:
20
})
})
}
.
height
(
"
100%
"
)
.
padding
({
top
:
60
,
left
:
50
})
.
backgroundColor
(
"
#aabbcc
"
)
// 内容区
Column
()
{
Text
(
"
内容区域
"
)
.
width
(
"
100%
"
)
.
height
(
"
100%
"
)
.
fontSize
(
30
)
.
textAlign
(
TextAlign
.
Center
)
}
.
width
(
"
100%
"
)
.
height
(
"
100%
"
)
.
backgroundColor
(
"
#bbaacc
"
)
}
// 默认不展示侧边栏,展示icon,用户点击调出
.
showSideBar
(
false
)
.
controlButton
({
// 图标距离左侧宽度
left
:
10
,
// 图标距离顶部高度
top
:
20
,
// 图标高度
height
:
30
,
// 图标宽度
width
:
30
,
icons
:
{
// 侧边栏展示时图标
shown
:
$r
(
'
app.media.back
'
),
// 侧边栏收起时图标
hidden
:
$r
(
'
app.media.sidebar_shown
'
),
// 侧边栏切换过程图标
switching
:
$r
(
'
app.media.sidebar_shown
'
)
}
})
// 侧边栏宽度
.
sideBarWidth
(
200
)
.
width
(
'
100%
'
)
.
height
(
'
100%
'
)
}
}
```
**注意**
:模拟机与真机的预览有区别,在SideBarContainerType.Embed情况下,真机中内容区域是压缩,模拟器中内容区域是缺失。
## 总结
[
Tabs组件
](
../application-dev/reference/arkui-ts/ts-container-tabs.md
)
: 适用于导航栏固定在页面上下左右侧,入口分类数目不多,可以控制在5个以内,且用户需要频繁切换每一个页签的应用,比如微信、QQ等。
[
Navigation组件
](
../application-dev/reference/arkui-ts/ts-basic-components-navigation.md
)
: 同样可以实现Tabs组件中导航栏位于底部的场景,根据需要显示隐藏导航栏,提供标题,菜单,返回等选项,使用户是使用时更加灵活。
[
sideBarContainer组件
](
../application-dev/reference/arkui-ts/ts-container-sidebarcontainer.md
)
:主要的功能和内容都在一个页面里面,只是一些低频操作内容需要显示在其他页面里,可以把这些辅助功能放在抽屉栏里。屏幕较小时导航栏不占用空间。比如QQ,开发指导文档等。
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录