1import { 2 Image, 3 ImageContentFit, 4 ImageContentPosition, 5 ImageContentPositionString, 6} from 'expo-image'; 7import { ScrollView, StyleSheet, Text, View } from 'react-native'; 8 9import HeadingText from '../../components/HeadingText'; 10import { Colors } from '../../constants'; 11 12const CONTENT_FITS: ImageContentFit[] = ['cover', 'contain', 'fill', 'none', 'scale-down']; 13 14const CONTENT_POSITIONS: ImageContentPositionString[] = [ 15 'center', 16 'top', 17 'right', 18 'bottom', 19 'left', 20 'top center', 21 'top right', 22 'top left', 23 'right center', 24 'right top', 25 'right bottom', 26 'bottom center', 27 'bottom right', 28 'bottom left', 29 'left center', 30 'left top', 31 'left bottom', 32]; 33 34type ContentFitExample = { 35 size: [number, number]; 36 position?: ImageContentPosition; 37}; 38 39const EXAMPLES: ContentFitExample[] = [ 40 { 41 size: [1500, 1000], 42 }, 43 { 44 size: [300, 200], 45 }, 46 { 47 size: [200, 300], 48 }, 49 { 50 size: [240, 160], 51 position: { top: 10, left: 20 }, 52 }, 53 { 54 size: [240, 160], 55 position: { top: 0, right: 0 }, 56 }, 57 { 58 size: [240, 160], 59 position: { bottom: 5, left: 10 }, 60 }, 61 { 62 size: [240, 160], 63 position: { bottom: '10%', right: '10%' }, 64 }, 65 { 66 size: [240, 160], 67 position: { left: '15%' }, 68 }, 69 { 70 size: [240, 160], 71 position: { top: '-50%', right: '10%' }, 72 }, 73]; 74 75function sourceWithSize(size: [number, number]): string { 76 return `https://picsum.photos/seed/138/${size[0]}/${size[1]}`; 77} 78 79function renderExample(contentFit: ImageContentFit, example: ContentFitExample, index: number) { 80 const sizeText = example.size.join(' x '); 81 const positionText = example.position 82 ? JSON.stringify(example.position).replaceAll(/[{}"]/g, '').replaceAll(/[:,]/g, ' ') 83 : null; 84 85 return ( 86 <View key={index} style={styles.imageContainer}> 87 <Image 88 style={styles.image} 89 source={{ uri: sourceWithSize(example.size) }} 90 contentFit={contentFit} 91 contentPosition={example.position} 92 /> 93 <Text style={styles.description}>{[sizeText, positionText].filter(Boolean).join('\n')}</Text> 94 </View> 95 ); 96} 97 98function renderContentFitExamples(contentFit: ImageContentFit, index: number) { 99 return ( 100 <View key={index} style={styles.contentFitExamples}> 101 <HeadingText style={styles.headingText}>{`Content fit: "${contentFit}"`}</HeadingText> 102 <ScrollView style={styles.examplesScrollView} horizontal indicatorStyle="black"> 103 {EXAMPLES.map((example, index) => renderExample(contentFit, example, index))} 104 </ScrollView> 105 </View> 106 ); 107} 108 109function renderContentPositionExample(contentPosition: ImageContentPositionString, index: number) { 110 const example: ContentFitExample = { 111 size: [100, 100], 112 position: contentPosition, 113 }; 114 return renderExample('none', example, index); 115} 116 117export default function ImageContentFitScreen() { 118 return ( 119 <ScrollView style={styles.container}> 120 <HeadingText style={styles.headingText}>Full-size image</HeadingText> 121 <Image style={styles.fullImageExample} source={{ uri: sourceWithSize([1500, 1000]) }} /> 122 <Text style={styles.description}>1500 x 1000</Text> 123 124 {CONTENT_FITS.map(renderContentFitExamples)} 125 126 <View style={styles.contentFitExamples}> 127 <HeadingText style={styles.headingText}>Content positions (strings)</HeadingText> 128 <ScrollView style={styles.examplesScrollView} horizontal indicatorStyle="black"> 129 {CONTENT_POSITIONS.map(renderContentPositionExample)} 130 </ScrollView> 131 </View> 132 </ScrollView> 133 ); 134} 135 136const styles = StyleSheet.create({ 137 container: { 138 flex: 1, 139 }, 140 contentFitExamples: { 141 backgroundColor: Colors.greyBackground, 142 borderTopColor: Colors.border, 143 borderTopWidth: StyleSheet.hairlineWidth, 144 }, 145 fullImageExample: { 146 width: 300, 147 height: 200, 148 margin: 10, 149 alignSelf: 'center', 150 }, 151 headingText: { 152 marginTop: -6, 153 marginBottom: 6, 154 marginHorizontal: 10, 155 }, 156 examplesScrollView: { 157 padding: 10, 158 }, 159 imageContainer: { 160 marginRight: 15, 161 alignItems: 'center', 162 }, 163 image: { 164 width: 100, 165 height: 100, 166 borderColor: Colors.tintColor, 167 borderStyle: 'solid', 168 borderWidth: 1, 169 }, 170 description: { 171 padding: 5, 172 fontSize: 11, 173 textAlign: 'center', 174 }, 175}); 176