# scroll-view

可滚动视图区域，相当于web中设置了overflow属性的div元素。

**起始版本：** 1.0.0

**约束与限制：**

使用竖向滚动时，需要通过CSS设置height，给scroll-view一个固定高度。组件属性的长度单位默认为px。

**属性：**

|名称|类型|默认值|必填|描述|
|:----------------------|:------------|:----------|:-|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|enhanced|boolean|false|否|是否启用scroll-view增强特性，启用后可通过[ScrollViewContext](https://developer.huawei.com/consumer/cn/doc/atomic-ascf/apis-scroll#scrollviewcontext)操作scroll-view。 **起始版本：** 1.0.23|
|scroll-x|boolean|false|否|允许横向滚动。|
|scroll-y|boolean|false|否|允许纵向滚动。|
|upper-threshold|number|string|50|否|距顶部/左边多远时，触发scrolltoupper事件。|
|lower-threshold|number|string|50|否|距底部/右边多远时，触发scrolltolower事件。|
|scroll-top|number|string|0|否|设置竖向滚动条位置。|
|scroll-left|number|string|0|否|设置横向滚动条位置。|
|scroll-into-view|string|-|否|值应为某子元素id（id不能以数字开头）。设置哪个方向可滚动，则在哪个方向滚动到该元素。|
|scroll-into-view-offset|number|0|否|跳转到scroll-into-view目标节点时的额外偏移。 **起始版本：** 2.0.1|
|scroll-with-animation|boolean|false|否|在设置滚动条位置时使用动画过渡。|
|show-scrollbar|boolean|true|否|2.0.1版本之前，滚动条显隐控制（没有其它额外限制）。 2.0.1版本之后，滚动条显隐控制（同时开启enhanced属性后生效）。|
|refresher-enabled|boolean|false|否|开启自定义下拉刷新。|
|refresher-threshold|number|45|否|设置自定义下拉刷新阈值。|
|refresher-default-style|string|"black"|否|设置自定义下拉刷新默认样式，支持设置black | white | none，none表示不使用默认样式。|
|refresher-background|string|transparent|否|设置自定义下拉刷新区域背景颜色，默认为透明。|
|refresher-triggered|boolean|false|否|设置当前下拉刷新状态，true表示下拉刷新已经被触发，false表示下拉刷新未被触发。|
|bounces|boolean|true|否|边界弹性控制（同时开启enhanced属性后生效）。 **起始版本：** 2.0.1|
|fast-deceleration|boolean|false|否|滑动减速速率控制（同时开启enhanced属性后生效）。 **起始版本：** 2.0.1|
|scroll-anchoring|boolean|false|否|开启scroll anchoring特性，即控制滚动位置不随内容变化而抖动。 **起始版本：** 2.0.1|
|enable-flex|boolean|false|否|启用flexbox布局。开启后，当前节点声明了display: flex就会成为flex container，并作用于其孩子节点。 **起始版本：** 2.0.1|
|paging-enabled|boolean|false|否|开启分页滚动（同时开启enhanced属性后生效）。 **起始版本：** 2.0.1|
|using-sticky|boolean|false|否|使scroll-view下的position: sticky特性生效。 **起始版本：** 2.0.1|

## 下拉刷新自定义内容

refresher-default-style设置为none时，在<scroll-view>下声明slot="refresher"的节点，可实现下拉刷新自定义内容，具体参考下面的下拉刷新自定义内容示例。

**起始版本：** 1.0.23

**事件：**

|名称|参数|描述|
|:-------------------|:----------|:-----------------------------------------|
|bindscrolltoupper|eventhandle|滚动到顶部/左边时触发。|
|bindscrolltolower|eventhandle|滚动到底部/右边时触发。|
|bindscroll|eventhandle|滚动时触发。|
|binddragstart|eventhandle|滑动开始事件（同时开启enhanced属性后生效）。 **起始版本：** 2.0.1|
|binddragging|eventhandle|滑动事件（同时开启enhanced属性后生效）。 **起始版本：** 2.0.1|
|binddragend|eventhandle|滑动结束事件（同时开启enhanced属性后生效）。 **起始版本：** 2.0.1|
|bindrefresherpulling|eventhandle|自定义下拉刷新控件被下拉。|
|bindrefresherrefresh|eventhandle|自定义下拉刷新被触发。|
|bindrefresherrestore|eventhandle|自定义下拉刷新被复位。|
|bindrefresherabort|eventhandle|自定义下拉刷新被中止。|

**示例：**

1. scroll-view组件示例：

   hxml文件：

   ```html
   <scroll-view
     scroll-y="{{scrollY}}"
     style="height: 50px"
     upper-threshold="50"
     lower-threshold="30px"
     bindscrolltoupper="scrollToUpperEvent"
     bindscrolltolower="scrollToLowerEvent"
     bindscroll="scrollEvent"
     bindrefresherpulling="refresherPullingEvent"
     bindrefresherrefresh="refresherRefreshEvent"
     bindrefresherrestore="refresherRestoreEvent"
     bindrefresherabort="refresherAbortEvent">
     <view id="demo1" class="scroll-view-item demo-text-1">1</view>
     <view id="demo2" class="scroll-view-item demo-text-2">2</view>
     <view id="demo3" class="scroll-view-item demo-text-3">3</view>
   </scroll-view>
   <view>自定义下拉刷新事件</view>
   <scroll-view
     class="page-section page-section-gap"
     scroll-y="{{scrollY}}"
     refresher-enabled="{{true}}"
     style="height: 500px"
     upper-threshold="50"
     lower-threshold="30px"
     bindscrolltoupper="scrollToUpperEvent"
     bindscrolltolower="scrollToLowerEvent"
     bindscroll="scrollEvent"
     bindrefresherpulling="refresherPullingEvent"
     bindrefresherrefresh="refresherRefreshEvent"
     bindrefresherrestore="refresherRestoreEvent"
     bindrefresherabort="refresherAbortEvent">
     <view id="demo1" class="scroll-view-item demo-text-1">3</view>
     <view id="demo2" class="scroll-view-item demo-text-2">4</view>
     <view id="demo3" class="scroll-view-item demo-text-3">5</view>
   </scroll-view>
   ```

   js文件：

   ```js
   Page({
     data: {
       scrollY: true,
       height: 50
     },
     scrollToUpperEvent(event) {
       // event.detail内容举例为：{"direction":""}
       console.info('scroll-view组件滚动到顶部/左边时触发，携带值为：', event.detail);
     },
     scrollToLowerEvent(event) {
       // event.detail内容举例为：{"direction":""}
       console.info('scroll-view组件滚动到底部/右边时触发，携带值为：', event.detail);
     },
     scrollEvent(event) {
       // event.detail内容举例为：{"scrollTop":0,"scrollLeft":0,"scrollWidth":0,"scrollHeight":0,"deltaY":0,"deltaX":0}
       console.info('scroll-view组件滚动时触发，携带值为：', event.detail);
     },
     refresherPullingEvent(event) {
       // event.detail内容举例为：{"dy":0}
       console.info('scroll-view组件自定义下拉刷新控件被下拉触发，携带值为：', event.detail);
     },
     refresherRefreshEvent(event) {
       // event.detail内容举例为：{"dy":0}
       console.info('scroll-view组件自定义下拉刷新被触发，携带值为：', event.detail);
     },
     refresherRestoreEvent(event) {
       // event.detail内容举例为：{"dy":0}
       console.info('scroll-view组件自定义下拉刷新被复位触发，携带值为：', event.detail);
     },
     refresherAbortEvent(event) {
       // event.detail内容举例为：{"dy":0}
       console.info('scroll-view组件自定义下拉刷新被中止触发，携带值为：', event.detail);
     }
   });
   ```

2. 下拉刷新自定义内容示例：

   hxml文件：

   ```html
   <view>
     <scroll-view
       style="width: 100%; height: 100vh"
       scroll-y="{{scrollY}}"
       refresher-enabled="{{refresherEnabled}}"
       refresher-threshold="{{refresherThreshold}}"
       refresher-default-style="{{refresherDefaultStyle}}"
       refresher-triggered="{{refresherTriggered}}"
       bindrefresherrefresh="refresherRefreshEvent">
       <view slot="refresher" class="custom-refresher">
         <view class="refresher-text">
           <text>下拉刷新中...</text>
         </view>
       </view>
       <view>
         <view class="scroll-view-item">列表内容1</view>
         <view class="scroll-view-item">列表内容2</view>
         <view class="scroll-view-item">列表内容3</view>
       </view>
     </scroll-view>
   </view>
   ```

   js文件：

   ```js
   Page({
     data: {
       scrollY: true,
       refresherEnabled: true,
       refresherThreshold: 45,
       refresherDefaultStyle: 'none',
       refresherTriggered: false
     },
     timeoutId: null,

     refresherRefreshEvent() {
       this.setData({
         refresherTriggered: true
       });
       if (this.timeoutId) {
         clearTimeout(this.timeoutId);
       }
       // 模拟内容刷新
       this.timeoutId = setTimeout(() => {
         this.setData({
           refresherTriggered: false
         });
         this.timeoutId = null;
       }, 2000);
     }
   });
   ```

   css文件：

   ```css
   .custom-refresher {
       width: 100%;
       height: 45px;
       background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
   }

   .refresher-text {
       font-size: 28rpx;
       color: white;
       font-weight: 500;
   }

   .scroll-view-item {
       padding: 50rpx;
   }
   ```

3. 边界弹性示例：

   hxml文件：

   ```html
   <view>
     <scroll-view
       style="width: 100%; height: 200px"
       scroll-y="{{scrollY}}"
       bounces="{{bounces}}"
       enhanced="{{enhanced}}">
       <view>
         <view class="scroll-view-item">列表内容1</view>
         <view class="scroll-view-item">列表内容2</view>
         <view class="scroll-view-item">列表内容3</view>
       </view>
     </scroll-view>
   </view>
   ```

   js文件：

   ```js
   Page({
     data: {
       scrollY: true,
       bounces: true,
       enhanced: true
     }
   });
   ```

   css文件：

   ```css
   .scroll-view-item {
       height: 100px;
       background-color: aliceblue;
   }
   ```

4. 滑动事件示例：

   hxml文件：

   ```html
   <view>
     <scroll-view
       style="width: 100%; height: 200px"
       scroll-y="{{scrollY}}"
       enhanced="{{enhanced}}"
       binddragstart="onDragStart"
       binddragging="onDragging"
       binddragend="onDragEnd">
       <view>
         <view class="scroll-view-item">列表内容1</view>
         <view class="scroll-view-item">列表内容2</view>
         <view class="scroll-view-item">列表内容3</view>
       </view>
     </scroll-view>
   </view>
   ```

   js文件：

   ```js
   Page({
     data: {
       scrollY: true,
       enhanced: true
     },
     onDragStart(event) {
       // event.detail内容举例为：{"scrollTop":"","scrollLeft":""}
       console.info('scroll-view组件开始滑动时触发，携带值为：', event.detail);
     },
     onDragging(event) {
       // event.detail内容举例为：{"scrollTop":"","scrollLeft":""}
       console.info('scroll-view组件滑动中触发，携带值为：', event.detail);
     },
     onDragEnd(event) {
       // event.detail内容举例为：{"scrollTop":"","scrollLeft":"","velocity":{"x":"","y":""}}
       console.info('scroll-view组件滑动结束时触发，携带值为：', event.detail);
     }
   });
   ```

   css文件：

   ```css
   .scroll-view-item {
       height: 100px;
       background-color: aliceblue;
   }
   ```

5. 快速减速示例：

   hxml文件：

   ```html
   <view>
     <scroll-view
       style="width: 100%; height: 200px"
       scroll-y="{{scrollY}}"
       fast-deceleration="{{fastDeceleration}}"
       enhanced="{{enhanced}}">
       <view>
         <view class="scroll-view-item">列表内容1</view>
         <view class="scroll-view-item">列表内容2</view>
         <view class="scroll-view-item">列表内容3</view>
         <view class="scroll-view-item">列表内容4</view>
         <view class="scroll-view-item">列表内容5</view>
       </view>
     </scroll-view>
   </view>
   ```

   js文件：

   ```js
   Page({
     data: {
       scrollY: true,
       fastDeceleration: true,
       enhanced: true
     }
   });
   ```

   css文件：

   ```css
   .scroll-view-item {
       height: 100px;
       background-color: aliceblue;
   }
   ```

6. flex布局示例：

   hxml文件：

   ```html
   <view>
     <scroll-view
       class="flex-scroll-view"
       scroll-y="{{scrollY}}"
       enable-flex="{{enableFlex}}"
       style="display: flex; flex-direction: row; flex-wrap: wrap; justify-content: center">
       <view id="{{'item-' + index}}" class="flex-item" has:for="{{itemCount}}" has:key="index">
           {{index+1}}
       </view>
     </scroll-view>
   </view>
   ```

   js文件：

   ```js
   Page({
     data: {
       scrollY: true,
       enableFlex: true,
       itemCount: 30
     }
   });
   ```

   css文件：

   ```css
   .flex-scroll-view {
       width: 100%;
       height: 300px;
       border: 1px solid #ccc;
       margin-bottom: 20px;
   }

   .flex-item {
       width: 75px;
       height: 60px;
       background: linear-gradient(135deg, #80d5cd 0%, #f19e9e 100%);
       color: #ffffff;
       text-align: center;
       line-height: 60px;
       margin: 5px;
       border-radius: 10px;
       flex-shrink: 0;
   }
   ```

7. 跳转到目标位置示例：

   hxml文件：

   ```html
   <view>
     <scroll-view
       style="width: 100%; height: 200px"
       scroll-y="{{scrollY}}"
       scroll-into-view="{{scrollIntoView}}"
       scroll-into-view-offset="{{scrollIntoViewOffset}}">
       <view>
         <view class="scroll-view-item">列表内容1</view>
         <view id="item2" class="scroll-view-item">列表内容2</view>
         <view class="scroll-view-item">列表内容3</view>
         <view class="scroll-view-item">列表内容4</view>
       </view>
     </scroll-view>
   </view>
   ```

   js文件：

   ```js
   Page({
     data: {
       scrollY: true,
       scrollIntoView: '',
       scrollIntoViewOffset: 50
     },
     onLoad() {
       setTimeout(() => {
         this.setData({
           scrollIntoView: 'item2'
         });
       }, 2000);
     }
   });
   ```

   css文件：

   ```css
   .scroll-view-item {
       height: 100px;
       background-color: aliceblue;
   }
   ```

8. 分页滚动示例：

   hxml文件：

   ```html
   <view>
     <scroll-view
       style="width: 100%; height: 200px"
       scroll-y="{{scrollY}}"
       paging-enabled="{{pagingEnabled}}"
       enhanced="{{enhanced}}">
       <view>
         <view class="scroll-view-item">第一页</view>
         <view class="scroll-view-item">第二页</view>
         <view class="scroll-view-item">第三页</view>
         <view class="scroll-view-item">第四页</view>
       </view>
     </scroll-view>
   </view>
   ```

   js文件：

   ```js
   Page({
     data: {
       scrollY: true,
       pagingEnabled: true,
       enhanced: true
     }
   });
   ```

   css文件：

   ```css
   .scroll-view-item {
       height: 200px;
       background-color: aliceblue;
   }
   ```

9. sticky特性示例：

   hxml文件：

   ```html
   <view>
     <scroll-view
       style="width: 100%; height: 300px"
       scroll-y="{{scrollY}}"
       using-sticky="{{usingSticky}}">
       <view>
         <view id="item1" class="scroll-view-item">列表内容1</view>
         <view id="item2" class="scroll-view-item">列表内容2</view>
         <view id="item3" class="scroll-view-item">列表内容3</view>
         <view id="item4" class="scroll-view-item">列表内容4</view>
         <view id="item5" class="scroll-view-item">列表内容5</view>
         <view id="item6" class="scroll-view-item">列表内容6</view>
         <view id="item7" class="scroll-view-item">列表内容7</view>
       </view>
     </scroll-view>
   </view>
   ```

   js文件：

   ```js
   Page({
     data: {
       scrollY: true,
       usingSticky: true
     }
   });
   ```

   css文件：

   ```css
   .scroll-view-item {
       height: 100px;
       background-color: aliceblue;
   }

   #item2 {
       position: sticky;
       top: 0;
       background-color: #fee2e2;
   }

   #item4 {
       position: sticky;
       bottom: 0;
       background-color: #fee2e2;
   }
   ```

