Commit 96d19d3b by nguyenquangtung004

TODO: Đã fix thành công SafeAreaView không bị khoảng trắng trên màn hình home

parent 61052ad2
import React from 'react';
import {
SafeAreaView,
StyleSheet,
Text,
TouchableOpacity,
......
......@@ -49,7 +49,6 @@ const styles = StyleSheet.create({
container: {
flexDirection: "row",
marginHorizontal: 15,
marginTop: 15,
maxHeight: 40,
},
size_box:{
......
......@@ -10,6 +10,8 @@ import {
Keyboard,
SafeAreaView,
Image,
StatusBar, // FEATURE: Import StatusBar để control status bar
Platform, // FEATURE: Check platform iOS/Android
} from "react-native";
import HeaderCus from "../home/header";
import R from "../../assets/R";
......@@ -18,6 +20,7 @@ import ItemGrid from "./item";
import styles from "./style";
import { useNavigation } from "@react-navigation/native";
import * as SCREENNAME from "../../routers/ScreenNames";
const HomeView = (props) => {
const {
menuDataStudy,
......@@ -29,119 +32,143 @@ const HomeView = (props) => {
onMenuItemPress,
onSearchChange,
} = props;
// OPTIMIZE: Move icon reference outside render để tránh re-create
const ArrowRightIcon = R.images.icArrowRight;
const navigate = useNavigation();
const renderMenuItem = ({ item }) => {
return <ItemGrid item={item} onPress={() => onMenuItemPress(item)} />;
};
return (
<TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
<SafeAreaView style={{ flex: 1 }}>
// PERFORMANCE: Memoized render function
const renderMenuItem = React.useCallback(({ item }) => {
return <ItemGrid item={item} onPress={() => onMenuItemPress(item)} />;
}, [onMenuItemPress]);
<View style={styles.container_body}>
<ImageBackground
source={R.images.igBackgroundSlider}
style={styles.background_header}
>
<HeaderCus
pathLogo={R.images.igLogo}
width={75}
height={36}
textInput={R.colors.white}
backgroundInput={R.colors.backgroundInputSearch}
textLabel={I18n.t("Search")}
textColorLabel={R.colors.white}
// UI/UX: Profile card component với null safety
const renderProfileCard = () => (
<View style={styles.profile_card}>
<View style={styles.profile_left}>
{/* FEATURE: Avatar với fallback */}
<View style={styles.avatar}>
{userProfile?.avatar ? (
<Image
source={{ uri: userProfile.avatar }}
style={styles.avatar_image}
resizeMode="cover"
/>
) : (
<View style={styles.avatar_placeholder}>
<Text style={styles.avatar_text}>
{userProfile?.name?.charAt(0) || "U"}
</Text>
</View>
)}
</View>
{/* FEATURE: User information với null safety */}
<View style={styles.information}>
<Text
style={styles.text_card_info}
numberOfLines={1}
ellipsizeMode="tail"
>
{userProfile?.name || "Không có tên"}
</Text>
<Text
style={styles.text_card_info}
numberOfLines={1}
ellipsizeMode="tail"
>
{userProfile?.phone || "Không có SĐT"}
</Text>
</View>
</View>
<View style={styles.profile_card}>
<View style={styles.profile_left}>
<View style={styles.avatar}>
{userProfile?.avatar ? (
<Image
source={{ uri: userProfile.avatar }}
style={styles.avatar_image}
resizeMode="cover"
/>
) : (
<View style={styles.avatar_placeholder}>
<Text style={styles.avatar_text}>
{userProfile?.name?.charAt(0)}
</Text>
</View>
)}
</View>
<View style={styles.information}>
<Text
style={styles.text_card_info}
numberOfLines={1}
ellipsizeMode="tail"
>
{userProfile?.name}
</Text>
<Text
style={styles.text_card_info}
numberOfLines={1}
ellipsizeMode="tail"
>
{userProfile?.phone}
</Text>
</View>
</View>
{/* FEATURE: Profile button với better UX */}
<TouchableOpacity
style={styles.profile_btn}
onPress={() => navigate.navigate(SCREENNAME.PROFILE)}
activeOpacity={0.7}
>
<Text style={styles.btn_text}>H s cá nhân</Text>
<ArrowRightIcon
width={5}
height={10}
fill={R.colors.txtMain}
style={styles.icon}
/>
</TouchableOpacity>
</View>
);
<TouchableOpacity style={styles.profile_btn} onPress={() => navigate.navigate(SCREENNAME.PROFILE)}>
<Text style={styles.btn_text}>H sơ cá nhân</Text>
<ArrowRightIcon
width={5}
height={10}
fill={R.colors.txtMain}
style={styles.icon}
/>
</TouchableOpacity>
</View>
</ImageBackground>
<ScrollView
showsVerticalScrollIndicator={false}
style={styles.scroll}>
<View style={styles.menu_container}>
<Text style={styles.menu_title}>Hc tp</Text>
<FlatList
data={menuDataStudy}
renderItem={renderMenuItem}
numColumns={3}
keyExtractor={(item) => item.id.toString()}
scrollEnabled={false}
columnWrapperStyle={styles.row}
/>
</View>
<View style={styles.menu_container}>
<Text style={styles.menu_title}>Cá nhân</Text>
<FlatList
data={menuDataIndividual}
renderItem={renderMenuItem}
numColumns={3}
keyExtractor={(item) => item.id.toString()}
scrollEnabled={false}
columnWrapperStyle={styles.row}
/>
</View>
<View style={styles.menu_container}>
<Text style={styles.menu_title}>Dch v trc tuyến</Text>
<FlatList
data={menuDataOnlineSer}
renderItem={renderMenuItem}
numColumns={3}
keyExtractor={(item) => item.id.toString()}
scrollEnabled={false}
columnWrapperStyle={styles.row}
// FUNCTIONALITY: Render menu section với reusable logic
const renderMenuSection = (title, data) => (
<View style={styles.menu_container}>
<Text style={styles.menu_title}>{title}</Text>
<FlatList
data={data}
renderItem={renderMenuItem}
numColumns={3}
keyExtractor={(item) => item.id.toString()}
scrollEnabled={false}
columnWrapperStyle={styles.row}
removeClippedSubviews={true} // PERFORMANCE: Memory optimization
maxToRenderPerBatch={9} // PERFORMANCE: Render batch size
windowSize={10} // PERFORMANCE: Window size optimization
/>
</View>
);
return (
<>
{/* FIXME: StatusBar configuration để loại bỏ white space */}
<StatusBar
barStyle="light-content" // Text trắng trên dark background
backgroundColor="transparent" // Background trong suốt
translucent={true} // Cho phép content extend lên status bar
/>
<TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
{/* FIXME: Dùng View với manual padding thay SafeAreaView */}
<View style={[
{ flex: 1 },
{ paddingTop: Platform.OS === 'ios' ? 0 : StatusBar.currentHeight }
]}>
<View style={styles.container_body}>
<ImageBackground
source={R.images.igBackgroundSlider}
style={[styles.background_header, {
// FIXME: Extend background để cover status bar area
paddingTop: Platform.OS === 'ios' ? 50 : (StatusBar.currentHeight || 0) + 10,
}]}
>
<HeaderCus
pathLogo={R.images.igLogo}
width={75}
height={36}
textInput={R.colors.white}
backgroundInput={R.colors.backgroundInputSearch}
textLabel={I18n.t("Search")}
textColorLabel={R.colors.white}
/>
</View>
</ScrollView>
{renderProfileCard()}
</ImageBackground>
<ScrollView
showsVerticalScrollIndicator={false}
style={styles.scroll}
bounces={false} // OPTIMIZE: Tắt bounce trên iOS
overScrollMode="never" // OPTIMIZE: Tắt over scroll trên Android
>
{/* FUNCTIONALITY: Render các menu sections */}
{renderMenuSection("Học tập", menuDataStudy)}
{renderMenuSection("Cá nhân", menuDataIndividual)}
{renderMenuSection("Dịch vụ trực tuyến", menuDataOnlineSer)}
</ScrollView>
</View>
</View>
</SafeAreaView>
</TouchableWithoutFeedback>
</TouchableWithoutFeedback>
</>
);
};
export default HomeView;
export default HomeView;
\ No newline at end of file
......@@ -18,7 +18,7 @@ const ProfileView = (props) => {
const { phone, setPhone, cmnd, setCmnd, bank, setBank } = props;
const IconCamera = R.images.icCamera;
return (
<SafeAreaView style={{ flex: 1, backgroundColor: R.colors.white }}>
<View style={{ flex: 1}}>
<Header title={"Hồ sơ cá nhân"} isBack />
<ScrollView showsVerticalScrollIndicator={false} style={{ flex: 1 }}>
<View style={styles.container}>
......@@ -335,7 +335,7 @@ const ProfileView = (props) => {
</View>
</View>
</ScrollView>
</SafeAreaView>
</View>
);
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment