Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update itemHeight in Scroller.js #365

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
181 changes: 103 additions & 78 deletions src/Scroller.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@
import React, { Component } from "react";
import { View } from "react-native";
import PropTypes from "prop-types";
import { RecyclerListView, DataProvider, LayoutProvider } from "recyclerlistview";
import {
RecyclerListView,
DataProvider,
LayoutProvider,
} from "recyclerlistview";
import moment from "moment";

export default class CalendarScroller extends Component {
Expand All @@ -25,8 +29,8 @@ export default class CalendarScroller extends Component {
onWeekScrollStart: PropTypes.func,
onWeekScrollEnd: PropTypes.func,
externalScrollView: PropTypes.func,
pagingEnabled: PropTypes.bool
}
pagingEnabled: PropTypes.bool,
};

static defaultProps = {
data: [],
Expand All @@ -38,32 +42,33 @@ export default class CalendarScroller extends Component {

this.timeoutResetPositionId = null;

this.updateLayout = renderDayParams => {
const itemHeight = renderDayParams.height;
const itemWidth = renderDayParams.width + renderDayParams.marginHorizontal * 2;
this.updateLayout = (renderDayParams) => {
const itemHeight = 100;
const itemWidth =
renderDayParams.width + renderDayParams.marginHorizontal * 2;

const layoutProvider = new LayoutProvider(
index => 0, // only 1 view type
(index) => 0, // only 1 view type
(type, dim) => {
dim.width = itemWidth;
dim.height = itemHeight;
}
);

return { layoutProvider, itemHeight, itemWidth };
}
};

this.dataProvider = new DataProvider((r1, r2) => {
return r1 !== r2;
});

this.updateDaysData = data => {
this.updateDaysData = (data) => {
return {
data,
numDays: data.length,
dataProvider: this.dataProvider.cloneWithRows(data),
}
}
};
};

this.state = {
...this.updateLayout(props.renderDayParams),
Expand All @@ -83,12 +88,11 @@ export default class CalendarScroller extends Component {
let newState = {};
let updateState = false;

const {
width,
height,
selectedDate
} = this.props.renderDayParams;
if (width !== prevProps.renderDayParams.width || height !== prevProps.renderDayParams.height) {
const { width, height, selectedDate } = this.props.renderDayParams;
if (
width !== prevProps.renderDayParams.width ||
height !== prevProps.renderDayParams.height
) {
updateState = true;
newState = this.updateLayout(this.props.renderDayParams);
}
Expand All @@ -99,7 +103,7 @@ export default class CalendarScroller extends Component {

if (this.props.data !== prevProps.data) {
updateState = true;
newState = {...newState, ...this.updateDaysData(this.props.data)};
newState = { ...newState, ...this.updateDaysData(this.props.data) };
}

if (updateState) {
Expand All @@ -112,27 +116,30 @@ export default class CalendarScroller extends Component {
if (this.state.visibleStartIndex === 0) {
return;
}
const newIndex = Math.max(this.state.visibleStartIndex - this.state.numVisibleItems, 0);
const newIndex = Math.max(
this.state.visibleStartIndex - this.state.numVisibleItems,
0
);
this.rlv.scrollToIndex(newIndex, true);
}
};

// Scroll right, guarding against end index.
scrollRight = () => {
const newIndex = this.state.visibleStartIndex + this.state.numVisibleItems;
if (newIndex >= (this.state.numDays - 1)) {
if (newIndex >= this.state.numDays - 1) {
this.rlv.scrollToEnd(true); // scroll to the very end, including padding
return;
}
this.rlv.scrollToIndex(newIndex, true);
}
};

// Scroll to given date, and check against min and max date if available.
scrollToDate = (date) => {
let targetDate = moment(date).subtract(Math.round(this.state.numVisibleItems / 2) - 1, "days");
const {
minDate,
maxDate,
} = this.props;
let targetDate = moment(date).subtract(
Math.round(this.state.numVisibleItems / 2) - 1,
"days"
);
const { minDate, maxDate } = this.props;

// Falls back to min or max date when the given date exceeds the available dates
if (minDate && targetDate.isBefore(minDate, "day")) {
Expand All @@ -147,30 +154,31 @@ export default class CalendarScroller extends Component {
break;
}
}
}
};

// Shift dates when end of list is reached.
shiftDaysForward = (visibleStartDate = this.state.visibleStartDate) => {
const prevVisStart = visibleStartDate.clone();
const newStartDate = prevVisStart.clone().subtract(Math.floor(this.state.numDays / 3), "days");
const newStartDate = prevVisStart
.clone()
.subtract(Math.floor(this.state.numDays / 3), "days");
this.updateDays(prevVisStart, newStartDate);
}
};

// Shift dates when beginning of list is reached.
shiftDaysBackward = (visibleStartDate) => {
const prevVisStart = visibleStartDate.clone();
const newStartDate = prevVisStart.clone().subtract(Math.floor(this.state.numDays * 2/3), "days");
const newStartDate = prevVisStart
.clone()
.subtract(Math.floor((this.state.numDays * 2) / 3), "days");
this.updateDays(prevVisStart, newStartDate);
}
};

updateDays = (prevVisStart, newStartDate) => {
if (this.shifting) {
return;
}
const {
minDate,
maxDate,
} = this.props;
const { minDate, maxDate } = this.props;
const data = [];
let _newStartDate = newStartDate;
if (minDate && newStartDate.isBefore(minDate, "day")) {
Expand All @@ -181,7 +189,7 @@ export default class CalendarScroller extends Component {
if (maxDate && date.isAfter(maxDate, "day")) {
break;
}
data.push({date});
data.push({ date });
}
// Prevent reducing range when the minDate - maxDate range is small.
if (data.length < this.props.maxSimultaneousDays) {
Expand All @@ -207,7 +215,7 @@ export default class CalendarScroller extends Component {
data,
dataProvider: this.dataProvider.cloneWithRows(data),
});
}
};

// Track which dates are visible.
onVisibleIndicesChanged = (all, now, notNow) => {
Expand All @@ -219,23 +227,29 @@ export default class CalendarScroller extends Component {
visibleEndDate: _visEndDate,
} = this.state;
const visibleStartIndex = all[0];
const visibleStartDate = data[visibleStartIndex] ? data[visibleStartIndex].date : moment();
const visibleEndIndex = Math.min(visibleStartIndex + numVisibleItems - 1, data.length - 1);
const visibleEndDate = data[visibleEndIndex] ? data[visibleEndIndex].date : moment();
const visibleStartDate = data[visibleStartIndex]
? data[visibleStartIndex].date
: moment();
const visibleEndIndex = Math.min(
visibleStartIndex + numVisibleItems - 1,
data.length - 1
);
const visibleEndDate = data[visibleEndIndex]
? data[visibleEndIndex].date
: moment();

const {
updateMonthYear,
onWeekChanged,
} = this.props;
const { updateMonthYear, onWeekChanged } = this.props;

// Fire month/year update on both week and month changes. This is
// necessary for the header and onWeekChanged updates.
if (!_visStartDate || !_visEndDate ||
!visibleStartDate.isSame(_visStartDate, "week") ||
!visibleEndDate.isSame(_visEndDate, "week") ||
!visibleStartDate.isSame(_visStartDate, "month") ||
!visibleEndDate.isSame(_visEndDate, "month") )
{
if (
!_visStartDate ||
!_visEndDate ||
!visibleStartDate.isSame(_visStartDate, "week") ||
!visibleEndDate.isSame(_visEndDate, "week") ||
!visibleStartDate.isSame(_visStartDate, "month") ||
!visibleEndDate.isSame(_visEndDate, "month")
) {
const visStart = visibleStartDate && visibleStartDate.clone();
const visEnd = visibleEndDate && visibleEndDate.clone();
onWeekChanged && onWeekChanged(visStart, visEnd);
Expand All @@ -262,33 +276,30 @@ export default class CalendarScroller extends Component {
visibleEndDate,
visibleStartIndex,
});
}
};

onScrollStart = (event) => {
const {onWeekScrollStart} = this.props;
const {prevStartDate, prevEndDate} = this.state;
const { onWeekScrollStart } = this.props;
const { prevStartDate, prevEndDate } = this.state;

if (onWeekScrollStart && prevStartDate && prevEndDate) {
onWeekScrollStart(prevStartDate.clone(), prevEndDate.clone());
}
}
};

onScrollEnd = () => {
const {onWeekScrollEnd} = this.props;
const {visibleStartDate, visibleEndDate, prevEndDate} = this.state;
const { onWeekScrollEnd } = this.props;
const { visibleStartDate, visibleEndDate, prevEndDate } = this.state;

if (onWeekScrollEnd && visibleStartDate && visibleEndDate) {
if (!visibleEndDate.isSame(prevEndDate, "day")) {
onWeekScrollEnd(visibleStartDate.clone(), visibleEndDate.clone());
}
}
}
};

