forked from marudy/react-native-responsive-screen
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathindex.js
175 lines (154 loc) · 6.25 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
// packages
import { Dimensions, PixelRatio, Platform } from 'react-native';
import useResponsive from './useResponsiveScreen';
import { baseDevice, baseFontSize, breakpoints, maxFontScaleFactor } from './constants';
// Retrieve initial screen's width
let screenWidth = Dimensions.get('window').width;
// Retrieve initial screen's height
let screenHeight = Dimensions.get('window').height;
const base = isLandscape ? screenHeight : screenWidth;
/**
* Determines if the platform is iOS.
* @type {boolean}
*/
const isIOS = Platform.OS === 'ios';
/**
* Determines if the platform is Android.
* @type {boolean}
*/
const isAndroid = Platform.OS === 'android';
/**
* Determines if the device is in landscape orientation.
* @type {boolean}
*/
const isLandscape = screenWidth > screenHeight;
/**
* Determines if the device is in portrait orientation.
* @type {boolean}
*/
const isPortrait = screenWidth < screenHeight;
/**
* 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.
*/
const widthPercentageToDP = widthPercent => {
// Parse string percentage input and convert it to number.
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.
*/
const heightPercentageToDP = heightPercent => {
// Parse string percentage input and convert it to number.
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()).
*/
const listenOrientationChange = that => {
Dimensions.addEventListener('change', newDimensions => {
// Retrieve and save new dimensions
screenWidth = newDimensions.window.width;
screenHeight = newDimensions.window.height;
// Trigger screen's rerender with a state update of the orientation variable
that.setState({
orientation: screenWidth < screenHeight ? 'portrait' : 'landscape'
});
});
};
/**
* 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.
*/
const removeOrientationListener = () => {
Dimensions.removeEventListener('change', () => {});
};
/**
* Converts provided width percentage to viewport-relative units (vw).
* @param {string} widthPercent The percentage of viewport's width that UI element should cover.
* @returns {number} The calculated vw value.
*/
const viewportWidthPercentage = widthPercent => {
const elemWidth = typeof widthPercent === 'number' ? widthPercent : parseFloat(widthPercent);
return Math.floor((screenWidth / 100) * elemWidth);
};
/**
* Converts provided height percentage to viewport-relative units (vh).
* @param {string} heightPercent The percentage of viewport's height that UI element should cover.
* @returns {number} The calculated vh value.
*/
const viewportHeightPercentage = heightPercent => {
const elemHeight = typeof heightPercent === 'number' ? heightPercent : parseFloat(heightPercent);
return Math.floor((screenHeight / 100) * elemHeight);
};
/**
* Converts provided font size to rem units.
* @param {string} size The font size in pixels.
* @returns {number} The calculated rem value.
*/
const remUnit = size => {
const elemSize = typeof size === 'number' ? size : parseFloat(size);
const multiplier = Math.max(screenHeight, screenWidth) < baseDevice.height ? 0.9 : 1;
return Math.floor((base / baseDevice.width) * elemSize * multiplier);
};
/**
* Converts provided font size to responsive font units (rf).
* @param {string} size The font size in pixels.
* @returns {number} The calculated rf value.
*/
const responsiveFont = size => {
const elemSize = typeof size === 'number' ? size : parseFloat(size);
const scaledFontSize = Math.min(baseFontSize * maxFontScaleFactor, elemSize);
return scaledFontSize;
};
/**
* Gets the current breakpoint group based on the device width.
* @returns {string} The name of the current breakpoint group.
*/
const getBreakpointGroup = () => {
for (let group in breakpoints) {
if (screenWidth >= breakpoints[group][0] && screenWidth <= breakpoints[group][1]) {
return group;
}
}
};
/**
* The current breakpoint group based on the device width.
* @type {string}
*/
const breakpointGroup = getBreakpointGroup();
export {
isLandscape,
isPortrait,
isAndroid,
isIOS,
breakpointGroup,
widthPercentageToDP,
heightPercentageToDP,
listenOrientationChange,
removeOrientationListener,
viewportWidthPercentage,
viewportHeightPercentage,
remUnit,
responsiveFont,
useResponsive,
};