react-native-refresh-loadmore-recyclerlistview
Version:
The listview that you need and deserve. It was built for performance, uses cell recycling to achieve smooth scrolling.
138 lines • 4.88 kB
JavaScript
import CustomError from "../exceptions/CustomError";
export default class LayoutManager {
constructor(layoutProvider, dimensions, isHorizontal = false, cachedLayouts) {
this._layoutProvider = layoutProvider;
this._window = dimensions;
this._totalHeight = 0;
this._totalWidth = 0;
this._layouts = cachedLayouts ? cachedLayouts : [];
this._isHorizontal = isHorizontal;
}
getLayoutDimension() {
return { height: this._totalHeight, width: this._totalWidth };
}
getLayouts() {
return this._layouts;
}
getOffsetForIndex(index) {
if (this._layouts.length > index) {
return { x: this._layouts[index].x, y: this._layouts[index].y };
}
throw new CustomError({
message: "No layout available for index: " + index,
type: "LayoutUnavailableException",
});
}
overrideLayout(index, dim) {
const layout = this._layouts[index];
if (layout) {
layout.isOverridden = true;
layout.width = dim.width;
layout.height = dim.height;
}
}
setMaxBounds(itemDim) {
if (this._isHorizontal) {
itemDim.height = Math.min(this._window.height, itemDim.height);
}
else {
itemDim.width = Math.min(this._window.width, itemDim.width);
}
}
reLayoutFromIndex(startIndex, itemCount) {
let startIndexTMp = this._locateFirstNeighbourIndex(startIndex);
let startX = 0, startY = 0, maxBound = 0;
const startVal = this._layouts[startIndexTMp];
if (startVal) {
startX = startVal.x;
startY = startVal.y;
this._pointDimensionsToRect(startVal);
}
const oldItemCount = this._layouts.length, itemDim = { height: 0, width: 0 };
let itemRect = null, oldLayout = null;
for (let i = startIndexTMp; i < itemCount; i++) {
oldLayout = this._layouts[i];
if (oldLayout && oldLayout.isOverridden) {
itemDim.height = oldLayout.height;
itemDim.width = oldLayout.width;
}
else {
this._layoutProvider.setLayoutForType(this._layoutProvider.getLayoutTypeForIndex(i), itemDim, i);
}
this.setMaxBounds(itemDim);
while (!this._checkBounds(startX, startY, itemDim, this._isHorizontal)) {
if (this._isHorizontal) {
startX += maxBound;
startY = 0;
this._totalWidth += maxBound;
}
else {
startX = 0;
startY += maxBound;
this._totalHeight += maxBound;
}
maxBound = 0;
}
maxBound = this._isHorizontal ? Math.max(maxBound, itemDim.width) : Math.max(maxBound, itemDim.height);
if (i > oldItemCount - 1) {
this._layouts.push({ x: startX, y: startY, height: itemDim.height, width: itemDim.width });
}
else {
itemRect = this._layouts[i];
itemRect.x = startX;
itemRect.y = startY;
itemRect.width = itemDim.width;
itemRect.height = itemDim.height;
}
if (this._isHorizontal) {
startY += itemDim.height;
}
else {
startX += itemDim.width;
}
}
if (oldItemCount > itemCount) {
this._layouts.splice(itemCount, oldItemCount - itemCount);
}
this._setFinalDimensions(maxBound);
}
_pointDimensionsToRect(itemRect) {
if (this._isHorizontal) {
this._totalWidth = itemRect.x;
}
else {
this._totalHeight = itemRect.y;
}
}
_setFinalDimensions(maxBound) {
if (this._isHorizontal) {
this._totalHeight = this._window.height;
this._totalWidth += maxBound;
}
else {
this._totalWidth = this._window.width;
this._totalHeight += maxBound;
}
}
_locateFirstNeighbourIndex(startIndex) {
if (startIndex === 0) {
return 0;
}
let i = startIndex - 1;
for (; i >= 0; i--) {
if (this._isHorizontal) {
if (this._layouts[i].y === 0) {
break;
}
}
else if (this._layouts[i].x === 0) {
break;
}
}
return i;
}
_checkBounds(itemX, itemY, itemDim, isHorizontal) {
return isHorizontal ? (itemY + itemDim.height <= this._window.height) : (itemX + itemDim.width <= this._window.width);
}
}
//# sourceMappingURL=LayoutManager.js.map