是一个竖直的,可以容纳多个排成一列的子组件的滚动器。如果子组件的总高度高于其本身,那么所有的子组件都可滚动。
可以当作根元素或者嵌套元素使用。此组件的滚动方向是垂直方向的形式。
子组件
特殊子组件
<refresh>
:用于给列表添加下拉刷新的功能。特殊子组件
< loading >
:用于给列表添加上拉加载更多的功能。
特性
show-scrollbar {boolean}
:可选值为true/ false
,默认值为true
。控制是否出现滚动条。scroll-direction {string}
:可选为horizontal
或者vertical
,默认值为vertical
。定义滚动的方向。loadmoreoffset {number}
:默认值为 0,触发loadmore
事件所需要的垂直偏移距离(设备屏幕底部与页面底部之间的距离)。当页面的滚动条滚动到足够接近页面底部时将会触发loadmore
这个事件。loadmoreretry {number}
:默认值为 0,当loadmore
失败时是否重置loadmore
相关的 UI,值不一样就会重置。
事件
-
loadmore
:如果滚动到底部将会立即触发这个事件,你可以在这个事件的处理函数中加载下一页的列表项。
约束
- 不允许相同方向的
<list>
或者<scroller>
互相嵌套,换句话说就是嵌套的<list>/<scroller>
必须是不同的方向。
示例vue
<template>
<div class="wrapper">
<scroller class="scroller">
<div class="row" v-for="(name, index) in rows" :ref="'item'+index">
<text class="text" :ref="'text'+index">{{name}}</text>
</div>
</scroller>
<div class="group">
<text @click="goto10" class="button">Go to 10</text>
<text @click="goto20" class="button">Go to 20</text>
</div>
</div>
</template>
<script>
const dom = weex.requireModule('dom')
export default {
data () {
return {
rows: []
}
},
created () {
for (let i = 0; i < 30; i++) {
this.rows.push('row ' + i)
}
},
methods: {
goto10 (count) {
const el = this.$refs.item10[0]
dom.scrollToElement(el, {})
},
goto20 (count) {
const el = this.$refs.item20[0]
dom.scrollToElement(el, { offset: 0 })
}
}
}
</script>
<style scoped>
.scroller {
width: 700px;
height: 700px;
border-width: 3px;
border-style: solid;
border-color: rgb(162, 217, 192);
margin-left: 25px;
}
.row {
height: 100px;
flex-direction: column;
justify-content: center;
padding-left: 30px;
border-bottom-width: 2px;
border-bottom-style: solid;
border-bottom-color: #DDDDDD;
}
.text {
font-size: 45px;
color: #666666;
}
.group {
flex-direction: row;
justify-content: center;
margin-top: 60px;
}
.button {
width: 200px;
padding-top: 20px;
padding-bottom: 20px;
font-size: 40px;
margin-left: 30px;
margin-right: 30px;
text-align: center;
color: #41B883;
border-width: 2px;
border-style: solid;
border-color: rgb(162, 217, 192);
background-color: rgba(162, 217, 192, 0.2);
}
</style>
SDK源码
- 组件类:
WXScrollerComponent
[self registerComponent:@"scroller" withClass:NSClassFromString(@"WXScrollerComponent") withProperties:nil];
- 实现的协议
@interface WXScrollerComponent : WXComponent <WXScrollerProtocol, UIScrollViewDelegate>
- 两个特殊的子组件:
@property (nonatomic, weak) WXRefreshComponent *refreshComponent;
@property (nonatomic, weak) WXLoadingComponent *loadingComponent;
- 属性和默认值
_scrollDirection = attributes[@"scrollDirection"] ? [WXConvert WXScrollDirection:attributes[@"scrollDirection"]] : WXScrollDirectionVertical;
_showScrollBar = attributes[@"showScrollbar"] ? [WXConvert BOOL:attributes[@"showScrollbar"]] : YES;
_loadMoreOffset = attributes[@"loadmoreoffset"] ? [WXConvert CGFloat:attributes[@"loadmoreoffset"]] : 0;
_loadmoreretry = attributes[@"loadmoreretry"] ? [WXConvert NSUInteger:attributes[@"loadmoreretry"]] : 0;
- 本质上是
UIScrollView
,却要进行类型强制转换
- (UIView *)loadView
{
return [[UIScrollView alloc] init];
}
- (void)viewDidLoad
{
[self setContentSize:_contentSize];
UIScrollView* scrollView = (UIScrollView *)self.view;
scrollView.scrollEnabled = YES;
scrollView.delegate = self;
scrollView.exclusiveTouch = YES;
scrollView.autoresizesSubviews = NO;
scrollView.clipsToBounds = YES;
scrollView.showsVerticalScrollIndicator = _showScrollBar;
scrollView.showsHorizontalScrollIndicator = _showScrollBar;
if (self.ancestorScroller) {
scrollView.scrollsToTop = NO;
} else {
scrollView.scrollsToTop = YES;
}
}
- 基本上都是通过x或者y的偏移量的组合计算来实现那两个代理的,需要很大的耐心和细心才能做到。比如:判断滑动方向
if (_lastContentOffset.x > scrollView.contentOffset.x){
_direction = @"right";
} else if (_lastContentOffset.x < scrollView.contentOffset.x){
_direction = @"left";
} else if(_lastContentOffset.y > scrollView.contentOffset.y){
_direction = @"down";
} else if(_lastContentOffset.y < scrollView.contentOffset.y) {
_direction = @"up";
}