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

Refactor Dimension Handling and Optimize Type Definitions #160

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
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
9 changes: 8 additions & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
declare module 'react-native-responsive-screen' {
import { Component } from 'react';

// Define props and state types if applicable
interface ScreenClassComponent<Props = {}, State = {}> extends Component<Props, State> {}

export function widthPercentageToDP(widthPercent: string | number): number;
export function heightPercentageToDP(heightPercent: string | number): number;
export function listenOrientationChange(screenClassComponent: Component<any, any>): void;

// Use a more specific type for the screenClassComponent parameter
export function listenOrientationChange(screenClassComponent: ScreenClassComponent): void;

// Indicate that this function does not take any parameters
export function removeOrientationListener(): void;
}
68 changes: 26 additions & 42 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,77 +1,61 @@
// packages
import { Dimensions, PixelRatio } from 'react-native';

// Retrieve initial screen's width
let screenWidth = Dimensions.get('window').width;
// Retrieve initial screen dimensions
const { width: initialScreenWidth, height: initialScreenHeight } = Dimensions.get('window');

// Retrieve initial screen's height
let screenHeight = Dimensions.get('window').height;
// Cache screen dimensions
let screenWidth = initialScreenWidth;
let screenHeight = initialScreenHeight;

/**
* Converts provided width percentage to independent pixel (dp).
* @param {string} widthPercent The percentage of screen's width that UI element should cover
* along with the percentage symbol (%).
* @return {number} The calculated dp depending on current device's screen width.
* Converts provided percentage of screen width to independent pixel (dp).
* @param {string|number} widthPercent The percentage of screen width (e.g., '50%').
* @return {number} The calculated dp based on the current screen width.
*/
const widthPercentageToDP = widthPercent => {
// Parse string percentage input and convert it to number.
const widthPercentageToDP = (widthPercent) => {
const elemWidth = typeof widthPercent === "number" ? widthPercent : parseFloat(widthPercent);

// Use PixelRatio.roundToNearestPixel method in order to round the layout
// size (dp) to the nearest one that correspons to an integer number of pixels.
return PixelRatio.roundToNearestPixel(screenWidth * elemWidth / 100);
};

/**
* Converts provided height percentage to independent pixel (dp).
* @param {string} heightPercent The percentage of screen's height that UI element should cover
* along with the percentage symbol (%).
* @return {number} The calculated dp depending on current device's screen height.
* Converts provided percentage of screen height to independent pixel (dp).
* @param {string|number} heightPercent The percentage of screen height (e.g., '50%').
* @return {number} The calculated dp based on the current screen height.
*/
const heightPercentageToDP = heightPercent => {
// Parse string percentage input and convert it to number.
const heightPercentageToDP = (heightPercent) => {
const elemHeight = typeof heightPercent === "number" ? heightPercent : parseFloat(heightPercent);

// Use PixelRatio.roundToNearestPixel method in order to round the layout
// size (dp) to the nearest one that correspons to an integer number of pixels.
return PixelRatio.roundToNearestPixel(screenHeight * elemHeight / 100);
};

/**
* Event listener function that detects orientation change (every time it occurs) and triggers
* screen rerendering. It does that, by changing the state of the screen where the function is
* called. State changing occurs for a new state variable with the name 'orientation' that will
* always hold the current value of the orientation after the 1st orientation change.
* Invoke it inside the screen's constructor or in componentDidMount lifecycle method.
* @param {object} that Screen's class component this variable. The function needs it to
* invoke setState method and trigger screen rerender (this.setState()).
* Sets up an event listener for orientation changes and updates screen dimensions.
* @param {object} that The component instance to call setState on.
*/
const listenOrientationChange = that => {
Dimensions.addEventListener('change', newDimensions => {
// Retrieve and save new dimensions
screenWidth = newDimensions.window.width;
screenHeight = newDimensions.window.height;
const listenOrientationChange = (that) => {
const handleDimensionsChange = ({ window }) => {
screenWidth = window.width;
screenHeight = window.height;

// Trigger screen's rerender with a state update of the orientation variable
that.setState({
orientation: screenWidth < screenHeight ? 'portrait' : 'landscape'
});
});
};

Dimensions.addEventListener('change', handleDimensionsChange);
};

/**
* Wrapper function that removes orientation change listener and should be invoked in
* componentWillUnmount lifecycle method of every class component (UI screen) that
* listenOrientationChange function has been invoked. This should be done in order to
* avoid adding new listeners every time the same component is re-mounted.
* Removes the orientation change listener to prevent memory leaks.
* Should be called in componentWillUnmount.
*/
const removeOrientationListener = () => {
Dimensions.removeEventListener('change', () => {});
Dimensions.removeEventListener('change', handleDimensionsChange);
};

export {
widthPercentageToDP,
heightPercentageToDP,
listenOrientationChange,
removeOrientationListener
removeOrientationListener,
};