Add banner to the Home screen
This commit is contained in:
BIN
assets/images/banner01PengajuanPaspor.png
Normal file
BIN
assets/images/banner01PengajuanPaspor.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.4 MiB |
BIN
assets/images/banner02Panduan.png
Normal file
BIN
assets/images/banner02Panduan.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 803 KiB |
BIN
assets/images/banner03EazyPassport.png
Normal file
BIN
assets/images/banner03EazyPassport.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.3 MiB |
@ -8,6 +8,7 @@ import {
|
|||||||
Animated,
|
Animated,
|
||||||
Dimensions,
|
Dimensions,
|
||||||
Pressable,
|
Pressable,
|
||||||
|
Image,
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import Colors from '../../../assets/styles/Colors';
|
import Colors from '../../../assets/styles/Colors';
|
||||||
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
|
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||||
@ -27,109 +28,131 @@ type HomeScreenNavigationProp = NativeStackNavigationProp<
|
|||||||
'Home'
|
'Home'
|
||||||
>;
|
>;
|
||||||
|
|
||||||
const {width} = Dimensions.get('window');
|
|
||||||
const ITEM_WIDTH = width * 0.8;
|
|
||||||
const ITEM_SPACING = (width - ITEM_WIDTH) / 2;
|
|
||||||
const FIRST_ITEM_SPACING = 16;
|
|
||||||
|
|
||||||
const data = [1, 2, 3, 4];
|
|
||||||
|
|
||||||
const ItemSeparator = () => <View style={styles.flatllistGap} />;
|
const ItemSeparator = () => <View style={styles.flatllistGap} />;
|
||||||
|
|
||||||
type RenderContentProps = {
|
type RenderContentProps = {
|
||||||
showDialog: () => void;
|
showDialog: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const RenderContent = ({showDialog}: RenderContentProps) => {
|
const RenderBanner = () => {
|
||||||
const navigation = useNavigation<HomeScreenNavigationProp>();
|
const {width} = Dimensions.get('window');
|
||||||
|
const ITEM_WIDTH = width * 0.8;
|
||||||
|
const ITEM_SPACING = (width - ITEM_WIDTH) / 2;
|
||||||
|
const FIRST_ITEM_SPACING = 16;
|
||||||
const scrollX = useRef(new Animated.Value(0)).current;
|
const scrollX = useRef(new Animated.Value(0)).current;
|
||||||
|
const data = [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
image: require('../../../assets/images/banner01PengajuanPaspor.png'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
image: require('../../../assets/images/banner02Panduan.png'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '3',
|
||||||
|
image: require('../../../assets/images/banner03EazyPassport.png'),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<View style={styles.topContainer}>
|
<Animated.FlatList
|
||||||
<Animated.FlatList
|
data={data}
|
||||||
data={data}
|
keyExtractor={item => item.toString()}
|
||||||
keyExtractor={item => item.toString()}
|
horizontal
|
||||||
horizontal
|
showsHorizontalScrollIndicator={false}
|
||||||
showsHorizontalScrollIndicator={false}
|
snapToInterval={ITEM_WIDTH}
|
||||||
snapToInterval={ITEM_WIDTH}
|
decelerationRate="fast"
|
||||||
decelerationRate="fast"
|
bounces={false}
|
||||||
bounces={false}
|
ListHeaderComponent={<View style={{width: FIRST_ITEM_SPACING}} />}
|
||||||
ListHeaderComponent={<View style={{width: FIRST_ITEM_SPACING}} />}
|
ListFooterComponent={<View style={{width: ITEM_SPACING}} />}
|
||||||
ListFooterComponent={<View style={{width: ITEM_SPACING}} />}
|
onScroll={Animated.event(
|
||||||
onScroll={Animated.event(
|
[{nativeEvent: {contentOffset: {x: scrollX}}}],
|
||||||
[{nativeEvent: {contentOffset: {x: scrollX}}}],
|
{useNativeDriver: true},
|
||||||
{useNativeDriver: true},
|
)}
|
||||||
)}
|
scrollEventThrottle={16}
|
||||||
scrollEventThrottle={16}
|
renderItem={({item, index}) => {
|
||||||
renderItem={({index}) => {
|
const inputRange = [
|
||||||
const inputRange = [
|
(index - 1) * ITEM_WIDTH,
|
||||||
(index - 1) * ITEM_WIDTH,
|
index * ITEM_WIDTH,
|
||||||
index * ITEM_WIDTH,
|
(index + 1) * ITEM_WIDTH,
|
||||||
(index + 1) * ITEM_WIDTH,
|
];
|
||||||
];
|
|
||||||
|
|
||||||
const scale = scrollX.interpolate({
|
const scale = scrollX.interpolate({
|
||||||
inputRange,
|
inputRange,
|
||||||
outputRange: [0.875, 1, 0.875],
|
outputRange: [0.875, 1, 0.875],
|
||||||
extrapolate: 'clamp',
|
extrapolate: 'clamp',
|
||||||
});
|
});
|
||||||
|
|
||||||
const opacity = scrollX.interpolate({
|
const opacity = scrollX.interpolate({
|
||||||
inputRange,
|
inputRange,
|
||||||
outputRange: [0.5, 1, 0.5],
|
outputRange: [0.5, 1, 0.5],
|
||||||
extrapolate: 'clamp',
|
extrapolate: 'clamp',
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Animated.View
|
<Animated.View
|
||||||
style={[
|
style={[
|
||||||
styles.itemContainer,
|
styles.itemContainer,
|
||||||
{
|
{
|
||||||
transform: [{scale}],
|
transform: [{scale}],
|
||||||
opacity,
|
opacity,
|
||||||
},
|
},
|
||||||
]}>
|
]}>
|
||||||
<View style={styles.item} />
|
<Image
|
||||||
</Animated.View>
|
source={item.image}
|
||||||
);
|
style={styles.item}
|
||||||
}}
|
resizeMode="cover"
|
||||||
/>
|
|
||||||
<View style={styles.indicatorContainer}>
|
|
||||||
{data.map((_, i) => {
|
|
||||||
const inputRange = [
|
|
||||||
(i - 1) * ITEM_WIDTH,
|
|
||||||
i * ITEM_WIDTH,
|
|
||||||
(i + 1) * ITEM_WIDTH,
|
|
||||||
];
|
|
||||||
|
|
||||||
const dotOpacity = scrollX.interpolate({
|
|
||||||
inputRange,
|
|
||||||
outputRange: [0.3, 1, 0.3],
|
|
||||||
extrapolate: 'clamp',
|
|
||||||
});
|
|
||||||
|
|
||||||
const dotScale = scrollX.interpolate({
|
|
||||||
inputRange,
|
|
||||||
outputRange: [0.8, 1.2, 0.8],
|
|
||||||
extrapolate: 'clamp',
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Animated.View
|
|
||||||
key={i}
|
|
||||||
style={[
|
|
||||||
styles.indicatorInactive,
|
|
||||||
{
|
|
||||||
opacity: dotOpacity,
|
|
||||||
transform: [{scale: dotScale}],
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
/>
|
/>
|
||||||
);
|
</Animated.View>
|
||||||
})}
|
);
|
||||||
</View>
|
}}
|
||||||
|
/>
|
||||||
|
<View style={styles.indicatorContainer}>
|
||||||
|
{data.map((_, i) => {
|
||||||
|
const inputRange = [
|
||||||
|
(i - 1) * ITEM_WIDTH,
|
||||||
|
i * ITEM_WIDTH,
|
||||||
|
(i + 1) * ITEM_WIDTH,
|
||||||
|
];
|
||||||
|
|
||||||
|
const dotOpacity = scrollX.interpolate({
|
||||||
|
inputRange,
|
||||||
|
outputRange: [0.3, 1, 0.3],
|
||||||
|
extrapolate: 'clamp',
|
||||||
|
});
|
||||||
|
|
||||||
|
const dotScale = scrollX.interpolate({
|
||||||
|
inputRange,
|
||||||
|
outputRange: [0.8, 1.2, 0.8],
|
||||||
|
extrapolate: 'clamp',
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Animated.View
|
||||||
|
key={i}
|
||||||
|
style={[
|
||||||
|
styles.indicatorInactive,
|
||||||
|
{
|
||||||
|
opacity: dotOpacity,
|
||||||
|
transform: [{scale: dotScale}],
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</View>
|
</View>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const RenderContent = ({showDialog}: RenderContentProps) => {
|
||||||
|
const navigation = useNavigation<HomeScreenNavigationProp>();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<View style={styles.topContainer}>{RenderBanner()}</View>
|
||||||
<View style={styles.serviceContainer}>
|
<View style={styles.serviceContainer}>
|
||||||
<Text style={styles.serviceText}>Layanan</Text>
|
<Text style={styles.serviceText}>Layanan</Text>
|
||||||
<View style={styles.serviceOptionWrapper}>
|
<View style={styles.serviceOptionWrapper}>
|
||||||
@ -229,7 +252,7 @@ const RenderContent = ({showDialog}: RenderContentProps) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type HomeScreenProps = {
|
type HomeScreenProps = {
|
||||||
showDialog: () => void;
|
readonly showDialog: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
function HomeScreen({showDialog}: HomeScreenProps) {
|
function HomeScreen({showDialog}: HomeScreenProps) {
|
||||||
|
Reference in New Issue
Block a user