295 lines
6.4 KiB
Markdown
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/MyApp/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/MyApp/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,
|
|
'MyAppIcons',
|
|
'MyAppIcons.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),
|
|
};
|
|
``` |