References

Platform-Specific Patterns

Platform.select, iOS/Android differences, platform APIs

Core Patterns

  • When to Read This
  • Platform Detection
  • Platform-Specific Files
  • Common Differences

When to Read This

  • Writing platform-specific code
  • Handling iOS vs Android differences
  • Using platform-specific APIs
  • Conditional styling per platform

Platform Detection

✅ Platform.select

import { Platform } from "react-native";

const styles = StyleSheet.create({
  container: {
    ...Platform.select({
      ios: {
        shadowColor: "#000",
        shadowOffset: { width: 0, height: 2 },
        shadowOpacity: 0.25,
        shadowRadius: 3.84,
      },
      android: {
        elevation: 5,
      },
    }),
  },
});

✅ Platform.OS

if (Platform.OS === "ios") {
  // iOS code
} else if (Platform.OS === "android") {
  // Android code
}

✅ Platform.Version

if (Platform.Version >= 23) {
  // Android API 23+ (Marshmallow)
}

Platform-Specific Files

✅ File Extensions

Button.ios.tsx  // iOS-specific
Button.android.tsx  // Android-specific
Button.tsx  // Fallback
// Import resolves automatically per platform
import Button from "./Button";

Common Differences

✅ Status Bar

import { StatusBar } from 'react-native';

<StatusBar
  barStyle={Platform.OS === 'ios' ? 'dark-content' : 'light-content'}
  backgroundColor={Platform.OS === 'android' ? '#000' : undefined}
/>

✅ Safe Area

import { SafeAreaView } from 'react-native-safe-area-context';

<SafeAreaView style={{ flex: 1 }}>
  {/* respects notch (iOS) and status bar (Android) */}
</SafeAreaView>

✅ Shadow Styles

// ❌ WRONG: iOS shadow on Android
<View style={{ shadowColor: '#000', shadowOpacity: 0.3 }} />

// ✅ CORRECT: Platform-specific shadow
<View
  style={{
    ...Platform.select({
      ios: {
        shadowColor: '#000',
        shadowOffset: { width: 0, height: 2 },
        shadowOpacity: 0.3,
        shadowRadius: 4,
      },
      android: {
        elevation: 4,
      },
    }),
  }}
/>

Platform APIs

✅ Keyboard Handling

import { KeyboardAvoidingView, Platform } from 'react-native';

<KeyboardAvoidingView
  behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
  style={{ flex: 1 }}
>
  {/* content */}
</KeyboardAvoidingView>

✅ ActionSheet (iOS) vs Menu (Android)

if (Platform.OS === "ios") {
  ActionSheetIOS.showActionSheetWithOptions(
    {
      options: ["Cancel", "Delete"],
      destructiveButtonIndex: 1,
      cancelButtonIndex: 0,
    },
    (buttonIndex) => {
      // handle
    },
  );
} else {
  // Use Android menu or custom component
}

References