blog bg

July 04, 2024

Media Query in React Native with Dimension API and useWindowDimensions Hook

Share what you learn in this blog to prepare for your interview, create your forever-free profile now, and explore how to monetize your valuable knowledge.

 

In this post, we will explore how to implement media queries in React Native using the Dimension API. We will continue from my last blog post, and you can get the source code here. Let's break down the API and its usage.

 

Breaking Down the API

The Dimension API provides a method called get, which takes a window or screen argument. On iOS, there is no difference between the two. On Android, screen represents the entire available width and height including the status bar, whereas window excludes the status bar.

 

The object returned from the get method gives us access to properties such as width, height, scale, and fontScale.

const deviceWidth = Dimensions.get("window").width;
const deviceHeight = Dimensions.get("window").height;
const deviceScale = Dimensions.get("window").scale;
const deviceFontScale = Dimensions.get("window").fontScale;

 

Implementing in the NumberContainer Component

In the /components/Game/NumberContainer.tsx file, we dynamically set the padding and margin of the container style based on a screen width of 380. We also adjust the font size of the number text similarly.

const deviceWidth = Dimensions.get("window").width;
const styles = StyleSheet.create({
 container: {
   padding: deviceWidth < 380 ? 12 : 24,
   margin: deviceWidth < 380 ? 12 : 24,
   borderWidth: 4,
   borderRadius: 8,
   borderColor: Colors.accent500,
   alignItems: "center",
   justifyContent: "center",
 },
 numberText: {
   color: Colors.accent500,
   fontSize: deviceWidth < 380 ? 28 : 36,
   fontFamily: "open-sans-bold",
 },
});

 

Implementing in the Card Component

In the /components/Ui/Card.tsx file, we adjust the marginTop property based on the device width, providing a responsive design for different screen sizes.

const deviceWidth = Dimensions.get("window").width;
const styles = StyleSheet.create({
 card: {
   padding: 16,
   marginTop: deviceWidth < 380 ? 18 : 36,
   marginHorizontal: 24,
   borderRadius: 8,
   backgroundColor: Colors.primary800,
   justifyContent: "center", // align vertically
   alignItems: "center", // Align horizontally
   elevation: 4,
   shadowColor: "black",
   shadowOffset: { width: 0, height: 2 },
   shadowRadius: 6,
   shadowOpacity: 0.25,
 },
});

 

Implementing in the GameOverScreen Component

In the GameOverScreen.tsx file, we adjust the styles dynamically based on the device width, ensuring the layout adapts to different screen sizes.

 

const deviceWidth = Dimensions.get("window").width;
const styles = StyleSheet.create({
 screenContainer: {
   flex: 1,
   padding: 24,
   justifyContent: "center",
   alignItems: "center",
 },
 imageContainer: {
   width: deviceWidth < 380 ? 150 : 300,
   height: deviceWidth < 380 ? 150 : 300,
   borderRadius: deviceWidth < 380 ? 75 : 150,
   borderWidth: 3,
   color: Colors.primary800,
   overflow: "hidden",
   margin: 36,
 },
 image: {
   width: "100%",
   height: "100%",
 },
 summaryText: {
   fontFamily: "open-sans",
   fontSize: 24,
   textAlign: "center",
   marginBottom: 24,
 },
 highlight: {
   fontFamily: "open-sans-bold",
   color: Colors.primary500,
 },
});

 

Handling Change of Orientation

The styles can break when you change orientation to landscape. To address this, we can use the height from the Dimension API to target it. However, the Dimension API is not reactive, meaning the styles will not react to orientation changes because it only runs once when the file is parsed. To solve this, React Native provides a hook useWindowDimensions which we can call within the component itself. With this hook, we can get the device's width and height dynamically.

 

Implementing with useWindowDimensions Hook

In the StartGameScreen.tsx file, we use the useWindowDimensions hook to dynamically adjust the margin based on the device height.

 

const { width, height } = useWindowDimensions();
const marginTop = height < 380 ? 30 : 100;
// other code
<View style={[styles.screenContainer, { marginTop }]}>
// other code

 

Platform API

React Native also provides a Platform API to handle platform-specific code. We can use Platform.OS in ternary statements or Platform.select for conditional styles.

 

// Using Platform.OS
borderWidth: Platform.OS === "android" ? 2 : 0,
// Using Platform.select
borderWidth: Platform.select({ ios: 0, android: 2 }),

 

Platform-Specific Files

We can create platform-specific files by updating the compiler options in tsconfig.json.

{
 "extends": "expo/tsconfig.base",
 "compilerOptions": {
   "strict": true,
   "moduleSuffixes": [".ios", ".android", ".native", ""]
 }
}

 

Then, make a copy of the Title file and name it Title.android.tsx, and rename the other to Title.ios.tsx. You can then make platform-specific styles respectively.

 

This concludes our exploration of media queries in React Native using the Dimension API and the useWindowDimensions hook as well as platform specific styling with Platform API. This approach ensures that your application can adapt to different screen sizes and orientations seamlessly. Stay tuned for more updates and improvements in future posts!

Source Code: https://github.com/Intuneteq/guessing-game/tree/media-query

 

234 views

Please Login to create a Question