UX не отображается одинаково на iOS и ExpoIOS

Программируем под IOS
Ответить
Anonymous
 UX не отображается одинаково на iOS и Expo

Сообщение Anonymous »

Я использую React Native для разработки пользовательского интерфейса мобильного приложения. На следующем снимке экрана показано, как я хочу, чтобы мой экран выглядел при визуализации с помощью Expo на моем компьютере:
Просмотр с компьютера
Однако, когда я создаю IPA и просматриваю его на на моем iPad макет отличается:
вид с iPad
Появляются поля, а заголовок и оставшиеся минуты не соответствуют желаемому расположению. Вот код с моего экрана:

Код: Выделить всё

javascript
`
import React, { useState, useEffect } from 'react';
import { View, Text, StyleSheet, Image, TouchableOpacity, ScrollView, useWindowDimensions, Dimensions, Alert, Modal, Platform } from 'react-native';
import { theme } from '../utils/theme';
import FontAwesome5 from 'react-native-vector-icons/FontAwesome5';

const LaunchedClassScreen = ({ navigation, route }) => {
const { activities, targetFinishTime } = route.params;
const [currentActivityIndex, setCurrentActivityIndex] = useState(0);
const [startTime] = useState(Math.floor(Date.now() / 1000)); // Track the start time, do not reset
const [timer, setTimer] = useState(0);
const [totalDuration, setTotalDuration] = useState(0);
const [isCancelModalVisible, setIsCancelModalVisible] = useState(false);
const [estimatedFinishTime, setEstimatedFinishTime] = useState(0);
const window = useWindowDimensions();
const isLandscape = window.width > window.height;
const activity = activities[currentActivityIndex];
const nextActivity = currentActivityIndex < activities.length - 1 ? activities[currentActivityIndex + 1] : null;

useEffect(() => {
const totalActivitiesDuration = activities.reduce((acc, curr) => acc + curr.Duration, 0);
setTotalDuration(totalActivitiesDuration);

const timerId = setInterval(() => {
const currentTime = Math.floor(Date.now() / 1000);
const elapsedTime = currentTime - startTime;
const remainingActivitiesDuration = activities.slice(currentActivityIndex).reduce((acc, curr) => acc + curr.Duration, 0);
const newEFT = currentTime + remainingActivitiesDuration;

setEstimatedFinishTime(newEFT);
setTimer(elapsedTime);
}, 1000);

return () => clearInterval(timerId);
}, [activities, currentActivityIndex, startTime, totalDuration]);

const determineBarColor = () => estimatedFinishTime > targetFinishTime ? 'red' : 'green';
const determineTextColor = () => estimatedFinishTime > targetFinishTime ? 'red' : 'black';
const timeLeftText = () => {
const currentTime = Math.floor(Date.now() / 1000);
const timeLeftInSeconds = targetFinishTime - currentTime;
const minutesLeft = Math.floor(timeLeftInSeconds / 60);
return `${minutesLeft} mins left`;
};
const deltaTimeText = () => {
const deltaTime = estimatedFinishTime - targetFinishTime;
return deltaTime > 0 ? `${Math.ceil(deltaTime / 60)} mins over` : `${Math.abs(Math.floor(deltaTime / 60))} mins ahead`;
};
const formatTime = (totalSeconds) => {
if (totalSeconds < 0) return ""; // Avoid negative time display
const minutes = Math.floor(totalSeconds / 60);
const seconds = totalSeconds % 60;
if (minutes > 0 && seconds > 0) {
return `${minutes} mins ${seconds}`;
} else if (minutes > 0) {
return `${minutes} mins`;
} else if (seconds > 0) {
return `${seconds}`;
} else {
return "0 secs";
}
};
const goToNextActivity = () => {
if (currentActivityIndex < activities.length - 1) {
setCurrentActivityIndex(currentActivityIndex + 1);
}
};
const goToPreviousActivity = () => {
if (currentActivityIndex > 0) {
setCurrentActivityIndex(currentActivityIndex - 1);
}
};
const completeClass = () => {
navigation.navigate('Home');
};
const handleCancelClass = () => {
Alert.alert(
"Cancel Class",
"Are you sure you want to cancel the class?",
[
{ text: "No", style: "cancel" },
{
text: "Yes, cancel it",
style: "destructive",
onPress: () => {
setIsCancelModalVisible(false);
navigation.navigate('Home');
},
},
],
{ cancelable: true }
);
};

useEffect(() => {
const subscription = Dimensions.addEventListener('change', ({ window }) => {
// Handle the orientation change logic here if needed
});
return () =>  subscription.remove();
}, []);

const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
backgroundColor: theme.colors.background,
},
mainSection: {
flex: 3,
padding: theme.spacing.medium,
},
header: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
backgroundColor: theme.colors.background,
marginTop: theme.spacing.medium,
paddingRight: theme.spacing.medium,
},
activitiesLeftText: {
fontSize: Math.min(window.width, window.height) * 0.05,
fontWeight: 'bold',
color: theme.colors.primary,
},
activityDetails: {
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
paddingHorizontal: theme.spacing.medium,
marginBottom: 0,
},
activityTitle: {
fontSize: Math.min(window.width, window.height) * 0.07,
fontWeight: 'bold',
color: theme.colors.primary,
textAlign: 'center',
flex: 1,
},
repetitionText: {
fontSize: theme.fontSize.large,
fontWeight: 'bold',
color: theme.colors.primary,
textAlign: 'right',
marginLeft: theme.spacing.medium,
},
activityImage: {
width: '100%',
height: window.height * 0.65,
resizeMode: 'contain',
},
descriptionText: {
fontSize: theme.fontSize.small,
color: theme.colors.gray,
textAlign: 'center',
padding: theme.spacing.small,
},
footer: {
flexDirection: 'row',
justifyContent: 'flex-start',
alignItems: 'center',
padding: theme.spacing.small,
backgroundColor: theme.colors.backgroundLight,
},
backButton: {
flexDirection: 'row',
alignItems: 'center',
paddingVertical: theme.spacing.small,
paddingHorizontal: theme.spacing.small,
},
backIcon: {
fontSize: theme.iconSize.small,
color: theme.colors.primary,
},
backText: {
fontSize: theme.fontSize.small,
color: theme.colors.primary,
marginLeft: theme.spacing.xsmall,
},
nextActivitySection: {
flex: 1,
backgroundColor: theme.colors.backgroundLight,
justifyContent: 'center',
alignItems: 'center',
padding: theme.spacing.medium,
width: '100%',
marginTop: theme.spacing.small,
},
nextText: {
fontSize: theme.fontSize.medium,
fontWeight: 'bold',
color: theme.colors.subtitle,
marginBottom: theme.spacing.small,
},
nextActivityImage: {
width: '80%',
height: undefined,
opacity: 0.5,
aspectRatio: 4 / 3,
resizeMode: 'contain',
},
nextActivityTitle: {
fontSize: theme.fontSize.small,
color: theme.colors.subtitle,
marginBottom: theme.spacing.small,
},
completeButtonContainer: {
justifyContent: 'center',
alignItems: 'center',
padding: theme.spacing.medium,
},
completeButton: {
backgroundColor: theme.colors.primary,
borderRadius: theme.borderRadius.medium,
paddingVertical: theme.spacing.medium,
paddingHorizontal: theme.spacing.large,
elevation: 3,
},
completeButtonText: {
color: theme.colors.white,
fontSize: theme.fontSize.medium,
fontWeight: 'bold',
textAlign: 'center',
},
progressContainer: {
width: '100%',
paddingHorizontal: 10,
paddingBottom: 10,
alignItems: 'center',
},
progressBar: {
height: 20,
backgroundColor: '#cccccc',
position: 'relative',
},
progress: {
height: '100%',
},
progressText: {
width: '15%',
textAlign: 'right',
paddingLeft: 10,
},
centeredView: {
flex: 1,
justifyContent: "center",
alignItems: "center",
marginTop: 22
},
modalView: {
margin: 20,
backgroundColor: "white",
borderRadius: 20,
padding: 35,
alignItems: "center",
shadowColor: "#000",
shadowOpacity: 0.25,
shadowRadius: 4,
elevation: 5,
},
modalButton:  {
borderRadius: 20,
padding: 10,
elevation: 2,
flexDirection: 'row',
alignItems: 'center',
},
modalCloseButton: {
backgroundColor: "#2196F3",
},
textStyle: {
color: "white",
fontWeight: "bold",
textAlign: "center",
},
modalText: {
marginBottom: 15,
textAlign: "center",
marginLeft: 10,
},
});

const calculateSegmentWidths = () => {
const totalActivitiesDuration = activities.reduce((acc, curr) => acc + curr.Duration, 0);
return activities.map(activity => (activity.Duration / totalActivitiesDuration) * 100);
};

const renderTimeSegments = () => {
const elapsedTime = Math.min(timer, totalDuration); // Ensure we don't exceed total duration
const progress = Math.min(elapsedTime / totalDuration, 1);

return (






{timeLeftText()}



);
};

const renderActivitySegments = () => {
const segmentWidths = calculateSegmentWidths();

return (



{segmentWidths.map((width, index) => (

))}


{deltaTimeText()}



);
};

const formatRepetitionAndTime = (repetitions, durationInSeconds) => {
const duration = formatTime(durationInSeconds);
if (repetitions && durationInSeconds) {
return `${repetitions} times (${duration})`;
} else if (repetitions) {
return `${repetitions} times`;
} else if (durationInSeconds) {
return `${duration}`;
}
return '';
};

return (





{activities.length - currentActivityIndex } LEFT


 setIsCancelModalVisible(true)}
/>



{activity &&  (


{activity.Name.toUpperCase()}

{formatRepetitionAndTime(activity.Repetitions, activity.Duration)}



{activity.StaffOnlyNotes}

)}



{nextActivity && (

NEXT

{nextActivity?.Name.toUpperCase()}

)}
{currentActivityIndex === activities.length - 1 && (


COMPLETE CLASS


)}




{renderTimeSegments()}
{renderActivitySegments()}


{currentActivityIndex > 0 && (


BACK

)}


 {
setIsCancelModalVisible(!isCancelModalVisible);
}}
>


Are you sure you want to cancel the class?


Yes, cancel it

 setIsCancelModalVisible(false)}
>
No






);
};

export default LaunchedClassScreen;
Я пытался изменить стили несколько раз и ожидал, что они будут выглядеть одинаково как на Expo, так и на iPad, но различия все еще присутствуют.

Подробнее здесь: https://stackoverflow.com/questions/787 ... s-and-expo
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «IOS»