onScrollBeginDrag = () => {
const {
onWeekScrollStart,
onWeekScrollEnd,
} = this.props;
const { onWeekScrollStart, onWeekScrollEnd } = this.props;
// Prev dates required only if scroll callbacks are defined
if (!onWeekScrollStart && !onWeekScrollEnd) {
return;
Expand All @@ -300,45 +311,59 @@ export default class CalendarScroller extends Component {
visibleStartIndex,
visibleEndIndex,
} = this.state;
const prevStartDate = visibleStartDate ? visibleStartDate
: (data[visibleStartIndex] ? data[visibleStartIndex].date : moment());
const prevEndDate = visibleEndDate ? visibleEndDate
: (data[visibleEndIndex] ? data[visibleEndIndex].date : moment());
const prevStartDate = visibleStartDate
? visibleStartDate
: data[visibleStartIndex]
? data[visibleStartIndex].date
: moment();
const prevEndDate = visibleEndDate
? visibleEndDate
: data[visibleEndIndex]
? data[visibleEndIndex].date
: moment();

this.setState({
prevStartDate,
prevEndDate,
});
}
};

onLayout = event => {
onLayout = (event) => {
let width = event.nativeEvent.layout.width;
this.setState({
numVisibleItems: Math.round(width / this.state.itemWidth),
});
}
};

rowRenderer = (type, data, i, extState) => {
return this.props.renderDay && this.props.renderDay({...data, ...extState});
}
return (
this.props.renderDay && this.props.renderDay({ ...data, ...extState })
);
};

render() {
if (!this.state.data || this.state.numDays === 0 || !this.state.itemHeight) {
if (
!this.state.data ||
this.state.numDays === 0 ||
!this.state.itemHeight
) {
return null;
}

const pagingProps = this.props.pagingEnabled ? {
decelerationRate: 0,
snapToInterval: this.state.itemWidth * this.state.numVisibleItems
} : {};
const pagingProps = this.props.pagingEnabled
? {
decelerationRate: 0,
snapToInterval: this.state.itemWidth * this.state.numVisibleItems,
}
: {};

return (
<View
style={{ height: this.state.itemHeight, flex: 1 }}
onLayout={this.onLayout}
>
<RecyclerListView
ref={rlv => this.rlv = rlv}
ref={(rlv) => (this.rlv = rlv)}
layoutProvider={this.state.layoutProvider}
dataProvider={this.state.dataProvider}
rowRenderer={this.rowRenderer}
Expand All @@ -353,7 +378,7 @@ export default class CalendarScroller extends Component {
onMomentumScrollBegin: this.onScrollStart,
onMomentumScrollEnd: this.onScrollEnd,
onScrollBeginDrag: this.onScrollBeginDrag,
...pagingProps
...pagingProps,
}}
/>
</View>
Expand Down