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

Move GridLayoutProvider inside RLV #462

Merged
merged 4 commits into from
Feb 5, 2020
Merged
Show file tree
Hide file tree
Changes from 3 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
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "recyclerlistview",
"version": "3.0.0",
"version": "3.0.1",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 is still not published, let's keep it the same

"description": "The listview that you need and deserve. It was built for performance, uses cell recycling to achieve smooth scrolling.",
"main": "dist/reactnative/index.js",
"types": "dist/reactnative/index.d.ts",
Expand Down Expand Up @@ -36,7 +36,6 @@
"dependencies": {
"lodash.debounce": "4.0.8",
"prop-types": "15.5.8",
"recyclerlistview-gridlayoutprovider": "1.0.1",
"ts-object-utils": "0.0.5"
},
"peerDependencies": {
Expand Down
57 changes: 57 additions & 0 deletions src/core/dependencies/GridLayoutProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { LayoutProvider, Dimension } from "./LayoutProvider";
import { Layout, LayoutManager } from "../layoutmanager/LayoutManager";
import { GridLayoutManager } from "../layoutmanager/GridLayoutManager";

export class GridLayoutProvider extends LayoutProvider {
private _getHeightOrWidth: (index: number) => number;
private _getSpan: (index: number) => number;
private _maxSpan: number;
private _renderWindowSize?: Dimension;
private _isHorizontal?: boolean;
private _acceptableRelayoutDelta: number;
constructor(
maxSpan: number,
getLayoutType: (index: number) => string | number,
getSpan: (index: number) => number,
// If horizonal return width while spans will be rowspans. Opposite holds true if not horizontal
getHeightOrWidth: (index: number) => number,
acceptableRelayoutDelta?: number,
) {
super(
getLayoutType,
(type: string | number, dimension: Dimension, index: number) => {
this.setLayout(dimension, index);
},
);
this._getHeightOrWidth = getHeightOrWidth;
this._getSpan = getSpan;
this._maxSpan = maxSpan;
this._acceptableRelayoutDelta = ((acceptableRelayoutDelta === undefined) || (acceptableRelayoutDelta === null)) ? 1 : acceptableRelayoutDelta;
}

public newLayoutManager(renderWindowSize: Dimension, isHorizontal?: boolean, cachedLayouts?: Layout[]): LayoutManager {
this._isHorizontal = isHorizontal;
this._renderWindowSize = renderWindowSize;
return new GridLayoutManager(this, renderWindowSize, this._getSpan, this._maxSpan, this._acceptableRelayoutDelta, this._isHorizontal, cachedLayouts);
}

private setLayout(dimension: Dimension, index: number): void {
const maxSpan: number = this._maxSpan;
const itemSpan: number = this._getSpan(index);
if (itemSpan > maxSpan) {
throw new Error("Item span for index " + index + " is more than the max span");
}
if (this._renderWindowSize) {
if (this._isHorizontal) {
dimension.width = this._getHeightOrWidth(index);
dimension.height = (this._renderWindowSize.height / maxSpan) * itemSpan;

} else {
dimension.height = this._getHeightOrWidth(index);
dimension.width = (this._renderWindowSize.width / maxSpan) * itemSpan;
}
} else {
throw new Error("setLayout called before layoutmanager was created, cannot be handled");
}
}
}
77 changes: 77 additions & 0 deletions src/core/layoutmanager/GridLayoutManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { LayoutProvider } from "./../dependencies/LayoutProvider";
import { WrapGridLayoutManager, Layout } from "./LayoutManager";
import { Dimension } from "../dependencies/LayoutProvider";

export class GridLayoutManager extends WrapGridLayoutManager {
private _maxSpan: number;
private _getSpan: (index: number) => number;
private _isGridHorizontal: boolean | undefined;
private _renderWindowSize: Dimension;
private _acceptableRelayoutDelta: number;
constructor(
layoutProvider: LayoutProvider,
renderWindowSize: Dimension,
getSpan: (index: number) => number,
maxSpan: number,
acceptableRelayoutDelta: number,
isHorizontal?: boolean,
cachedLayouts?: Layout[],
) {
super(layoutProvider, renderWindowSize, isHorizontal, cachedLayouts);
this._getSpan = getSpan;
this._isGridHorizontal = isHorizontal;
this._renderWindowSize = renderWindowSize;
if (acceptableRelayoutDelta < 0) {
throw new Error("acceptableRelayoutDelta cannot be less than 0");
} else {
this._acceptableRelayoutDelta = acceptableRelayoutDelta;
}
if (maxSpan <= 0) {
throw new Error("Max Column Span cannot be less than or equal to 0");
} else {
this._maxSpan = maxSpan;
}
}

public overrideLayout(index: number, dim: Dimension): boolean {
// we are doing this because - when we provide decimal dimensions for a
// certain cell - the onlayout returns a different dimension in certain high end devices.
// This causes the layouting to behave weirdly as the new dimension might not adhere to the spans and the cells arrange themselves differently
// So, whenever we have layouts for a certain index, we explicitly override the dimension to those very layout values
// and call super so as to set the overridden flag as true
const layout = this.getLayouts()[index];
const heightDiff = Math.abs(dim.height - layout.height);
const widthDiff = Math.abs(dim.width - layout.width);
if (layout) {
if (this._isGridHorizontal) {
if (heightDiff < this._acceptableRelayoutDelta) {
if (widthDiff === 0) {
return false;
}
dim.height = layout.height;
}
} else {
if (widthDiff < this._acceptableRelayoutDelta) {
if (heightDiff === 0) {
return false;
}
dim.width = layout.width;
}
}
}
return super.overrideLayout(index, dim);
}

public getStyleOverridesForIndex(index: number): object | undefined {
const columnSpanForIndex = this._getSpan(index);
return this._isGridHorizontal
? {
height:
(this._renderWindowSize.height / this._maxSpan) * columnSpanForIndex,
}
: {
width:
(this._renderWindowSize.width / this._maxSpan) * columnSpanForIndex,
};
}
}
3 changes: 2 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import ContextProvider from "./core/dependencies/ContextProvider";
import DataProvider, { BaseDataProvider } from "./core/dependencies/DataProvider";
import { BaseLayoutProvider, Dimension, LayoutProvider } from "./core/dependencies/LayoutProvider";
import { GridLayoutProvider, GridLayoutManager } from "recyclerlistview-gridlayoutprovider";
import { GridLayoutProvider } from "./core/dependencies/GridLayoutProvider";
import RecyclerListView, { OnRecreateParams } from "./core/RecyclerListView";
import BaseScrollView from "./core/scrollcomponent/BaseScrollView";
import { BaseItemAnimator } from "./core/ItemAnimator";
import { AutoScroll } from "./utils/AutoScroll";
import { Layout, LayoutManager, Point, WrapGridLayoutManager } from "./core/layoutmanager/LayoutManager";
import { GridLayoutManager } from "./core/layoutmanager/GridLayoutManager";
import ProgressiveListView from "./core/ProgressiveListView";
import { DebugHandlers } from "./core/devutils/debughandlers/DebugHandlers";
import { ComponentCompat } from "./utils/ComponentCompat";
Expand Down