Skip to content

Commit 52a227f

Browse files
authored
Merge pull request #17 from itenl/dev-1.1.1
Dev 1.1.1
2 parents ab171fa + a43130d commit 52a227f

File tree

5 files changed

+84
-42
lines changed

5 files changed

+84
-42
lines changed

README-zh_CN.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
* [Injection lifecycle to Screen](#InjectionLifecycle)
2020
* [Injection props to Screen](#InjectionScreenProps)
2121
* [Injection props to Sticky](#InjectionStickyProps)
22+
* [Known Issues](#KnownIssues)
2223
* [Snapshot](#Snapshot)
2324

2425
## <a name="features"/>Features
@@ -188,13 +189,17 @@ Prop | Type | Default | Description
188189
</ScrollableTabView>
189190
this.scrollableTabView.getCurrentRef();
190191
this.scrollableTabView.toTabView(1);
192+
this.scrollableTabView.scrollTo(0);
193+
this.scrollableTabView.clearStacks(()=>alert('done'));
194+
191195
```
192196

193197
Name | Type | Description
194198
----------------- | -------- | -----------
195199
**`getCurrentRef(index: number.optional)`** | Function | 获取当前活动的视图的实例,可传 **`index`** 获取指定实例
196200
**`toTabView(index: number.required / label: string.required)`** | Function | 跳到指定 Screen
197201
**`scrollTo(index: number.required)`** | Function | 上下滑动至指定位置 (传入 0 默认定位至 tabs / 传入负数则置顶)
202+
**`clearStacks(callback: function.optional)`** | Function | 清空栈以及相关状态 (Tabs / Badge / Stacks))
198203

199204
## <a name="StackProperty"/>Stack Property
200205

@@ -240,6 +245,8 @@ Name | Type | Description
240245
----------------- | -------- | -----------
241246
**`screenContext`** | Object | 获取 Screen 上下文
242247

248+
## <a name="KnownIssues"/>Known Issues
249+
- 如果你仅仅是新增 `Stack` 可以 `Push` 即可,但如果需要更新或者删除 `Stack` 请使用 [clearStacks](#Method) 后在添加你所需要的 `Stacks`
243250

244251
## <a name="Snapshot"/>Snapshot
245252

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Based on pure `JS` scripts, without relying on native, no need for `react-native
1919
* [Injection lifecycle to Screen](#InjectionLifecycle)
2020
* [Injection props to Screen](#InjectionScreenProps)
2121
* [Injection props to Sticky](#InjectionStickyProps)
22+
* [Known Issues](#KnownIssues)
2223
* [Snapshot](#Snapshot)
2324

2425
## <a name="features"/>Features
@@ -189,13 +190,15 @@ Prop | Type | Default | Description
189190
this.scrollableTabView.getCurrentRef();
190191
this.scrollableTabView.toTabView(1);
191192
this.scrollableTabView.scrollTo(0);
193+
this.scrollableTabView.clearStacks(()=>alert('done'));
192194
```
193195

194196
Name | Type | Description
195197
----------------- | -------- | -----------
196198
**`getCurrentRef(index: number.optional)`** | Function | Get the instance of the currently active view, you can pass **`index`** to get the specified instance
197199
**`toTabView(index: number.required / label: string.required)`** | Function | Jump to the specified Screen
198200
**`scrollTo(index: number.required)`** | Function | Swipe up and down to the specified position (passing in 0 is the default positioning to tabs / passing in a negative number is set to the top)
201+
**`clearStacks(callback: function.optional)`** | Function | Clear the Stacks and related state (Tabs / Badge / Stacks))
199202

200203
## <a name="StackProperty"/>Stack Property
201204

@@ -241,6 +244,8 @@ Name | Type | Description
241244
----------------- | -------- | -----------
242245
**`screenContext`** | Object | Get Screen context
243246

247+
## <a name="KnownIssues"/>Known Issues
248+
- If you just add a `Stack`, you can `Push`, but if you need to update or delete a `Stack`, please use [clearStacks](#Method) and then add the `Stacks` you need
244249

245250
## <a name="Snapshot"/>Snapshot
246251

package-lock.json

Lines changed: 6 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
{
22
"name": "@itenl/react-native-scrollable-tabview",
3-
"version": "1.1.0",
3+
"version": "1.1.1",
44
"description": "react-native-scrollable-tabview",
55
"main": "index.js",
66
"scripts": {
77
"test": "echo \"Error: no test specified\" && exit 1"
88
},
99
"dependencies": {
1010
"lodash.throttle": "^4.1.1",
11-
"react-native-snap-carousel": "^4.0.0-beta.6"
11+
"react-native-snap-carousel": "git+https://github.com/itenl/react-native-snap-carousel.git#8b7f0fcad966e56ef1b86fc6ff90dcefdaed9527"
1212
},
1313
"keywords": [
1414
"react",

src/index.js

Lines changed: 64 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,7 @@ export default class ScrollableTabView extends React.Component {
9696
constructor(props) {
9797
super(props);
9898
this.state = {
99-
checkedIndex: this._getFirstIndex(),
100-
refsObj: {},
101-
lazyIndexs: this._initLazyIndexs(),
102-
isRefreshing: false
99+
...this._initialState()
103100
};
104101
this.sectionListScrollY = new Animated.Value(0);
105102
this.carouselScrollX = new Animated.Value(0);
@@ -134,6 +131,15 @@ export default class ScrollableTabView extends React.Component {
134131
this._initial(newProps, true);
135132
}
136133

134+
_initialState() {
135+
return {
136+
checkedIndex: this._getFirstIndex(),
137+
refsObj: {},
138+
lazyIndexs: this._initLazyIndexs(),
139+
isRefreshing: false
140+
};
141+
}
142+
137143
_initial(props = this.props, isProcess = false) {
138144
isProcess && this._toProcess(props);
139145
this.tabs = this._getTabs(props);
@@ -199,12 +205,25 @@ export default class ScrollableTabView extends React.Component {
199205
return ref => {
200206
if (this.state.refsObj[index] && this.state.refsObj[index] === ref) return;
201207
this.state.refsObj[index] = ref;
208+
this.state.refsObj[index].__id__ = id;
202209
this.setState({
203210
refsObj: this.state.refsObj
204211
});
205212
};
206213
}
207214

215+
clearStacks = callback => {
216+
this.tabs = [];
217+
this.badges = [];
218+
this.stacks = [];
219+
this.setState(
220+
{
221+
...this._initialState()
222+
},
223+
() => typeof callback === 'function' && callback()
224+
);
225+
};
226+
208227
getCurrentRef(index) {
209228
return this.state.refsObj[index ?? this.state.checkedIndex];
210229
}
@@ -365,6 +384,7 @@ export default class ScrollableTabView extends React.Component {
365384
const { oneTabHidden, tabsShown, tabsStyle, tabStyle, useScroll, tabsEnableAnimated, useScrollStyle } = this.props;
366385
const { width } = tabStyle;
367386
if (tabsEnableAnimated && tabStyle && width == undefined) throw new Error('When tabsEnableAnimated is true, the width must be specified for tabStyle');
387+
if (useScroll && tabStyle && width == undefined) throw new Error('When useScroll is true, the width must be specified for tabStyle');
368388
const renderTab = !(oneTabHidden && this.tabs && this.tabs.length == 1) && tabsShown;
369389
const _tabsStyle = Object.assign({}, !useScroll && { alignItems: 'center', justifyContent: 'space-around' }, styles.tabsStyle, tabsStyle);
370390
this.layoutHeight['tabs'] = renderTab ? _tabsStyle.height : 0;
@@ -414,6 +434,7 @@ export default class ScrollableTabView extends React.Component {
414434
});
415435
};
416436

437+
// 启用 useScroll 情况下保证滚动条跟随
417438
_tabTranslateX(index = this.state.checkedIndex) {
418439
const { useScroll } = this.props;
419440
if (useScroll && this.scrollview && this.tabWidth) {
@@ -423,26 +444,31 @@ export default class ScrollableTabView extends React.Component {
423444
}
424445
}
425446

447+
_resetOtherRefs() {
448+
const checkedIndex = this.state.checkedIndex;
449+
if (this.state.refsObj && this.state.refsObj[checkedIndex]) this.state.refsObj[checkedIndex] = null;
450+
return this.state.refsObj;
451+
}
452+
426453
_onTabviewChange(isCarouselScroll, index) {
427-
const { toHeaderOnTab, toTabsOnTab, onTabviewChanged } = this.props;
454+
const { enableCachePage, toHeaderOnTab, toTabsOnTab, onTabviewChanged } = this.props;
428455
if (index == this.state.checkedIndex) {
429456
if (!isCarouselScroll && toHeaderOnTab) return this._scrollTo(-this.layoutHeight['header']);
430457
if (!isCarouselScroll && toTabsOnTab) return this._scrollTo(0);
431458
return void 0;
432459
}
433460
if (!this.state.lazyIndexs.includes(index)) this.state.lazyIndexs.push(index);
434-
this.setState(
435-
{
436-
checkedIndex: index,
437-
lazyIndexs: this.state.lazyIndexs
438-
},
439-
() => {
440-
if (onTabviewChanged) {
441-
const tab = this.tabs[this.state.checkedIndex];
442-
onTabviewChanged(this.state.checkedIndex, tab && tab.tabLabel);
443-
}
461+
let state = {
462+
checkedIndex: index,
463+
lazyIndexs: this.state.lazyIndexs
464+
};
465+
if (!enableCachePage) state.refsObj = this._resetOtherRefs();
466+
this.setState(state, () => {
467+
if (onTabviewChanged) {
468+
const tab = this.tabs[this.state.checkedIndex];
469+
onTabviewChanged(this.state.checkedIndex, tab && tab.tabLabel);
444470
}
445-
);
471+
});
446472
this._tabTranslateX(index);
447473
// 非滑动触发的情况下需要同步index,避免Carousel无法正常显示
448474
// !isCarouselScroll && this._snapToItem(index);
@@ -464,21 +490,22 @@ export default class ScrollableTabView extends React.Component {
464490
}
465491

466492
_renderItem({ item, index }) {
493+
const { enableCachePage, fillScreen, fixedTabs, mappingProps } = this.props;
467494
const screenHeight = this._getScreenHeight();
468495
return (
469-
(this.props.enableCachePage ? this.props.enableCachePage : this.state.checkedIndex == index) &&
496+
(enableCachePage ? enableCachePage : this.state.checkedIndex == index) &&
470497
(this.getCurrentRef(index) || this.getCurrentRef(index) == undefined) &&
471498
this._getLazyIndexs(index) && (
472499
<View
473500
style={[
474501
{ flex: 1 },
475-
this.props.enableCachePage && this.state.checkedIndex != index && { maxHeight: screenHeight },
476-
this.props.enableCachePage && this.state.checkedIndex == index && this.props.fillScreen && { minHeight: screenHeight },
477-
this.props.enableCachePage && this.state.checkedIndex == index && this.props.fixedTabs && { minHeight: this._getMaximumScreenHeight() },
478-
!this.props.enableCachePage && this.state.checkedIndex == index && { minHeight: screenHeight }
502+
enableCachePage && this.state.checkedIndex != index && { maxHeight: screenHeight },
503+
enableCachePage && this.state.checkedIndex == index && fillScreen && { minHeight: screenHeight },
504+
enableCachePage && this.state.checkedIndex == index && fixedTabs && { minHeight: this._getMaximumScreenHeight() },
505+
!enableCachePage && this.state.checkedIndex == index && { minHeight: screenHeight }
479506
]}
480507
>
481-
<item.screen {...this._getProps(this.props.mappingProps)} {...(item.toProps || {})} />
508+
<item.screen {...this._getProps(mappingProps)} {...(item.toProps || {})} />
482509
</View>
483510
)
484511
);
@@ -487,6 +514,7 @@ export default class ScrollableTabView extends React.Component {
487514
_onEndReached() {
488515
const next = () => {
489516
const ref = this.getCurrentRef();
517+
!ref && console.warn(`The Screen Ref is lost when calling onEndReached. Please confirm whether the Stack is working properly.(index: ${this.state.checkedIndex})`);
490518
if (ref && ref.onEndReached && typeof ref.onEndReached == 'function') ref.onEndReached();
491519
};
492520
const { onBeforeEndReached } = this.props;
@@ -502,6 +530,7 @@ export default class ScrollableTabView extends React.Component {
502530
_onRefresh() {
503531
const next = () => {
504532
const ref = this.getCurrentRef();
533+
!ref && console.warn(`The Screen Ref is lost when calling onRefresh. Please confirm whether the Stack is working properly.(index: ${this.state.checkedIndex})`);
505534
if (ref && ref.onRefresh && typeof ref.onRefresh == 'function') ref.onRefresh(this._toggledRefreshing.bind(this));
506535
};
507536
const { onBeforeRefresh } = this.props;
@@ -545,32 +574,34 @@ export default class ScrollableTabView extends React.Component {
545574
};
546575

547576
render() {
577+
const { style, title, onEndReachedThreshold, fixedHeader, tabsEnableAnimated, carouselProps, onScroll, sectionListProps } = this.props;
548578
return (
549579
<View
550580
onLayout={({ nativeEvent }) => {
551581
const { height } = nativeEvent.layout;
552582
this.layoutHeight['container'] = height;
553583
if (height !== 0) this._refresh();
554584
}}
555-
style={[styles.container, this.props.style]}
585+
style={[styles.container, style]}
556586
>
557-
{!!this.props.title && this._renderTitle()}
587+
{!!title && this._renderTitle()}
558588
<SectionList
559589
ref={rf => (this.section = rf)}
560590
keyExtractor={(item, index) => `scrollable-tab-view-wrap-${index}`}
561591
renderSectionHeader={this._renderSectionHeader.bind(this)}
562592
onEndReached={this._onEndReached.bind(this)}
563-
onEndReachedThreshold={this.props.onEndReachedThreshold}
593+
onEndReachedThreshold={onEndReachedThreshold}
564594
refreshControl={<RefreshControl refreshing={this.state.isRefreshing} onRefresh={this._onRefresh.bind(this)} />}
565595
sections={[{ data: [1] }]}
566596
stickySectionHeadersEnabled={true}
567-
ListHeaderComponent={!this.props.fixedHeader && this._renderHeader()}
597+
ListHeaderComponent={!fixedHeader && this._renderHeader()}
568598
showsVerticalScrollIndicator={false}
569599
showsHorizontalScrollIndicator={false}
570600
renderItem={() => {
571601
return (
572602
<Carousel
573603
ref={c => (this.tabview = c)}
604+
pagingEnabled={true}
574605
inactiveSlideScale={1}
575606
data={this.stacks}
576607
renderItem={this._renderItem.bind(this)}
@@ -585,7 +616,7 @@ export default class ScrollableTabView extends React.Component {
585616
index
586617
})}
587618
onScroll={
588-
this.props.tabsEnableAnimated &&
619+
tabsEnableAnimated &&
589620
Animated.event(
590621
[
591622
{
@@ -599,29 +630,29 @@ export default class ScrollableTabView extends React.Component {
599630
}
600631
)
601632
}
602-
{...this.props.carouselProps}
633+
{...carouselProps}
603634
/>
604635
);
605636
}}
606637
onScrollToIndexFailed={() => {}}
607638
onScroll={
608-
!!this.props.title
639+
!!title
609640
? Animated.event(
610641
[
611642
{
612643
nativeEvent: { contentOffset: { y: this.sectionListScrollY } }
613644
}
614645
],
615646
{
616-
listener: !!this.props.onScroll && this.props.onScroll.bind(this),
647+
listener: !!onScroll && onScroll.bind(this),
617648
useNativeDriver: false
618649
}
619650
)
620-
: !!this.props.onScroll
621-
? this.props.onScroll.bind(this)
651+
: !!onScroll
652+
? onScroll.bind(this)
622653
: null
623654
}
624-
{...this.props.sectionListProps}
655+
{...sectionListProps}
625656
></SectionList>
626657
</View>
627658
);

0 commit comments

Comments
 (0)