feat(medications): 添加药品图片预览功能并优化InfoCard组件
- 在药品详情页面集成 react-native-image-viewing 实现图片全屏预览 - 添加图片预览提示图标,提升用户交互体验 - 优化 InfoCard 组件渲染逻辑,简化代码结构 - 调整药品图片样式,增加圆角效果并优化尺寸比例 - 为可点击的 InfoCard 图标和箭头添加玻璃态效果支持
This commit is contained in:
@@ -38,6 +38,7 @@ import {
|
||||
TouchableOpacity,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import ImageViewing from 'react-native-image-viewing';
|
||||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
|
||||
const DEFAULT_IMAGE = require('@/assets/images/medicine/image-medicine.png');
|
||||
@@ -79,6 +80,7 @@ export default function MedicationDetailScreen() {
|
||||
const [keyboardHeight, setKeyboardHeight] = useState(0);
|
||||
const [deleteSheetVisible, setDeleteSheetVisible] = useState(false);
|
||||
const [deleteLoading, setDeleteLoading] = useState(false);
|
||||
const [showImagePreview, setShowImagePreview] = useState(false);
|
||||
|
||||
// 剂量选择相关状态
|
||||
const [dosagePickerVisible, setDosagePickerVisible] = useState(false);
|
||||
@@ -518,6 +520,12 @@ export default function MedicationDetailScreen() {
|
||||
}
|
||||
}, [deleteLoading, dispatch, medication, router]);
|
||||
|
||||
const handleImagePreview = useCallback(() => {
|
||||
if (medication?.photoUrl) {
|
||||
setShowImagePreview(true);
|
||||
}
|
||||
}, [medication?.photoUrl]);
|
||||
|
||||
const handleStartDatePress = useCallback(() => {
|
||||
Alert.alert('开始日期', `开始服药日期:${startDateLabel}`);
|
||||
}, [startDateLabel]);
|
||||
@@ -743,13 +751,23 @@ export default function MedicationDetailScreen() {
|
||||
>
|
||||
<View style={[styles.heroCard, { backgroundColor: colors.surface }]}>
|
||||
<View style={styles.heroInfo}>
|
||||
<View style={styles.heroImageWrapper}>
|
||||
<TouchableOpacity
|
||||
style={styles.heroImageWrapper}
|
||||
onPress={handleImagePreview}
|
||||
activeOpacity={0.8}
|
||||
disabled={!medication.photoUrl}
|
||||
>
|
||||
<Image
|
||||
source={medication.photoUrl ? { uri: medication.photoUrl } : DEFAULT_IMAGE}
|
||||
style={styles.heroImage}
|
||||
contentFit="cover"
|
||||
/>
|
||||
</View>
|
||||
{medication.photoUrl && (
|
||||
<View style={styles.imagePreviewHint}>
|
||||
<Ionicons name="expand-outline" size={14} color="#FFF" />
|
||||
</View>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
<View>
|
||||
<Text style={[styles.heroTitle, { color: colors.text }]}>{medication.name}</Text>
|
||||
<Text style={[styles.heroMeta, { color: colors.textSecondary }]}>
|
||||
@@ -1305,6 +1323,35 @@ export default function MedicationDetailScreen() {
|
||||
loading={deleteLoading}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
{/* 图片预览 */}
|
||||
{medication?.photoUrl && (
|
||||
<ImageViewing
|
||||
images={[{ uri: medication.photoUrl }]}
|
||||
imageIndex={0}
|
||||
visible={showImagePreview}
|
||||
onRequestClose={() => setShowImagePreview(false)}
|
||||
swipeToCloseEnabled={true}
|
||||
doubleTapToZoomEnabled={true}
|
||||
HeaderComponent={() => (
|
||||
<View style={styles.imageViewerHeader}>
|
||||
<Text style={styles.imageViewerHeaderText}>
|
||||
{medication.name}
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
FooterComponent={() => (
|
||||
<View style={styles.imageViewerFooter}>
|
||||
<TouchableOpacity
|
||||
style={styles.imageViewerFooterButton}
|
||||
onPress={() => setShowImagePreview(false)}
|
||||
>
|
||||
<Text style={styles.imageViewerFooterButtonText}>关闭</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
@@ -1381,10 +1428,12 @@ const styles = StyleSheet.create({
|
||||
backgroundColor: '#F2F2F2',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
position: 'relative',
|
||||
},
|
||||
heroImage: {
|
||||
width: '80%',
|
||||
height: '80%',
|
||||
width: '60%',
|
||||
height: '60%',
|
||||
borderRadius: '20%'
|
||||
},
|
||||
heroTitle: {
|
||||
fontSize: 20,
|
||||
@@ -1709,4 +1758,49 @@ const styles = StyleSheet.create({
|
||||
fontSize: 13,
|
||||
fontWeight: '600',
|
||||
},
|
||||
imagePreviewHint: {
|
||||
position: 'absolute',
|
||||
top: 4,
|
||||
right: 4,
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
||||
borderRadius: 10,
|
||||
padding: 4,
|
||||
},
|
||||
// ImageViewing 组件样式
|
||||
imageViewerHeader: {
|
||||
position: 'absolute',
|
||||
top: 60,
|
||||
left: 20,
|
||||
right: 20,
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.7)',
|
||||
borderRadius: 12,
|
||||
paddingHorizontal: 16,
|
||||
paddingVertical: 12,
|
||||
zIndex: 1,
|
||||
},
|
||||
imageViewerHeaderText: {
|
||||
color: '#FFF',
|
||||
fontSize: 14,
|
||||
fontWeight: '500',
|
||||
textAlign: 'center',
|
||||
},
|
||||
imageViewerFooter: {
|
||||
position: 'absolute',
|
||||
bottom: 60,
|
||||
left: 20,
|
||||
right: 20,
|
||||
alignItems: 'center',
|
||||
zIndex: 1,
|
||||
},
|
||||
imageViewerFooterButton: {
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.7)',
|
||||
paddingHorizontal: 24,
|
||||
paddingVertical: 12,
|
||||
borderRadius: 20,
|
||||
},
|
||||
imageViewerFooterButtonText: {
|
||||
color: '#FFF',
|
||||
fontSize: 16,
|
||||
fontWeight: '500',
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user