react-native-sop-docs/04-design-integration/icons-fonts.md

295 lines
6.4 KiB
Markdown

# Icons & Fonts
## App Icon & Splash Screen
### Generate App Icons
**Using IconKitchen or manually:**
1. **Android**: Place icons in `android/app/src/main/res/mipmap-*`
2. **iOS**: Use Xcode Asset Catalog in `ios/SaayamApp/Images.xcassets`
**Android Icon Sizes:**
- `mipmap-mdpi`: 48x48px
- `mipmap-hdpi`: 72x72px
- `mipmap-xhdpi`: 96x96px
- `mipmap-xxhdpi`: 144x144px
- `mipmap-xxxhdpi`: 192x192px
**iOS Icon Sizes:**
- iPhone: 60x60pt (120x120px, 180x180px)
- iPad: 76x76pt (152x152px, 228x228px)
- App Store: 1024x1024px
### Splash Screen Setup
**Install react-native-splash-screen:**
```bash
yarn add react-native-splash-screen
```
**Android Configuration:**
1. Create `android/app/src/main/res/drawable/launch_screen.xml`:
```xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/primary_color" />
<item
android:width="200dp"
android:height="200dp"
android:drawable="@mipmap/launch_icon"
android:gravity="center" />
</layer-list>
```
2. Update `android/app/src/main/res/values/styles.xml`:
```xml
<resources>
<style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
<item name="android:editTextBackground">@drawable/rn_edit_text_material</item>
</style>
<style name="SplashTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">@drawable/launch_screen</item>
</style>
</resources>
```
**iOS Configuration:**
1. Create LaunchScreen.storyboard in Xcode
2. Add your logo and configure constraints
## Custom Fonts
### Font Installation
**Add fonts to project:**
1. Create `src/assets/fonts/` directory
2. Add font files (.ttf, .otf)
3. Configure for each platform
**Android Configuration:**
1. Copy fonts to `android/app/src/main/assets/fonts/`
2. Use font family name in styles
**iOS Configuration:**
1. Add fonts to Xcode project
2. Update `ios/SaayamApp/Info.plist`:
```xml
<key>UIAppFonts</key>
<array>
<string>Montserrat-Regular.ttf</string>
<string>Montserrat-Bold.ttf</string>
<string>Montserrat-SemiBold.ttf</string>
</array>
```
### Font Helper
```typescript
// src/utils/fontHelper.ts
import {Platform} from 'react-native';
export const FontFamily = {
regular: Platform.select({
ios: 'Montserrat-Regular',
android: 'Montserrat-Regular',
}),
medium: Platform.select({
ios: 'Montserrat-Medium',
android: 'Montserrat-Medium',
}),
semiBold: Platform.select({
ios: 'Montserrat-SemiBold',
android: 'Montserrat-SemiBold',
}),
bold: Platform.select({
ios: 'Montserrat-Bold',
android: 'Montserrat-Bold',
}),
};
export const getFontFamily = (weight: 'regular' | 'medium' | 'semiBold' | 'bold' = 'regular'): string => {
return FontFamily[weight] || FontFamily.regular;
};
```
## Icon Font Generation
### Using IcoMoon
1. **Visit IcoMoon.io**
2. **Import SVG icons**
3. **Generate font**
4. **Download and integrate**
**IcoMoon Integration:**
```typescript
// src/config/iconFont.ts
import {createIconSetFromIcoMoon} from 'react-native-vector-icons/lib/create-icon-set-from-icomoon';
import icoMoonConfig from '../assets/fonts/selection.json';
export const CustomIcon = createIconSetFromIcoMoon(
icoMoonConfig,
'CustomIcons',
'CustomIcons.ttf'
);
```
### Custom Icon Component
```typescript
// src/components/common/CustomIcon/CustomIcon.tsx
import React from 'react';
import {createIconSetFromIcoMoon} from 'react-native-vector-icons/lib/create-icon-set-from-icomoon';
import icoMoonConfig from '@assets/fonts/selection.json';
const IconFont = createIconSetFromIcoMoon(
icoMoonConfig,
'SaayamIcons',
'SaayamIcons.ttf'
);
interface CustomIconProps {
name: string;
size?: number;
color?: string;
style?: any;
onPress?: () => void;
}
export const CustomIcon: React.FC<CustomIconProps> = ({
name,
size = 24,
color = '#000',
style,
onPress,
}) => {
return (
<IconFont
name={name}
size={size}
color={color}
style={style}
onPress={onPress}
/>
);
};
```
## Icon Library Setup
```typescript
// src/config/icons.ts
export const IconLibrary = {
// Navigation icons
home: 'home',
profile: 'user',
settings: 'settings',
back: 'arrow-left',
// Action icons
add: 'plus',
edit: 'edit',
delete: 'trash',
save: 'check',
cancel: 'x',
// Status icons
success: 'check-circle',
error: 'x-circle',
warning: 'alert-triangle',
info: 'info',
// Social icons
facebook: 'facebook',
google: 'google',
apple: 'apple',
// Feature icons
camera: 'camera',
gallery: 'image',
location: 'map-pin',
notification: 'bell',
search: 'search',
filter: 'filter',
share: 'share',
favorite: 'heart',
star: 'star',
};
export type IconName = keyof typeof IconLibrary;
```
## Dynamic Icon Loading
```typescript
// src/utils/iconLoader.ts
import {IconLibrary, IconName} from '@config/icons';
export class IconLoader {
private static loadedIcons: Set<string> = new Set();
static async preloadIcons(iconNames: IconName[]): Promise<void> {
const promises = iconNames.map(async (iconName) => {
if (!this.loadedIcons.has(iconName)) {
// Preload icon font glyphs
await this.loadIcon(iconName);
this.loadedIcons.add(iconName);
}
});
await Promise.all(promises);
}
private static async loadIcon(iconName: IconName): Promise<void> {
// Implementation depends on your icon font setup
return new Promise((resolve) => {
// Simulate icon loading
setTimeout(resolve, 10);
});
}
static isIconLoaded(iconName: IconName): boolean {
return this.loadedIcons.has(iconName);
}
}
```
## Font Size Scaling
```typescript
// src/utils/fontScaling.ts
import {Dimensions, PixelRatio} from 'react-native';
const {width: SCREEN_WIDTH} = Dimensions.get('window');
const BASE_WIDTH = 375; // iPhone 6/7/8 width
export const fontSizer = (size: number): number => {
const scale = SCREEN_WIDTH / BASE_WIDTH;
const newSize = size * scale;
// Ensure minimum readable size
const minSize = size * 0.8;
const maxSize = size * 1.2;
return Math.max(minSize, Math.min(maxSize, Math.round(PixelRatio.roundToNearestPixel(newSize))));
};
export const FontSizes = {
xs: fontSizer(10),
sm: fontSizer(12),
base: fontSizer(14),
lg: fontSizer(16),
xl: fontSizer(18),
'2xl': fontSizer(20),
'3xl': fontSizer(24),
'4xl': fontSizer(28),
'5xl': fontSizer(32),
};
```