Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
Docs
提交
1cd6c533
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看板
未验证
提交
1cd6c533
编写于
5月 16, 2023
作者:
O
openharmony_ci
提交者:
Gitee
5月 16, 2023
浏览文件
操作
浏览文件
下载
差异文件
!18247 新增案例【不需要翻译】
Merge pull request !18247 from duangavin123/master
上级
fc41d891
d85b231a
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
821 addition
and
0 deletion
+821
-0
zh-cn/third-party-cases/Readme-CN.md
zh-cn/third-party-cases/Readme-CN.md
+2
-0
zh-cn/third-party-cases/circle-progress-bar.md
zh-cn/third-party-cases/circle-progress-bar.md
+289
-0
zh-cn/third-party-cases/content-changing-with-pulldown.md
zh-cn/third-party-cases/content-changing-with-pulldown.md
+265
-0
zh-cn/third-party-cases/figures/collapsibleeffect.gif
zh-cn/third-party-cases/figures/collapsibleeffect.gif
+0
-0
zh-cn/third-party-cases/figures/jihe.png
zh-cn/third-party-cases/figures/jihe.png
+0
-0
zh-cn/third-party-cases/figures/progressachieved.gif
zh-cn/third-party-cases/figures/progressachieved.gif
+0
-0
zh-cn/third-party-cases/realization-of-collapsible-title-effect.md
...rd-party-cases/realization-of-collapsible-title-effect.md
+265
-0
未找到文件。
zh-cn/third-party-cases/Readme-CN.md
浏览文件 @
1cd6c533
...
@@ -15,6 +15,8 @@
...
@@ -15,6 +15,8 @@
-
[
如何在网格组件中通过拖拽交换子组件的位置
](
griditem-drag-and-drop.md
)
-
[
如何在网格组件中通过拖拽交换子组件的位置
](
griditem-drag-and-drop.md
)
-
[
如何实现逐帧动画
](
how-to-develop-frame-animation.md
)
-
[
如何实现逐帧动画
](
how-to-develop-frame-animation.md
)
-
[
如何实现抽屉式导航
](
navigation-drawer.md
)
-
[
如何实现抽屉式导航
](
navigation-drawer.md
)
-
[
如何实现内容下拉变化
](
content-changing-with-pulldown.md
)
-
[
如何实现圆形进度条
](
circle-progress-bar.md
)
### 网络管理
### 网络管理
-
[
如何请求并加载网络图片
](
how-to-load-images-from-internet.md
)
-
[
如何请求并加载网络图片
](
how-to-load-images-from-internet.md
)
...
...
zh-cn/third-party-cases/circle-progress-bar.md
0 → 100644
浏览文件 @
1cd6c533
# 如何实现波纹进度条
## 场景说明
应用开发过程中经常用到波纹进度条,常见的如充电进度、下载进度、上传进度等,本例即为大家介绍如何实现上述场景。
## 效果呈现
本示例最终效果如下:
![](
figures/progressachieved.gif
)
## 运行环境
本例基于以下环境开发,开发者也可以基于其他适配的版本进行开发:
-
IDE: DevEco Studio 3.1 Beta2
-
SDK: Ohos_sdk_public 3.2.11.9(API Version 9 Release)
## 实现思路
本示例涉及4个主要特性及其实现方案如下:
-
进度条的圆形外框:使用Circle组件绘制外层圆环,实现外层框架。
-
圆框内进度数值变化:使用setInterval()让进度值持续递增控制进度数据变化(本案例未提供实时数据来源,所以直接通过数据递增来呈现效果)。
-
圆框水纹区域绘制:通过Path组件的绘制命令(M、Q、T)去绘制水纹形状并对中间进行填充。
-
底部进度条展示(主要用于跟波纹进度对比展示,方便大家理解):使用Slider组件绘制进度条。
## 开发步骤
针对上述所提到的内容,具体实现步骤如下:
1.
先使用Cricle组件绘制外层的圆环
具体代码块如下:
```
ts
...
// 外框圆环
Circle
({
width
:
BIG_DIAMETER
,
height
:
BIG_DIAMETER
})
.
fill
(
COLOR_TRANSPARENT
)
// 填充:透明
.
stroke
(
'
#007DFF
'
)
//圆环颜色
.
strokeWidth
(
5
)
//圆环环宽
...
```
2.
通过setInterval()方法让outSetValue值一直增加到100,使进度在规定时间内完成,最后通过clearInterval结束自增。
具体代码块如下:
```
ts
...
aboutToAppear
()
{
this
.
test
()
}
test
()
{
let
timer
=
setInterval
(()
=>
{
//开始定时
if
(
this
.
outSetValue
<
100
)
{
//进度值每次+1
this
.
outSetValue
+=
1
//进度显示
if
(
this
.
outSetValue
==
100
)
{
this
.
backGroundColor
=
COLOR_BACKGROUND_FILL
this
.
pathCommands
=
''
;
}
else
{
this
.
backGroundColor
=
COLOR_TRANSPARENT
this
.
pathCommands
=
this
.
calPathCommands
(
this
.
outSetValue
);
}
}
else
{
clearInterval
(
timer
)
//取消定时
}
},
100
)
}
...
```
3.
通过方程表达进度百分比和y的关系,通过Path组件的路径绘制命令(M、Q、T)去绘制路径生成封闭的自定义形状并对中间进行填充。
中间的填充有两个状态:
1.在进度100%时时填充颜色的圆形。
2.在进度不是100%时,使用Path组件绘制闭合曲线实现。
在使用Path组件绘制路径时的计算过程和相关函数的使用如下(坐标系以Path组件的左上角为坐标原点):
![](figures/jihe.png)
- 进度百分比和y的关系:y = (1-k)* 2r。
- 圆心点的坐标是(r, r),使用圆方程就可以计算出圆弧的起点和终点。
- 使用 A(rx ry x-axis-rotation large-arc-flag sweep-flag x y) 绘制圆弧,注意点就是在过圆心之后,需要反转下绘制角度。
- 使用 Q(x1 y1 x y) 和 T(x, y) 绘制对应的波浪,最后闭合路径然后填充颜色。
具体代码块如下:
```ts
...
onPageShow() {
//校准的路径指令与进度值
this.pathCommands = this.calPathCommands(this.outSetValue);
}
calXSquare(y: number) {
return RADIUS_IN_PX * RADIUS_IN_PX - (y - RADIUS_IN_PX) * (y - RADIUS_IN_PX);
}
calY(k: number) {
return (1 - k) * RADIUS_IN_PX * 2;//返回值为百分比
}
formatPathCommands(x1: number, x2: number, y: number, radius: number) {
//填充区域波浪线
return `M${x1} ${y} A${radius} ${radius} 0 ${y > RADIUS_IN_PX ? 0 : 1} 0 ${x2} ${y} `
+ `Q${(x1 + 3 * x2) / 4} ${y + 12.5 * (x2 - x1) / radius}, ${(x1 + x2) / 2} ${y} T${x1} ${y}`
}
calPathCommands(value: number) {
let y = this.calY(value / 100.0)
let squareX = this.calXSquare(y)
if (squareX >= 0) {
let x = Math.sqrt(squareX);
let x1 = RADIUS_IN_PX - x;
let x2 = RADIUS_IN_PX + x;
return this.formatPathCommands(x1, x2, y, RADIUS_IN_PX);
}
return "";
}
...
```
4.
绘制下方滑动条组件
具体代码块如下:
```
ts
...
Row
()
{
Slider
({
value
:
this
.
outSetValue
,
min
:
0
,
max
:
100
,
step
:
1
,
style
:
SliderStyle
.
OutSet
})
.
blockColor
(
'
#FFFFFF
'
)
.
trackColor
(
'
#182431
'
)
.
selectedColor
(
'
#007DFF
'
)
.
showSteps
(
true
)
.
showTips
(
true
)
.
onChange
((
value
:
number
,
mode
:
SliderChangeMode
)
=>
{
if
(
this
.
outSetValue
==
0
)
{
this
.
test
()
}
this
.
outSetValue
=
value
//初始状态
if
(
this
.
outSetValue
==
100
)
{
this
.
backGroundColor
=
COLOR_BACKGROUND_FILL
//进度为100时,滑动条拉满,背景全满
this
.
pathCommands
=
''
;
}
else
{
this
.
backGroundColor
=
COLOR_TRANSPARENT
、
this
.
pathCommands
=
this
.
calPathCommands
(
this
.
outSetValue
);
}
console
.
log
(
`value =
${
value
}
->`
+
this
.
pathCommands
);
//进度显示
})
Text
(
this
.
outSetValue
.
toFixed
(
0
)).
fontSize
(
16
)
}
...
```
## 完整代码
具体代码如下:
```
ts
const
COLOR_TRANSPARENT
=
'
#00000000
'
const
COLOR_BACKGROUND_FILL
=
'
#7ebede
'
const
DIAMETER
=
200
;
const
RADIUS_IN_PX
=
vp2px
(
DIAMETER
/
2.0
);
const
BIG_DIAMETER
=
220
;
@
Entry
@
Component
struct
Page3
{
@
State
outSetValue
:
number
=
0
@
State
pathCommands
:
string
=
''
@
State
backGroundColor
:
string
=
'
#00000000
'
onPageShow
()
{
this
.
pathCommands
=
this
.
calPathCommands
(
this
.
outSetValue
);
}
calXSquare
(
y
:
number
)
{
return
RADIUS_IN_PX
*
RADIUS_IN_PX
-
(
y
-
RADIUS_IN_PX
)
*
(
y
-
RADIUS_IN_PX
);
}
calY
(
k
:
number
)
{
return
(
1
-
k
)
*
RADIUS_IN_PX
*
2
;
}
formatPathCommands
(
x1
:
number
,
x2
:
number
,
y
:
number
,
radius
:
number
)
{
return
`M
${
x1
}
${
y
}
A
${
radius
}
${
radius
}
0
${
y
>
RADIUS_IN_PX
?
0
:
1
}
0
${
x2
}
${
y
}
`
+
`Q
${(
x1
+
3
*
x2
)
/
4
}
${
y
+
12.5
*
(
x2
-
x1
)
/
radius
}
,
${(
x1
+
x2
)
/
2
}
${
y
}
T
${
x1
}
${
y
}
`
}
calPathCommands
(
value
:
number
)
{
let
y
=
this
.
calY
(
value
/
100.0
)
let
squareX
=
this
.
calXSquare
(
y
)
if
(
squareX
>=
0
)
{
let
x
=
Math
.
sqrt
(
squareX
);
let
x1
=
RADIUS_IN_PX
-
x
;
let
x2
=
RADIUS_IN_PX
+
x
;
return
this
.
formatPathCommands
(
x1
,
x2
,
y
,
RADIUS_IN_PX
);
}
return
""
;
}
aboutToAppear
()
{
this
.
test
()
}
test
()
{
let
timer
=
setInterval
(()
=>
{
if
(
this
.
outSetValue
<
100
)
{
this
.
outSetValue
+=
1
if
(
this
.
outSetValue
==
100
)
{
this
.
backGroundColor
=
COLOR_BACKGROUND_FILL
this
.
pathCommands
=
''
;
}
else
{
this
.
backGroundColor
=
COLOR_TRANSPARENT
this
.
pathCommands
=
this
.
calPathCommands
(
this
.
outSetValue
);
}
}
else
{
clearInterval
(
timer
)
}
},
100
)
}
build
()
{
Column
()
{
Column
()
{
Stack
()
{
// 外框圆环
Circle
({
width
:
BIG_DIAMETER
,
height
:
BIG_DIAMETER
})
.
fill
(
COLOR_TRANSPARENT
)
.
stroke
(
'
#007DFF
'
)
.
strokeWidth
(
5
)
// 进度显示
Circle
({
width
:
DIAMETER
,
height
:
DIAMETER
})
.
fill
(
this
.
backGroundColor
)
Path
()
.
width
(
DIAMETER
)
.
height
(
DIAMETER
)
.
commands
(
this
.
pathCommands
)
.
fill
(
COLOR_BACKGROUND_FILL
)
// 进度
Text
(
this
.
outSetValue
.
toFixed
(
0
)
+
"
%
"
)
.
fontSize
(
60
)
}.
width
(
BIG_DIAMETER
)
.
height
(
BIG_DIAMETER
)
Row
()
{
Slider
({
value
:
this
.
outSetValue
,
min
:
0
,
max
:
100
,
step
:
1
,
style
:
SliderStyle
.
OutSet
})
.
blockColor
(
'
#FFFFFF
'
)
.
trackColor
(
'
#182431
'
)
.
selectedColor
(
'
#007DFF
'
)
.
showSteps
(
true
)
.
showTips
(
true
)
.
onChange
((
value
:
number
,
mode
:
SliderChangeMode
)
=>
{
if
(
this
.
outSetValue
==
0
)
{
this
.
test
()
}
this
.
outSetValue
=
value
if
(
this
.
outSetValue
==
100
)
{
this
.
backGroundColor
=
COLOR_BACKGROUND_FILL
this
.
pathCommands
=
''
;
}
else
{
this
.
backGroundColor
=
COLOR_TRANSPARENT
this
.
pathCommands
=
this
.
calPathCommands
(
this
.
outSetValue
);
}
console
.
log
(
`value =
${
value
}
->`
+
this
.
pathCommands
);
})
Text
(
this
.
outSetValue
.
toFixed
(
0
)).
fontSize
(
16
)
}
.
padding
({
top
:
50
})
.
width
(
'
80%
'
)
}.
width
(
'
100%
'
)
}
.
height
(
'
100%
'
)
.
justifyContent
(
FlexAlign
.
Center
)
}
}
```
## 参考
[
Circle
](
../application-dev/reference/arkui-ts/ts-drawing-components-circle.md
)
[
Path
](
../application-dev/reference/arkui-ts/ts-drawing-components-path.md
)
[
Slider
](
../application-dev/reference/arkui-ts/ts-basic-components-slider.md
)
[
Timer
](
../application-dev/reference/apis/js-apis-timer.md
)
zh-cn/third-party-cases/content-changing-with-pulldown.md
0 → 100644
浏览文件 @
1cd6c533
# 如何实现内容下拉变化
## 场景介绍
组件开发过程中经常遇到组件堆叠,上层组件下拉,下层组件随之变化的场景。常见的如朋友圈背景的下拉放大,内容的下拉刷新等。本例将为大家介绍如何实现上述下拉变化的场景。
## 效果呈现
效果图如下:
![](
figures/collapsibleeffect.gif
)
## 运行环境
本例基于以下环境开发,开发者也可以基于其他适配的版本进行开发:
-
IDE: DevEco Studio 3.1 Beta2
-
SDK: Ohos_sdk_public 3.2.11.9(API Version 9 Release)
## 实现思路
本例的3个关键特性及实现方案如下:
-
界面不同背景的展示:通过Stack堆叠容器实现界面之间的覆盖
-
中间子组件的下拉和回弹:通过ontouch事件判断heightValue的大小去设置可滑动的中层组件的动画效果
-
底层子组件的文本变化:判断heightValuede来决定文本的变化
## 开发步骤
1.
通过Stack堆叠容器创建各层子组件和文本
具体代码块如下:
```
ts
// 底层子组件
...
Stack
({
alignContent
:
Alignment
.
Bottom
})
{
build
()
{
Stack
({
alignContent
:
Alignment
.
Bottom
})
{
//底部对齐
Column
()
{
Row
()
{
Image
(
$r
(
'
app.media.back
'
)).
width
(
25
).
height
(
25
)
.
onClick
(()
=>
{
router
.
back
();
})
...
Image
(
$r
(
"
app.media.sharew
"
))
//分享
.
width
(
25
)
.
height
(
25
)
Image
(
$r
(
'
app.media.more
'
))
//更多
.
width
(
25
)
.
height
(
25
)
}.
width
(
'
100%
'
).
padding
(
20
).
margin
({
top
:
20
})
...
}
.
height
(
this
.
ImHeight
)
.
width
(
this
.
ImWidth
)
.
backgroundImage
(
$r
(
'
app.media.images
'
))
//底层背景图
.
backgroundImageSize
(
ImageSize
.
Cover
)
...
}
}
}
...
//中层子组件
...
Column
()
{
Row
()
{
Text
(
'
当点击此场景卡片时:
'
).
fontSize
(
16
)
Blank
()
Image
(
$r
(
'
app.media.bl_harm
'
)).
width
(
30
).
height
(
30
)
}.
width
(
'
100%
'
).
margin
({
top
:
10
,
left
:
10
,
right
:
10
,
bottom
:
20
})
}.
borderRadius
(
35
)
...
//颜色渲染,线性渐变
.
linearGradient
(
{
direction
:
GradientDirection
.
Top
,
angle
:
180
,
colors
:
[[
'
#c7e2eb
'
,
0.01
],
[
"
#F7F7F7
"
,
0.05
],
[
"
#F7F7F7
"
,
1
]]
})
//底层子组件
...
Column
()
{
Flex
({
alignItems
:
ItemAlign
.
Center
,
justifyContent
:
FlexAlign
.
SpaceEvenly
})
{
Button
({
type
:
ButtonType
.
Capsule
,
stateEffect
:
true
})
{
Row
()
{
Text
(
'
查看更多
'
).
fontSize
(
16
).
fontColor
(
Color
.
Blue
).
margin
({
left
:
5
,
right
:
12
})
}.
alignItems
(
VerticalAlign
.
Center
)
}.
height
(
40
).
borderRadius
(
25
).
backgroundColor
(
'
#EBEBEB
'
).
width
(
'
45%
'
)
Button
({
type
:
ButtonType
.
Capsule
,
stateEffect
:
true
})
{
Row
()
{
Text
(
'
执行
'
).
fontSize
(
16
).
fontColor
(
Color
.
Blue
).
margin
({
left
:
5
,
right
:
12
})
}.
alignItems
(
VerticalAlign
.
Center
)
}.
height
(
40
).
borderRadius
(
25
).
backgroundColor
(
'
#EBEBEB
'
).
width
(
'
45%
'
)
}
}.
height
(
'
10%
'
).
width
(
'
100%
'
).
align
(
Alignment
.
Top
).
backgroundColor
(
'
#F7F7F7
'
)
...
```
2.
通过ontouch事件判断heightValue的大小去设置可滑动的中层组件的动画效果
具体代码块如下:
```
ts
...
.
onTouch
((
event
:
TouchEvent
)
=>
{
//触摸事件
if
(
event
.
type
===
TouchType
.
Down
)
{
this
.
duration
=
1000
;
}
if
(
event
.
type
===
TouchType
.
Up
)
{
// 结束,回弹,回弹动画更快
this
.
heightValue
=
'
88%
'
this
.
duration
=
500
;
this
.
ImHeight
=
"
100%
"
this
.
ImWidth
=
"
100%
"
}
if
(
event
.
type
===
TouchType
.
Move
)
{
// 根据滑动距离确定组件高度,最多拖动140的,此时组件最小高度为68%
if
(
event
.
touches
[
0
].
y
<=
140
)
{
this
.
heightValue
=
88
-
event
.
touches
[
0
].
y
/
7
+
'
%
'
this
.
ImHeight
=
"
200%
"
this
.
ImWidth
=
"
200%
"
}
else
{
this
.
heightValue
=
'
68%
'
}
}
console
.
info
(
'
垂直方向滑动距离
'
+
event
.
touches
[
0
].
y
)
})
.
height
(
this
.
heightValue
)
.
animation
({
duration
:
this
.
duration
,
// 动画时长
curve
:
Curve
.
FastOutSlowIn
,
// 动画曲线
delay
:
0
,
// 动画延迟
iterations
:
1
,
// 播放次数
playMode
:
PlayMode
.
Normal
// 动画模式
})
```
3.
判断可滑动的中层组件的高度变化来体现标题栏的变化
具体代码块如下:
```
ts
...
Row
(){
//可滑动的组件高度大于整体界面的70%,显示test1
Text
(
this
.
heightValue
>=
'
70%
'
?
'
test1
'
:
''
)
.
fontColor
(
Color
.
Black
)
.
fontSize
(
20
)
.
margin
({
left
:
5
})
}
...
Row
()
{
Text
(
this
.
heightValue
<
'
70%
'
?
'
test2
'
:
''
)
//可滑动的组件高度小于于整体界面的70%,显示test2
.
fontColor
(
Color
.
Red
)
.
fontSize
(
30
)
.
margin
({
left
:
5
})
}
...
```
## 完整代码
示例完整代码如下:
```
ts
import
router
from
'
@ohos.router
'
@
Entry
@
Component
struct
DetailExample
{
@
State
heightValue
:
string
=
'
88%
'
@
State
duration
:
number
=
1000
@
State
ImHeight
:
string
=
'
100%
'
@
State
ImWidth
:
string
=
'
100%
'
build
()
{
Stack
({
alignContent
:
Alignment
.
Bottom
})
{
// 底层子组件
Column
()
{
Row
()
{
Image
(
$r
(
'
app.media.back
'
)).
width
(
25
).
height
(
25
)
.
onClick
(()
=>
{
router
.
back
();
})
Text
(
this
.
heightValue
>=
'
70%
'
?
'
test1
'
:
''
)
.
fontColor
(
Color
.
Black
)
.
fontSize
(
20
)
.
margin
({
left
:
5
})
Blank
()
Image
(
$r
(
"
app.media.sharew
"
))
.
width
(
25
)
.
height
(
25
)
Image
(
$r
(
'
app.media.more
'
))
.
width
(
25
)
.
height
(
25
)
}.
width
(
'
100%
'
).
padding
(
20
).
margin
({
top
:
20
})
Row
()
{
Text
(
this
.
heightValue
<
'
70%
'
?
'
test2
'
:
''
)
.
fontColor
(
Color
.
Red
)
.
fontSize
(
30
)
.
margin
({
left
:
5
})
}
.
width
(
"
100%
"
)
.
height
(
35
)
.
alignItems
(
VerticalAlign
.
Center
)
.
justifyContent
(
FlexAlign
.
Start
)
}
.
height
(
this
.
ImHeight
)
.
width
(
this
.
ImWidth
)
.
backgroundImage
(
$r
(
'
app.media.images
'
))
.
backgroundImageSize
(
ImageSize
.
Cover
)
// 可拖动中层子组件,动画,圆弧
Column
()
{
Row
()
{
Text
(
'
当点击此场景卡片时:
'
).
fontSize
(
16
)
Blank
()
Image
(
$r
(
'
app.media.bl_harm
'
)).
width
(
30
).
height
(
30
)
}.
width
(
'
100%
'
).
margin
({
top
:
10
,
left
:
10
,
right
:
10
,
bottom
:
20
})
}.
borderRadius
(
35
)
.
padding
(
20
)
.
onTouch
((
event
:
TouchEvent
)
=>
{
if
(
event
.
type
===
TouchType
.
Down
)
{
this
.
duration
=
1000
;
}
if
(
event
.
type
===
TouchType
.
Up
)
{
this
.
heightValue
=
'
88%
'
this
.
duration
=
500
;
this
.
ImHeight
=
"
100%
"
this
.
ImWidth
=
"
100%
"
}
if
(
event
.
type
===
TouchType
.
Move
)
{
if
(
event
.
touches
[
0
].
y
<=
140
)
{
this
.
heightValue
=
88
-
event
.
touches
[
0
].
y
/
7
+
'
%
'
this
.
ImHeight
=
"
200%
"
this
.
ImWidth
=
"
200%
"
}
else
{
this
.
heightValue
=
'
68%
'
}
}
console
.
info
(
'
垂直方向滑动距离
'
+
event
.
touches
[
0
].
y
)
})
.
height
(
this
.
heightValue
)
.
animation
({
duration
:
this
.
duration
,
curve
:
Curve
.
FastOutSlowIn
,
delay
:
0
,
iterations
:
1
,
playMode
:
PlayMode
.
Normal
})
.
linearGradient
(
{
direction
:
GradientDirection
.
Top
,
angle
:
180
,
colors
:
[[
'
#c7e2eb
'
,
0.01
],
[
"
#F7F7F7
"
,
0.05
],
[
"
#F7F7F7
"
,
1
]]
})
// 最上层子组件
Column
()
{
Flex
({
alignItems
:
ItemAlign
.
Center
,
justifyContent
:
FlexAlign
.
SpaceEvenly
})
{
Button
({
type
:
ButtonType
.
Capsule
,
stateEffect
:
true
})
{
Row
()
{
Text
(
'
查看更多
'
).
fontSize
(
16
).
fontColor
(
Color
.
Blue
).
margin
({
left
:
5
,
right
:
12
})
}.
alignItems
(
VerticalAlign
.
Center
)
}
.
height
(
40
).
borderRadius
(
25
).
backgroundColor
(
'
#EBEBEB
'
).
width
(
'
45%
'
)
Button
({
type
:
ButtonType
.
Capsule
,
stateEffect
:
true
})
{
Row
()
{
Text
(
'
执行
'
).
fontSize
(
16
).
fontColor
(
Color
.
Blue
).
margin
({
left
:
5
,
right
:
12
})
}.
alignItems
(
VerticalAlign
.
Center
)
}
.
height
(
40
).
borderRadius
(
25
).
backgroundColor
(
'
#EBEBEB
'
).
width
(
'
45%
'
)
}
}.
height
(
'
10%
'
).
width
(
'
100%
'
).
align
(
Alignment
.
Top
).
backgroundColor
(
'
#F7F7F7
'
)
}
}
}
```
## 参考
[
Stack堆叠容器
](
../application-dev/reference/arkui-ts/ts-container-stack.md
)
[
Toggle
](
../application-dev/reference/arkui-ts/ts-basic-components-toggle.md
)
[
Flex
](
../application-dev/reference/arkui-ts/ts-container-flex.md
)
zh-cn/third-party-cases/figures/collapsibleeffect.gif
0 → 100644
浏览文件 @
1cd6c533
528.6 KB
zh-cn/third-party-cases/figures/jihe.png
0 → 100644
浏览文件 @
1cd6c533
5.0 KB
zh-cn/third-party-cases/figures/progressachieved.gif
0 → 100644
浏览文件 @
1cd6c533
361.4 KB
zh-cn/third-party-cases/realization-of-collapsible-title-effect.md
0 → 100644
浏览文件 @
1cd6c533
# 如何实现内容下拉变化
## 场景介绍
组件开发过程中经常遇到组件堆叠,上层组件下拉,下层组件随之变化的场景。常见的如朋友圈背景的下拉放大,内容的下拉刷新等。本例将为大家介绍如何实现上述下拉变化的场景。
## 效果呈现
效果图如下:
![](
figures/collapsibleeffect.gif
)
## 运行环境
本例基于以下环境开发,开发者也可以基于其他适配的版本进行开发:
-
IDE: DevEco Studio 3.1 Beta2
-
SDK: Ohos_sdk_public 3.2.11.9(API Version 9 Release)
## 实现思路
本例的3个关键特性及实现方案如下:
-
界面不同背景的展示:通过Stack堆叠容器实现界面之间的覆盖
-
中间子组件的下拉和回弹:通过ontouch事件判断heightValue的大小去设置可滑动的中层组件的动画效果
-
底层子组件的文本变化:判断heightValuede来决定文本的变化
## 开发步骤
1.
通过Stack堆叠容器创建各层子组件和文本
具体代码块如下:
```
ts
// 底层子组件
...
Stack
({
alignContent
:
Alignment
.
Bottom
})
{
build
()
{
Stack
({
alignContent
:
Alignment
.
Bottom
})
{
//底部对齐
Column
()
{
Row
()
{
Image
(
$r
(
'
app.media.back
'
)).
width
(
25
).
height
(
25
)
.
onClick
(()
=>
{
router
.
back
();
})
...
Image
(
$r
(
"
app.media.sharew
"
))
//分享
.
width
(
25
)
.
height
(
25
)
Image
(
$r
(
'
app.media.more
'
))
//更多
.
width
(
25
)
.
height
(
25
)
}.
width
(
'
100%
'
).
padding
(
20
).
margin
({
top
:
20
})
...
}
.
height
(
this
.
ImHeight
)
.
width
(
this
.
ImWidth
)
.
backgroundImage
(
$r
(
'
app.media.images
'
))
//底层背景图
.
backgroundImageSize
(
ImageSize
.
Cover
)
...
}
}
}
...
//中层子组件
...
Column
()
{
Row
()
{
Text
(
'
当点击此场景卡片时:
'
).
fontSize
(
16
)
Blank
()
Image
(
$r
(
'
app.media.bl_harm
'
)).
width
(
30
).
height
(
30
)
}.
width
(
'
100%
'
).
margin
({
top
:
10
,
left
:
10
,
right
:
10
,
bottom
:
20
})
}.
borderRadius
(
35
)
...
//颜色渲染,线性渐变
.
linearGradient
(
{
direction
:
GradientDirection
.
Top
,
angle
:
180
,
colors
:
[[
'
#c7e2eb
'
,
0.01
],
[
"
#F7F7F7
"
,
0.05
],
[
"
#F7F7F7
"
,
1
]]
})
//底层子组件
...
Column
()
{
Flex
({
alignItems
:
ItemAlign
.
Center
,
justifyContent
:
FlexAlign
.
SpaceEvenly
})
{
Button
({
type
:
ButtonType
.
Capsule
,
stateEffect
:
true
})
{
Row
()
{
Text
(
'
查看更多
'
).
fontSize
(
16
).
fontColor
(
Color
.
Blue
).
margin
({
left
:
5
,
right
:
12
})
}.
alignItems
(
VerticalAlign
.
Center
)
}.
height
(
40
).
borderRadius
(
25
).
backgroundColor
(
'
#EBEBEB
'
).
width
(
'
45%
'
)
Button
({
type
:
ButtonType
.
Capsule
,
stateEffect
:
true
})
{
Row
()
{
Text
(
'
执行
'
).
fontSize
(
16
).
fontColor
(
Color
.
Blue
).
margin
({
left
:
5
,
right
:
12
})
}.
alignItems
(
VerticalAlign
.
Center
)
}.
height
(
40
).
borderRadius
(
25
).
backgroundColor
(
'
#EBEBEB
'
).
width
(
'
45%
'
)
}
}.
height
(
'
10%
'
).
width
(
'
100%
'
).
align
(
Alignment
.
Top
).
backgroundColor
(
'
#F7F7F7
'
)
...
```
2.
通过ontouch事件判断heightValue的大小去设置可滑动的中层组件的动画效果
具体代码块如下:
```
ts
...
.
onTouch
((
event
:
TouchEvent
)
=>
{
//触摸事件
if
(
event
.
type
===
TouchType
.
Down
)
{
this
.
duration
=
1000
;
}
if
(
event
.
type
===
TouchType
.
Up
)
{
// 结束,回弹,回弹动画更快
this
.
heightValue
=
'
88%
'
this
.
duration
=
500
;
this
.
ImHeight
=
"
100%
"
this
.
ImWidth
=
"
100%
"
}
if
(
event
.
type
===
TouchType
.
Move
)
{
// 根据滑动距离确定组件高度,最多拖动140的,此时组件最小高度为68%
if
(
event
.
touches
[
0
].
y
<=
140
)
{
this
.
heightValue
=
88
-
event
.
touches
[
0
].
y
/
7
+
'
%
'
this
.
ImHeight
=
"
200%
"
this
.
ImWidth
=
"
200%
"
}
else
{
this
.
heightValue
=
'
68%
'
}
}
console
.
info
(
'
垂直方向滑动距离
'
+
event
.
touches
[
0
].
y
)
})
.
height
(
this
.
heightValue
)
.
animation
({
duration
:
this
.
duration
,
// 动画时长
curve
:
Curve
.
FastOutSlowIn
,
// 动画曲线
delay
:
0
,
// 动画延迟
iterations
:
1
,
// 播放次数
playMode
:
PlayMode
.
Normal
// 动画模式
})
```
3.
判断可滑动的中层组件的高度变化来体现标题栏的变化
具体代码块如下:
```
ts
...
Row
(){
//可滑动的组件高度大于整体界面的70%,显示test1
Text
(
this
.
heightValue
>=
'
70%
'
?
'
test1
'
:
''
)
.
fontColor
(
Color
.
Black
)
.
fontSize
(
20
)
.
margin
({
left
:
5
})
}
...
Row
()
{
Text
(
this
.
heightValue
<
'
70%
'
?
'
test2
'
:
''
)
//可滑动的组件高度小于于整体界面的70%,显示test2
.
fontColor
(
Color
.
Red
)
.
fontSize
(
30
)
.
margin
({
left
:
5
})
}
...
```
## 完整代码
示例完整代码如下:
```
ts
import
router
from
'
@ohos.router
'
@
Entry
@
Component
struct
DetailExample
{
@
State
heightValue
:
string
=
'
88%
'
@
State
duration
:
number
=
1000
@
State
ImHeight
:
string
=
'
100%
'
@
State
ImWidth
:
string
=
'
100%
'
build
()
{
Stack
({
alignContent
:
Alignment
.
Bottom
})
{
// 底层子组件
Column
()
{
Row
()
{
Image
(
$r
(
'
app.media.back
'
)).
width
(
25
).
height
(
25
)
.
onClick
(()
=>
{
router
.
back
();
})
Text
(
this
.
heightValue
>=
'
70%
'
?
'
test1
'
:
''
)
.
fontColor
(
Color
.
Black
)
.
fontSize
(
20
)
.
margin
({
left
:
5
})
Blank
()
Image
(
$r
(
"
app.media.sharew
"
))
.
width
(
25
)
.
height
(
25
)
Image
(
$r
(
'
app.media.more
'
))
.
width
(
25
)
.
height
(
25
)
}.
width
(
'
100%
'
).
padding
(
20
).
margin
({
top
:
20
})
Row
()
{
Text
(
this
.
heightValue
<
'
70%
'
?
'
test2
'
:
''
)
.
fontColor
(
Color
.
Red
)
.
fontSize
(
30
)
.
margin
({
left
:
5
})
}
.
width
(
"
100%
"
)
.
height
(
35
)
.
alignItems
(
VerticalAlign
.
Center
)
.
justifyContent
(
FlexAlign
.
Start
)
}
.
height
(
this
.
ImHeight
)
.
width
(
this
.
ImWidth
)
.
backgroundImage
(
$r
(
'
app.media.images
'
))
.
backgroundImageSize
(
ImageSize
.
Cover
)
// 可拖动中层子组件,动画,圆弧
Column
()
{
Row
()
{
Text
(
'
当点击此场景卡片时:
'
).
fontSize
(
16
)
Blank
()
Image
(
$r
(
'
app.media.bl_harm
'
)).
width
(
30
).
height
(
30
)
}.
width
(
'
100%
'
).
margin
({
top
:
10
,
left
:
10
,
right
:
10
,
bottom
:
20
})
}.
borderRadius
(
35
)
.
padding
(
20
)
.
onTouch
((
event
:
TouchEvent
)
=>
{
if
(
event
.
type
===
TouchType
.
Down
)
{
this
.
duration
=
1000
;
}
if
(
event
.
type
===
TouchType
.
Up
)
{
this
.
heightValue
=
'
88%
'
this
.
duration
=
500
;
this
.
ImHeight
=
"
100%
"
this
.
ImWidth
=
"
100%
"
}
if
(
event
.
type
===
TouchType
.
Move
)
{
if
(
event
.
touches
[
0
].
y
<=
140
)
{
this
.
heightValue
=
88
-
event
.
touches
[
0
].
y
/
7
+
'
%
'
this
.
ImHeight
=
"
200%
"
this
.
ImWidth
=
"
200%
"
}
else
{
this
.
heightValue
=
'
68%
'
}
}
console
.
info
(
'
垂直方向滑动距离
'
+
event
.
touches
[
0
].
y
)
})
.
height
(
this
.
heightValue
)
.
animation
({
duration
:
this
.
duration
,
curve
:
Curve
.
FastOutSlowIn
,
delay
:
0
,
iterations
:
1
,
playMode
:
PlayMode
.
Normal
})
.
linearGradient
(
{
direction
:
GradientDirection
.
Top
,
angle
:
180
,
colors
:
[[
'
#c7e2eb
'
,
0.01
],
[
"
#F7F7F7
"
,
0.05
],
[
"
#F7F7F7
"
,
1
]]
})
// 最上层子组件
Column
()
{
Flex
({
alignItems
:
ItemAlign
.
Center
,
justifyContent
:
FlexAlign
.
SpaceEvenly
})
{
Button
({
type
:
ButtonType
.
Capsule
,
stateEffect
:
true
})
{
Row
()
{
Text
(
'
查看更多
'
).
fontSize
(
16
).
fontColor
(
Color
.
Blue
).
margin
({
left
:
5
,
right
:
12
})
}.
alignItems
(
VerticalAlign
.
Center
)
}
.
height
(
40
).
borderRadius
(
25
).
backgroundColor
(
'
#EBEBEB
'
).
width
(
'
45%
'
)
Button
({
type
:
ButtonType
.
Capsule
,
stateEffect
:
true
})
{
Row
()
{
Text
(
'
执行
'
).
fontSize
(
16
).
fontColor
(
Color
.
Blue
).
margin
({
left
:
5
,
right
:
12
})
}.
alignItems
(
VerticalAlign
.
Center
)
}
.
height
(
40
).
borderRadius
(
25
).
backgroundColor
(
'
#EBEBEB
'
).
width
(
'
45%
'
)
}
}.
height
(
'
10%
'
).
width
(
'
100%
'
).
align
(
Alignment
.
Top
).
backgroundColor
(
'
#F7F7F7
'
)
}
}
}
```
## 参考
[
Stack堆叠容器
](
../application-dev/reference/arkui-ts/ts-container-stack.md
)
[
Toggle
](
../application-dev/reference/arkui-ts/ts-basic-components-toggle.md
)
[
Flex
](
../application-dev/reference/arkui-ts/ts-container-flex.md
)
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录