小部件(Widget)不同于小程序页面,仅支持有限的组件,用于绘制小部件(Widget) 的 UI 界面。现总结视图容器的内置组件明细:
属性 | 类型 | 默认值 | 必填 | 说明 | 备注 |
---|---|---|---|---|---|
hover-class | string | none | 否 | 指定按下去的样式类。当?hover-class="none" ?时,没有点击态效果 | |
hover-start-time | number | 50 | 否 | 按住后多久出现点击态,单位毫秒 | |
hover-stay-time | number | 400 | 否 | 手指松开后点击态保留时间,单位毫秒 |
<view class="page-head">
<view class="page-head-title">view</view>
<view class="page-head-line"></view>
</view>
<view class="page-section">
<view class="page-section-title l-r-padding">
<view>flex-direction: row</view>
<view>横向布局</view>
</view>
<view class="flex-wrp" style="flex-direction:row;justify-content: center;">
<view class="flex-item demo-text-1">A</view>
<view class="flex-item demo-text-2">B</view>
<view class="flex-item demo-text-3">C</view>
</view>
</view>
<view class="page-section">
<view class="page-section-title l-r-padding">
<view>flex-direction: column</view>
<view>纵向布局</view>
</view>
<view class="flex-wrp" style="flex-direction:column;">
<view class="flex-item flex-item-V demo-text-1">A</view>
<view class="flex-item flex-item-V demo-text-2">B</view>
<view class="flex-item flex-item-V demo-text-3">C</view>
</view>
</view>
?
可滚动视图区域,可实现横向滚动和竖向滚动。使用竖向滚动时,需要给定一个固定高度,可以通过样式来设置 height。组件属性的长度单位支持 px 和 rpx。
属性 | 类型 | 默认值 | 必填 | 说明 | 备注 |
---|---|---|---|---|---|
scroll-x | boolean | false | 否 | 允许横向滚动 | |
scroll-y | boolean | false | 否 | 允许纵向滚动 | |
upper-threshold | number/string | 50 | 否 | 距顶部/左边多远时,触发 scrolltoupper 事件 | |
lower-threshold | number/string | 50 | 否 | 距底部/右边多远时,触发 scrolltolower 事件 | |
scroll-top | number/string | 否 | 设置竖向滚动条位置 | ||
scroll-left | number/string | 否 | 设置横向滚动条位置 | ||
scroll-into-view | string | 否 | 值应为某子元素 id(id 不能以数字开头)。设置哪个方向可滚动,则在哪个方向滚动到该元素 | ||
scroll-with-animation | boolean | false | 否 | 在设置滚动条位置时使用动画过渡 | |
refresher-enabled | boolean | false | 否 | 开启自定义下拉刷新 | |
refresher-threshold | number | 45 | 否 | 设置自定义下拉刷新阈值 | |
refresher-default-style | string | "black" | 否 | 设置自定义下拉刷新默认样式,支持设置 black、white、none, none 表示不使用默认样式 | |
refresher-background | string | "#FFF" | 否 | 设置自定义下拉刷新区域背景颜色 | |
refresher-triggered | boolean | false | 否 | 设置当前下拉刷新状态,true 表示下拉刷新已经被触发,false 表示下拉刷新未被触发 | |
bind:scroll | eventhandle | -- | 否 | 滚动时触 | |
bind:scrolltoupper | eventhandle | -- | 否 | 滚动到顶部/左边时触发 | |
bind:scrolltolower | eventhandle | -- | 否 | 滚动到底部/右边时触发 | |
bind:refresherpulling | eventhandle | -- | 否 | 自定义下拉刷新控件被下拉 | |
bind:refresherrefresh | eventhandle | -- | 否 | 自定义下拉刷新被触发 | |
bind:refresherrestore | eventhandle | -- | 否 | 自定义下拉刷新被复位 | |
bind:refresherabort | eventhandle | -- | 否 | 自定义下拉刷新被中止 |
<view class="page-head">
<view class="page-head-title">scroll-view</view>
<view class="page-head-line"></view>
</view>
<view class="page-section">
<view class="page-section-title l-r-padding">
<text>Vertical Scroll</text>
<view>纵向滚动</view>
</view>
<view class="page-section-spacing">
<scroll-view
style="height: 150px;"
scrollY="{{true}}"
bind:scroll="scroll"
bind:scrolltoupper="upper"
bind:scrolltolower="lower"
>
<view id="demo1" class="scroll-view-item demo-text-1">A</view>
<view id="demo2" class="scroll-view-item demo-text-2">B</view>
<view id="demo3" class="scroll-view-item demo-text-3">C</view>
</scroll-view>
</view>
</view>
<view class="page-section">
<view class="page-section-title l-r-padding">
<text>Horizontal Scroll</text>
<view>横向滚</view>
</view>
<view class="page-section-spacing">
<scroll-view
class="scroll-view_H"
scrollX="{{true}}"
scrollIntoView="{{toView}}"
scrollWithAnimation="{{true}}"
bind:scroll="scroll"
bind:scrolltoupper="upper"
bind:scrolltolower="lower"
>
<view class="box">
<view id="demo4" class="scroll-view-item_H demo-text-1">A</view>
<view id="demo5" class="scroll-view-item_H demo-text-2">B</view>
<view id="demo6" class="scroll-view-item_H demo-text-3">C</view>
</view>
</scroll-view>
</view>
</view>
Page({
data: {
toView: 'demo5',
},
upper(e) {
console.log('demo upper', e);
},
lower(e) {
console.log('demo lower', e);
},
scroll(e) {
console.log('demo scroll', e);
},
});
.page-section {
width: 100%;
display: block;
margin: 30px 0;
}
.page-section:last-child {
margin-bottom: 0;
}
.page-section-spacing {
margin-top: 30px;
box-sizing: border-box;
padding: 0 40px;
}
.scroll-view_H {
width: 100%;
white-space: nowrap;
}
.box {
display: flex;
flex-wrap: nowrap;
width: 300%;
}
.scroll-view-item_H {
flex: 1;
height: 150px;
color: #ffffff;
font-size: 13px;
display: flex;
align-items: center;
justify-content: center;
}
.scroll-view-item {
height: 150px;
color: #ffffff;
font-size: 13px;
display: flex;
align-items: center;
justify-content: center;
}
.demo-text-1 {
background-color: #1aad19;
}
.demo-text-2 {
background-color: #2782d7;
}
.demo-text-3 {
background-color: #f1f1f1;
color: #353535;
}
为何 scroll-view 在 popup 扩展组件中无法滑动?
popup 组件上加上 disableScroll={{false}} 属性才能滑动。
如何监听 scroll-view 滚动到底部?
可以直接在?onScroll
?方法中进行处理,使用?onScrollToLower
?监听?scroll-view
?的滚动高度来进行判断是否滑动到了底部。?scrollHeight
?是?scroll-view
?里面所有?view
?的高度和,scrollTop
?是滚动的值。
自定义页面蒙层的时候,当滚动蒙层里面的内容,蒙层底下页面也能跟着滑动?
可以给蒙层内部?scroll-view
?或?view
?添加?catch:touchmove
事件,阻止事件冒泡。
滑块视图容器。其中只可放置 swiper-item 组件,否则会导致未定义的行为。
属性 | 类型 | 默认值 | 必填 | 说明 |
---|---|---|---|---|
indicator-dots | boolean | false | 否 | 是否显示面板指示点 |
indicator-color | color | #666666 | 否 | 指示点颜色 |
indicator-active-color | color | #333333 | 否 | 当前选中的指示点颜色 |
autoplay | boolean | false | 否 | 是否自动切换 |
current | number | 0 | 否 | 当前所在滑块的 index |
interval | number | 5000 | 否 | 自动切换时间间隔,单位 ms |
duration | number | 500 | 否 | 滑动动画时长,单位 ms |
circular | boolean | false | 否 | 是否采用衔接滑动 |
vertical | boolean | false | 否 | 滑动方向是否为纵向 |
bind:change | eventhandle | 否 | current 改变时会触发 change 事件,event.detail = {current, source} | |
bind:animationfinish | eventhandle | 否 | 动画结束时会触发 animationfinish 事件,event.detail 同上 |
change 事件的 source 字段,表示导致变更的原因,可能值如下:
值 | 说明 |
---|---|
autoplay | 自动播放导致 swiper 变化 |
touch | 用户划动引起 swiper 变化 |
空字符串 | 其它原因 |
<view class="container">
<view class="page-body">
<view class="page-section page-section-spacing swiper">
<swiper
indicator-dots="{{indicatorDots}}"
autoplay="{{autoplay}}"
circular="{{circular}}"
vertical="{{vertical}}"
interval="{{interval}}"
duration="{{duration}}"
>
<block ty:for="{{background}}" ty:key="*this">
<swiper-item>
<view class="swiper-item {{item}}"></view>
</swiper-item>
</block>
</swiper>
</view>
<view class="page-section" style="margin-top: 40rpx;margin-bottom: 0;">
<view class="tyui-cells tyui-cells_after-title">
<view class="page-cell tyui-cell_switch">
<view class="tyui-cell__bd">指示点</view>
<view class="tyui-cell__ft">
<switch checked="{{indicatorDots}}" bind:change="changeProperty" data-property-name="indicatorDots" />
</view>
</view>
<view class="page-cell tyui-cell_switch">
<view class="tyui-cell__bd">自动播放</view>
<view class="tyui-cell__ft">
<switch checked="{{autoplay}}" bind:change="changeProperty" data-property-name="autoplay" />
</view>
</view>
<view class="page-cell tyui-cell_switch">
<view class="tyui-cell__bd">衔接滑动</view>
<view class="tyui-cell__ft">
<switch checked="{{circular}}" bind:change="changeProperty" data-property-name="circular" />
</view>
</view>
<view class="page-cell tyui-cell_switch">
<view class="tyui-cell__bd">竖向</view>
<view class="tyui-cell__ft">
<switch checked="{{vertical}}" bind:change="changeProperty" data-property-name="vertical" />
</view>
</view>
</view>
</view>
<view class="page-section page-section-spacing">
<view class="page-section-title">
<text>幻灯片切换时长(ms)</text>
<text class="info">{{duration}}</text>
</view>
<slider value="{{duration}}" min="{{500}}" max="{{2000}}" bind:change="changeProperty" data-property-name="duration" />
<view class="page-section-title">
<text>自动播放间隔时长(ms)</text>
<text class="info">{{interval}}</text>
</view>
<slider value="{{interval}}" min="{{2000}}" max="{{10000}}" bind:change="changeProperty" data-property-name="interval" />
</view>
</view>
</view>
Page({
data: {
background: ['demo-text-1', 'demo-text-2', 'demo-text-3'],
indicatorDots: true,
vertical: false,
autoplay: false,
circular: true,
interval: 2000,
duration: 500,
previousMargin: 0,
nextMargin: 0,
},
change: function (e) {},
changeProperty: function (e) {
var propertyName = e.currentTarget.dataset.propertyName;
var newData = {};
newData[propertyName] = e.detail.value;
this.setData(newData);
},
changeIndicatorDots: function (e) {
this.setData({
indicatorDots: !this.data.indicatorDots,
});
},
changeAutoplay: function (e) {
this.setData({
autoplay: !this.data.autoplay,
});
},
intervalChange: function (e) {
this.setData({
interval: e.detail.value,
});
},
durationChange: function (e) {
this.setData({
duration: e.detail.value,
});
},
});
?
movable-view 的可移动区域。
属性 | 类型 | 默认值 | 必填 | 说明 |
---|---|---|---|---|
scale-area | boolean | false | 否 | 当里面的 movable-view 设置为支持双指缩放时,设置此值可将缩放手势生效区域修改为整个 movable-area |
<view class="page-section">
<view class="page-section-title l-r-padding">movable移动功能</view>
<view class="area-wrap">
<movable-area class="area">
<movable-view class="block" x="{{x}}" y="{{y}}" direction="all">
text
</movable-view>
</movable-area>
</view>
<view class="btn-wrap">
<view class="btn-line">
<button type="primary" bind:tap="moveFn" class="btn">点击移动到(30px, 30px)</button>
</view>
<view class="btn-line">
<button type="primary" bind:tap="moveStep" class="btn sec-btn">点击移动到({{x + 10}}px, {{y + 10}}px)</button>
</view>
</view>
</view>
<view class="page-section">
<view class="page-section-title l-r-padding">只可以横向移动</view>
<view class="area-wrap">
<movable-area class="area">
<movable-view class="block" direction="horizontal">text</movable-view>
</movable-area>
</view>
</view>
<view class="page-section">
<view class="page-section-title l-r-padding">只可以纵向移动</view>
<view class="area-wrap">
<movable-area class="area">
<movable-view class="block" direction="vertical">text</movable-view>
</movable-area>
</view>
</view>
<view class="page-section">
<view class="page-section-title l-r-padding">可超出边界</view>
<view class="area-wrap">
<movable-area class="area">
<movable-view class="block" direction="all" out-of-bounds="true">text</movable-view>
</movable-area>
</view>
</view>
Page({
data: {
x: 0,
y: 0,
},
// 移动到30px,30px
moveFn() {
this.setData({
x: 30,
y: 30,
});
},
moveStep() {
const x = this.data.x + 10;
const y = this.data.y + 10;
this.setData({
x,
y,
});
},
});
.page-section {
width: 100%;
margin-bottom: 30px;
}
.area-wrap {
display: flex;
justify-content: space-around;
}
.area {
flex: none;
height: 200px;
width: 200px;
margin: 10px;
background-color: #ccc;
overflow: hidden;
}
.block {
display: flex;
align-items: center;
justify-content: center;
height: 50px;
width: 50px;
background: var(--ty-native-primary-color);
color: #fff;
}
.btn-line {
text-align: center;
}
.btn-line .btn {
display: inline-block;
width: 240px;
}
.btn-line .sec-btn {
margin-top: 10px;
}
?
可移动的视图容器,在页面中可以拖拽滑动。movable-view 必须在 movable-area 组件中,并且必须是直接子节点,否则不能移动。?
属性 | 类型 | 默认值 | 必填 | 说明 |
---|---|---|---|---|
direction | string | none | 否 | movable-view 的移动方向,属性值有 all、vertical、horizontal、none |
inertia | boolean | false | 否 | movable-view 是否带有惯性 |
out-of-bounds | boolean | false | 否 | 超过可移动区域后,movable-view 是否还可以移动 |
x | number | 0 | 否 | 定义 x 轴方向的偏移,如果 x 的值不在可移动范围内,会自动移动到可移动范围。改变 x 的值会触发动画 |
y | number | 0 | 否 | 定义 y 轴方向的偏移,如果 y 的值不在可移动范围内,会自动移动到可移动范围。改变 y 的值会触发动画 |
damping | number | 20 | 否 | 阻尼系数,用于控制 x 或 y 改变时的动画和过界回弹的动画,值越大移动越快 |
friction | number | 2 | 否 | 摩擦系数,用于控制惯性滑动的动画,值越大摩擦力越大,滑动越快停止;必须大于 0,否则会被设置成默认值 |
disabled | boolean | false | 否 | 是否禁用 |
scale | boolean | false | 否 | 是否支持双指缩放,默认缩放手势生效区域是在 movable-view 内 |
scale-min | number | 0.5 | 否 | 定义缩放倍数最小值 |
scale-max | number | 10 | 否 | 定义缩放倍数最大值 |
scale-value | number | 1 | 否 | 定义缩放倍数,取值范围为 0.5 - 10 |
animation | boolean | true | 否 | 是否使用动画 |
bind:change | eventhandle | 否 | 拖动过程中触发的事件,event.detail = {x, y, source} | |
bind:scale | eventhandle | 否 | 缩放过程中触发的事件,event.detail = {x, y, scale} |
bind:change
?返回的?source
?表示产生移动的原因
值 | 说明 |
---|---|
touch | 拖动 |
touch-out-of-bounds | 超出移动范围 |
out-of-bounds | 超出移动范围后的回弹 |
friction | 惯性 |
空字符串 | setData |
tip:?movable-view
?必须设置?width
?和?height
?属性,不设置默认为?10px
?tip:?movable-view
?默认为绝对定位,top
?和?left
?属性为?0px。
?
?页面容器。用于实现类似 popup 弹出层的效果,可以通过控制 show 属性来实现显示/隐藏。
页面容器。
小程序如果在页面内进行复杂的界面设计(如在页面内弹出半屏的弹窗、在页面内加载一个全屏的子页面等),用户进行返回操作会直接离开当前页面,不符合用户预期,预期应为关闭当前弹出的组件。 为此提供“假页”容器组件,效果类似于 popup 弹出层。
页面内存 page-container 时,当用户进行返回操作,关闭该容器不关闭页面。返回操作包括三种情形,右滑手势、安卓物理返回键和调用 navigateBack 接口。
容器版本 2.3.0+ 以上支持
注意:当页面状态触发 page-container 显示隐藏时,开发者需在 page-container 离开视图的相关事件中,将控制 page-container 的状态设置为 false,否则可能会影响再次打开 page-container。
属性 | 类型 | 默认值 | 必填 | 说明 |
---|---|---|---|---|
show | boolean | false | 否 | 是否显示容器组件 |
duration | number | 300 | 否 | 动画时长,单位毫秒 |
z-index | number | 100 | 否 | z-index 层级 |
overlay | boolean | true | 否 | 是否显示遮罩层 |
position | string | bottom | 否 | 弹出位置,可选值为 top bottom right center |
round | boolean | false | 否 | 是否显示圆角 |
overlay-style | string | 否 | 自定义遮罩层样式 | |
custom-style | string | 否 | 自定义弹出层样式 | |
bind:beforeenter | eventhandle | 否 | 进入前触发 | |
bind:enter | eventhandle | 否 | 进入中触发 | |
bind:afterenter | eventhandle | 否 | 进入后触发 | |
bind:beforeleave | eventhandle | 否 | 离开前触发 | |
bind:leave | eventhandle | 否 | 离开中触发 | |
bind:afterleave | eventhandle | 否 | 离开后触发 | |
bind:clickoverlay | eventhandle | 否 | 点击遮罩层时触发 |
<view class="title">弹出位置</view>
<view class="box">
<button class="btn" bind:tap="popup" data-position="right">右侧弹出</button>
<button class="btn" bind:tap="popup" data-position="top">顶部弹出</button>
<button class="btn" bind:tap="popup" data-position="bottom">底部弹出</button>
<button class="btn" bind:tap="popup" data-position="center">中央弹出</button>
</view>
<view class="title">弹窗圆角</view>
<view class="box">
<button class="btn" bind:tap="changeRound">设置{{round ? '直角' : '圆角'}}</button>
</view>
<view class="title">遮罩层</view>
<view class="box">
<button class="btn" bind:tap="changeOverlay">设置{{overlay ? '无' : '有'}}遮罩</button>
<button class="btn" bind:tap="changeOverlayStyle" data-type="black">黑色半透明遮罩</button>
<button class="btn" bind:tap="changeOverlayStyle" data-type="white">白色半透明遮罩</button>
<button class="btn" bind:tap="changeOverlayStyle" data-type="blur">模糊遮罩</button>
</view>
<page-container
style="height: 500px"
show="{{show}}"
round="{{round}}"
overlay="{{overlay}}"
duration="{{duration}}"
position="{{position}}"
close-on-slide-down="{{false}}"
bind:beforeenter="onBeforeEnter"
bind:enter="onEnter"
bind:afterenter="onAfterEnter"
bind:beforeleave="onBeforeLeave"
bind:leave="onLeave"
bind:afterleave="onAfterLeave"
bind:clickoverlay="onClickOverlay"
custom-style="{{customStyle}}"
overlay-style="{{overlayStyle}}"
>
<view class="detail-page">
<button type="primary" bind:tap="exit">推出</button>
</view>
</page-container>
Page({
data: {
show: false,
duration: 300,
position: 'right',
round: false,
overlay: true,
customStyle: '',
overlayStyle: '',
},
onLoad: function () {},
onShow() {},
popup(e) {
const position = e.currentTarget.dataset.position;
let customStyle = '';
let duration = this.data.duration;
switch (position) {
case 'top':
case 'bottom':
customStyle = '';
break;
case 'right':
break;
}
this.setData({
position,
show: true,
customStyle,
duration,
});
},
changeRound() {
this.setData({ round: !this.data.round });
},
changeOverlay() {
this.setData({ overlay: !this.data.overlay, show: true });
},
changeOverlayStyle(e) {
let overlayStyle = '';
const type = e.currentTarget.dataset.type;
switch (type) {
case 'black':
overlayStyle = 'background-color: rgba(0, 0, 0, 0.7)';
break;
case 'white':
overlayStyle = 'background-color: rgba(255, 255, 255, 0.7)';
break;
case 'blur':
overlayStyle =
'background-color: rgba(0, 0, 0, 0.7); filter: blur(4px);';
}
this.setData({ overlayStyle, show: true });
},
exit() {
this.setData({ show: false });
},
onBeforeEnter(res) {
console.log(res);
},
onEnter(res) {
console.log(res);
},
onAfterEnter(res) {
console.log(res);
},
onBeforeLeave(res) {
console.log(res);
},
onLeave(res) {
console.log(res);
this.setData({ show: false });
},
onAfterLeave(res) {
console.log(res);
},
onClickOverlay(res) {
this.setData({
show: false,
});
},
});
.box {
margin: 0 20px;
}
.title {
margin: 0;
padding: 32px 16px 16px;
color: rgba(0, 0, 0, 0.5);
font-weight: normal;
font-size: 14px;
line-height: 20px;
text-align: center;
}
.btn {
display: block;
width: 100%;
margin: 10px 0;
background-color: #fff;
}
.detail-page {
width: 100%;
height: 100%;
min-height: 300px;
display: flex;
align-items: center;
justify-content: center;
}
?
基础库 2.7.0 开始支持, 低版本需做兼容处理。
覆盖在原生组件之上的文本视图。
cover-view
?包裹住, 其它场景不建议使用cover-view
cover-view
?,?cover-view
?只作为覆盖在原生组件之上的包裹标签使用cover-view
?子节点不要溢出父节点<view class="container">
<map style="width: 100%; height: 300px;" latitude="{{latitude}}" longitude="{{longitude}}"></map>
<cover-view class="cover-view">
<view class="flex-wrp" style="flex-direction:row;" bindtap="coverTap">
<view class="flex-item demo-text-1"></view>
<view class="flex-item demo-text-2"></view>
<view class="flex-item demo-text-3"></view>
</view>
</cover-view>
</view>
Page({
data: {
latitude: 23.099994,
longitude: 113.32452,
},
coverTap(e) {
console.log(e);
},
});
.container {
position: relative;
}
.cover-view {
position: absolute;
top: calc(50% - 150rpx);
left: calc(50% - 300rpx);
}
.flex-wrp {
display: flex;
}
.flex-item {
width: 200rpx;
height: 300rpx;
font-size: 26rpx;
}
.demo-text-1 {
background: rgba(26, 173, 25, 0.7);
}
.demo-text-2 {
background: rgba(39, 130, 215, 0.7);
}
.demo-text-3 {
background: rgba(255, 255, 255, 0.7);
}