scrollview 相关问题

请务必使用**平台特定的**标签。仅将此标记用于有关所有平台上滚动视图的最常见问题。滚动视图是用户可以在包含区域内滚动的视图。所有现代用户体验的基础之一。

.safeAreaInsets 会阻止 iOS17 上 SwiftUI 中的触摸

我正在尝试向 ScrollView 添加安全区域,但注意到在 iOS17 上我无法点击 ScrollView 安全区域内的任何内容。 示例代码: 滚动视图{ 虚拟堆栈{ ForEac...

回答 1 投票 0

在 iOS 17 SwiftUI 中检测 ScrollView 何时完成滚动

使用 iOS 17 作为最小目标和 .scrollTargetBehavior(.paging) 修饰符。 我需要一个类似于scrollViewDidEndScrollingAnimation 的回调。 目标是仅在页面切换后获得回调...

回答 1 投票 0

GooglePlacesAutocomplete 不会点击结果

我正在尝试在使用expo(sdk 49)的react-native项目上使用react-native-google-places-autocomplete库及其组件GooglePlacesAutocomplete。 这在正常屏幕下工作正常...

回答 1 投票 0

HStack 在滚动 SwiftUI 中仅移动一项

我正在尝试在 SwiftUI 中创建一个水平滚动视图,一次只能移动一个项目,并且我想保持窥视视图的比例(即项目的部分...

回答 1 投票 0

Kivy 滚动浏览数千行文本

所以我正在开发一个基于 kivy 的应用程序,我希望能够滚动浏览数千行文本。我开始尝试使用基本的滚动视图,但这根本不起作用(据我所知......

回答 3 投票 0

SwiftUI - 淡出 ScrollView

我有一个生成的超大图表,我将其放入 ScrollView 中,以便用户可以向右滚动并查看所有值。我想向用户表明“还有更多内容&...

回答 4 投票 0

Android ScrollView 键盘弹起时不滚动

我的视图没有填满屏幕,但是当键盘出现时,您无法向下滚动到现在覆盖的几个字段。我尝试在清单中添加 adjustmentSize、adjustPan...

回答 4 投票 0

SwiftUI ScrollView 在开头附加元素时忽略滚动位置

我正在实现当用户滑动到边缘时动态将元素附加到 ScrollView 的功能。将元素添加到列表末尾可以按预期工作,但我遇到了一个问题...

回答 1 投票 0

SwiftUI 中 ScrollView 的奇怪行为

我目前正在温习我的 SwiftUI 知识,并且正在构建这个任务屏幕。然而,ScrollView 有一个奇怪的部分,我无法解释如何删除(上面的灰色区域......

回答 1 投票 0

React Native ScrollView 在滚动视图之外的顶部添加了额外的空间

我有一个反应本机应用程序,它有一个滚动视图,当我滚动回顶部时,在滚动视图容器外部添加了一个额外的空间。我添加了一个视图来显示问题...

回答 1 投票 0

iOS 18:contentShape 交互破坏了滚动功能

这是一个简单的代码。问题是在 iOS 18 中,文本编辑器中的滚动不起作用(但在以前的操作系统中它可以正常工作)。对于此问题的任何帮助(解决方法),我将不胜感激。 ZSt...

回答 1 投票 0

垂直滚动在 Expo React Native 中不起作用

我对这个屏幕有疑问。元素溢出,我无法显示侧边栏来滚动内容。奇怪的是,在所有其他屏幕中我都使用我的组件 我对这个屏幕有疑问。元素溢出,我无法显示侧边栏来滚动内容。奇怪的是,在所有其他屏幕中,我使用我的组件 <AppContainer> 和 <SafeScreen>,并且一切正常。我没有包含每个单独组件的代码,因为滚动在任何幻灯片上都不起作用。 我实际上只在网页版上进行测试。 import React, { useState, useEffect, useRef } from 'react'; import { View, Text, TouchableOpacity, StyleSheet, Alert, Platform, TextInput, ScrollView, Dimensions, KeyboardAvoidingView } from 'react-native'; import { Ionicons } from '@expo/vector-icons'; import AppContainer from '../AppContainer'; import SafeScreen from '../SafeScreen'; import AsyncStorage from '@react-native-async-storage/async-storage'; import RicercaScuolaComponent from '../RicercaScuolaComponent'; import RicercaPartecipanti from '../RicercaPartecipanti'; import Animated, { useSharedValue, useAnimatedStyle, withTiming } from 'react-native-reanimated'; import loadGoogleMapsAPI from '../webMapComponent'; import PianoViaggiSummary from './PianoViaggiSummary'; import { getAuth } from 'firebase/auth'; import { getFirestore, collection, doc, setDoc } from 'firebase/firestore'; let MapView, Marker, Geocoder, AutocompleteService, PlacesService;; const NuovoPianoViaggiScreen = ({ }) => { const [currentSlide, setCurrentSlide] = useState(0); const [partecipanti, setPartecipanti] = useState([]); const [scuolaSelezionata, setScuolaSelezionata] = useState(null); const [googleMapsLoaded, setGoogleMapsLoaded] = useState(false); const [meetingPlace, setMeetingPlace] = useState(null); const [searchQuery, setSearchQuery] = useState(''); const [meetingAddress, setMeetingAddress] = useState(''); //const [scuolaDestinazione, setScuolaDestinazione] = useState(null); const [lastSavedSlide, setLastSavedSlide] = useState(-1); const [meetingName, setMeetingName] = useState(''); const [suggestions, setSuggestions] = useState([]); const handleScuolaSelezionata = (scuola) => { console.log('Scuola selezionata:', scuola); setScuolaSelezionata(scuola); // Aggiorna il pianoViaggi direttamente setPianoViaggi(prev => ({ ...prev, scuola: scuola })); }; const [pianoViaggi, setPianoViaggi] = useState({ luogo: null, scuola: null, partecipanti: [] }); const [region, setRegion] = useState({ latitude: 41.9028, longitude: 12.4964, latitudeDelta: 0.0922, longitudeDelta: 0.0421, }); const mapRef = useRef(null); const opacity = useSharedValue(1); useEffect(() => { {/*...*/} } ); // custom alert const customAlert = (title, message, buttons) => { if (Platform.OS === 'web') { if (window.confirm(`${title}\n\n${message}`)) { buttons.find(b => b.style === 'default').onPress(); } else { buttons.find(b => b.style === 'cancel').onPress(); } } else { Alert.alert(title, message, buttons); } }; const salvaProgressoLocale = async () => { {/*...*/} }; const caricaProgressoLocale = async () => { {/*...*/} } }; const salvaSuFirestore = async () => { {/*...*/} }; const handleMapPress = (event) => { {/*...*/} }; const handleSearch = () => { {/*...*/} }; const handleSearchInputChange = (text) => { {/*...*/} }; const renderSuggestion = ({ item }) => ( {/*...*/} ); const renderMap = () => { if (!googleMapsLoaded || !MapView || !AutocompleteService || !PlacesService) { return <Text>Caricamento della mappa...</Text>; } return ( <View style={styles.mapContainer}> <View style={styles.searchContainer}> <TextInput style={styles.searchInput} value={searchQuery} onChangeText={handleSearchInputChange} placeholder="Cerca un luogo o selezionalo sulla mappa" /> <TouchableOpacity style={styles.searchButton} onPress={handleSearch}> <Ionicons name="search" size={24} color="#fff" /> </TouchableOpacity> </View> <MapView style={styles.map} region={region} onRegionChangeComplete={setRegion} onPress={handleMapPress} > {meetingPlace && ( <Marker coordinate={meetingPlace} title="Punto di Ritrovo" description="Luogo di incontro selezionato" /> )} </MapView> {/* Input per il nome personalizzato del luogo */} <TextInput style={styles.locationNameInput} value={meetingName} onChangeText={setMeetingName} // Cambia il nome personalizzato placeholder="Assegna un nome personalizzato al luogo" /> </View> ); }; const fadeOutIn = (nextSlide) => { opacity.value = withTiming(0, { duration: 300 }, () => { setCurrentSlide(nextSlide); opacity.value = withTiming(1, { duration: 300 }); }); }; const passaAllaSlideSuccessiva = async () => { console.log(`Inizio passaAllaSlideSuccessiva. Slide corrente: ${currentSlide}`); let canProceed = true; if (currentSlide === 0) { console.log('Slide 0: Verifica dati del luogo'); console.log(`meetingPlace: ${JSON.stringify(meetingPlace)}`); console.log(`meetingAddress: ${meetingAddress}`); console.log(`meetingName: ${meetingName}`); if (!meetingPlace || !meetingAddress || !meetingName) { console.log('Errore: Dati del luogo mancanti'); customAlert("Errore", "Per favore, seleziona un punto di ritrovo e inserisci un nome per il luogo prima di procedere."); canProceed = false; } else { console.log('Aggiornamento pianoViaggi con i dati del luogo'); setPianoViaggi(prev => ({ {/*...*/} } })); } } else if (currentSlide === 1) { console.log('Slide 1: Verifica selezione scuola'); console.log(`scuolaSelezionata: ${JSON.stringify(scuolaSelezionata)}`); if (!scuolaSelezionata) { console.log('Errore: Scuola non selezionata'); customAlert("Errore", "Per favore, seleziona una scuola dalla lista prima di procedere."); canProceed = false; } else { console.log('Aggiornamento pianoViaggi con la scuola selezionata'); // Aggiorna anche il pianoViaggi con la destinazione setPianoViaggi(prev => ({ ...prev, scuola: scuolaSelezionata // Aggiungi qui })); } } if (canProceed) { {/*...*/} }; const passaAllaSlidePrecedente = () => { fadeOutIn(currentSlide - 1); }; const animatedStyle = useAnimatedStyle(() => { return { opacity: opacity.value, }; }); const renderSlide = () => { const slideContent = (() => { switch (currentSlide) { case 0: return ( <> <Text style={styles.title}>Seleziona il Punto di Ritrovo</Text> {renderMap()} </> ); case 1: return ( <> <Text style={styles.title}>Scuola di Destinazione</Text> <RicercaScuolaComponent onScuolaSelezionata={setScuolaSelezionata} scuolaSelezionata={scuolaSelezionata} /> </> ); case 2: return ( <> <Text style={styles.title}>Aggiungi Partecipanti</Text> <RicercaPartecipanti scuolaSelezionata={scuolaSelezionata} onPartecipanteSelezionato={(partecipante) => setPartecipanti([...partecipanti, partecipante])} /> </> ); case 3: return ( <> <Text style={styles.title}>Riepilogo del piano viaggi</Text> <PianoViaggiSummary pianoViaggi={pianoViaggi} partecipanti={partecipanti} /> </> ); default: return null; } })(); return ( <AppContainer> <SafeScreen style={styles.container}> <Animated.View style={[styles.slideContainer, animatedStyle]}> {slideContent} </Animated.View> </SafeScreen> </AppContainer> ); }; return ( <KeyboardAvoidingView behavior={Platform.OS === 'ios' ? 'padding' : 'height'} style={styles.container} > {renderSlide()} <View style={styles.navigationContainer}> {currentSlide > 0 && ( <TouchableOpacity style={styles.navButton} onPress={passaAllaSlidePrecedente} > <Ionicons name="arrow-back" size={24} color="#fff" /> <Text style={styles.navButtonText}>Indietro</Text> </TouchableOpacity> )} {currentSlide < 3 && ( <TouchableOpacity style={styles.navButton} onPress={passaAllaSlideSuccessiva} > <Text style={styles.navButtonText}>Avanti</Text> <Ionicons name="arrow-forward" size={24} color="#fff" /> </TouchableOpacity> )} </View> </KeyboardAvoidingView> ); }; const styles = StyleSheet.create({ container: { flex: 1, padding: 20, justifyContent: 'center', backgroundColor: '#f4f4f9', }, contentContainer: { flexGrow: 1, padding:20, paddingBottom:100, }, title: { fontSize: 28, fontWeight: 'bold', color: '#333', marginBottom: 20, textAlign: 'center', }, subtitle: { fontSize: 22, fontWeight: 'bold', marginTop: 20, marginBottom: 10, color: '#333', }, input: { borderWidth: 1, borderColor: '#ddd', padding: 15, borderRadius: 10, marginBottom: 20, backgroundColor: '#fff', fontSize: 16, }, suggestionList: { flex: 1, marginBottom: 20, }, suggestionItem: { padding: 15, borderBottomWidth: 1, borderBottomColor: '#ddd', backgroundColor: '#f9f9f9', borderRadius: 8, marginBottom: 5, }, suggestionText: { color: '#333', fontSize: 16, fontWeight: 'bold', }, addManuallyButton: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', marginTop: 10, marginBottom: 20, padding: 10, backgroundColor: '#f0e6ff', borderRadius: 8, }, subtitle: { fontSize: 16, color: '#666', marginBottom: 20, textAlign: 'center', }, addManuallyText: { color: '#6200EE', marginLeft: 10, fontSize: 16, }, participantList: { flex: 1, }, participantItem: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', padding: 15, borderBottomWidth: 1, borderBottomColor: '#ddd', backgroundColor: '#f9f9f9', borderRadius: 8, marginBottom: 5, }, participantText: { color: '#333', fontSize: 16, }, scrollView: { flexGrow: 1, }, navButton: { flexDirection: 'row', alignItems: 'center', }, navButtonText: { color: '#fff', marginHorizontal: 8, }, searchContainer: { flexDirection: 'row', marginBottom: 10, }, searchInput: { flex: 1, borderWidth: 1, borderColor: '#ddd', padding: 10, borderRadius: 5, marginRight: 10, backgroundColor: '#fff', }, searchButton: { backgroundColor: '#6200EE', padding: 10, borderRadius: 5, justifyContent: 'center', alignItems: 'center', }, scrollContent: { flexGrow: 1, paddingBottom: 80, // Aggiungi spazio per la navigation bar }, navigationContainer: { position: 'absolute', bottom: 0, left: 0, right: 0, backgroundColor: '#000', }, navigation: { flexDirection: 'row', justifyContent: 'space-between', padding: 16, }, mapContainer: { height: 400, // Altezza fissa per la mappa marginVertical: 20, }, map: { flex: 1, }, locationNameInput: { borderWidth: 1, borderColor: '#ddd', padding: 10, borderRadius: 5, marginTop: 10, backgroundColor: '#fff', }, safeArea: { flex: 1, backgroundColor: '#f4f4f9', }, slideContainer: { flex:1, }, title: { fontSize: 28, fontWeight: 'bold', color: '#333', marginBottom: 20, textAlign: 'center', }, mapContainer: { height: 400, marginVertical: 20, width: '100%', }, map: { flex: 1, }, searchContainer: { flexDirection: 'row', marginBottom: 10, width: '100%', }, searchInput: { flex: 1, borderWidth: 1, borderColor: '#ddd', padding: 10, borderRadius: 5, marginRight: 10, backgroundColor: '#fff', }, searchButton: { backgroundColor: '#6200EE', padding: 10, borderRadius: 5, justifyContent: 'center', alignItems: 'center', }, locationNameInput: { borderWidth: 1, borderColor: '#ddd', padding: 10, borderRadius: 5, marginTop: 10, backgroundColor: '#fff', width: '100%', }, navigationContainer: { position: 'absolute', bottom: 0, left: 0, right: 0, backgroundColor: '#6200EE', padding: 16, flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', }, navButton: { flexDirection: 'row', alignItems: 'center', padding: 10, }, navButtonText: { color: '#fff', marginHorizontal: 8, fontSize: 16, }, }); export default NewScreen; import React from 'react'; import { View, StyleSheet, useWindowDimensions, ScrollView } from 'react-native'; const AppContainer = ({ children }) => { const { width } = useWindowDimensions(); const isDesktop = width > 768; return ( <ScrollView style={styles.scrollView} contentContainerStyle={styles.scrollViewContent} keyboardShouldPersistTaps="handled" > <View style={[styles.container, isDesktop && styles.desktopContainer]}> <View style={[styles.content, isDesktop && styles.desktopContent]}> {children} </View> </View> </ScrollView> ); }; const styles = StyleSheet.create({ scrollView: { flex: 1, padding: 5, backgroundColor: '#f5f5f5', }, scrollViewContent: { flexGrow: 1, }, container: { flex: 1, alignItems: 'center', }, desktopContainer: { paddingHorizontal: 16, }, content: { flex: 1, width: '100%', maxWidth: 768, backgroundColor: '#f5f5f5', }, desktopContent: { elevation: 5, }, }); export default AppContainer; import React from 'react'; import { SafeAreaView, StyleSheet, Platform, View, ScrollView, StatusBar } from 'react-native'; import { useBottomTabBarHeight } from '@react-navigation/bottom-tabs'; import { useNavigationState } from '@react-navigation/native'; const SafeScreen = ({ children, style, scrollable = false }) => { const navigationState = useNavigationState(state => state); let tabBarHeight = 0; let isInBottomTab = false; if (navigationState) { const route = navigationState.routes[navigationState.index]; isInBottomTab = route.state && route.state.type === 'tab'; } if (isInBottomTab) { try { tabBarHeight = useBottomTabBarHeight(); } catch (error) { console.warn('Failed to get bottom tab bar height:', error); } } const content = ( <View style={[ styles.content, { paddingBottom: Platform.OS === 'android' && isInBottomTab ? tabBarHeight : 0 } ]} > {children} </View> ); return ( <SafeAreaView style={[styles.container, style]}> <StatusBar barStyle="dark-content" backgroundColor="white" /> {content} </SafeAreaView> ); }; const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: 'white', paddingTop: Platform.OS === 'android' ? StatusBar.currentHeight : 0, }, content: { flex: 1, }, scrollViewContent: { flexGrow: 1, }, }); export default SafeScreen; 不要使用本机派生组件作为包装器,这会导致 UI 和手势行为中出现错误。 在您的情况下,您需要用另一个 ScrollView 包裹您的 View 并对其应用 flex: 1 样式。

回答 1 投票 0

有没有办法在 SwiftUI 中成功地将 ScrollView 与拖动手势结合起来?

我本以为这在 SwiftUI 中是微不足道的,但显然不是。 想象一个项目列表,每个项目都有一些文本,在 ScrollView 或滚动的东西(可能是 VStack)中。名单...

回答 1 投票 0

ScrollView 上的分页不起作用/出现

我使用 SwiftUI,我想要一个垂直滚动视图来显示多个项目(事件)。 这些项目包含由照片表示的子项目(参与者)。 我想展示 4

回答 1 投票 0

防止子滚动视图在android上列表的开头和结尾处滚动父级(本机反应)

我正在使用垂直滚动视图和嵌套在其中的平面列表。 在 iOS 上,当我到达列表的开头或结尾并继续滚动时,列表会弹起并且父级不会向上滚动或......

回答 1 投票 0

具有捕捉和缩放功能的滚动视图

我一直想为 Swift iOS 应用程序制作一个滚动捕捉缩放 UI,但不知道要搜索什么。然后昨晚我在苹果新闻应用程序中看到了这个,这是 EX...

回答 1 投票 0

ScrollView 内的 React Native Stack.screen [已关闭]

我正在尝试让我的所有屏幕完全可滚动。直接使用ScrollView就可以了吗? (也许,没有线索)。第二个问题,我正在创建的应用程序具有以下设置: _layout.tsx(根)- 带标题

回答 1 投票 0

带有lazyhstack的滚动视图内奇怪的动画错误

我在一个位于Scrollview内部的lazyHStack中有一个ForEach的itemView(), 在 itemView 中,我有一个点击手势,将一个项目添加到数组中,然后运行 checkIfSelected() 函数,

回答 1 投票 0

iOS 18 中水平 ScrollView 中嵌入 LazyHStack 的 SwiftUI 内容跳转问题

在ScrollView中嵌入LazyHStack时,存在跳跃的内容布局问题。当子组件是嵌入在 VStack 中的 Button 时,会发生奇怪的视图“跳跃”行为

回答 1 投票 0

Swift CollectionView 垂直分页

我在我的collectionview上启用了分页,并遇到了每次滑动的第一个问题,不是在不同的单元格上停止,而是在页面上停止。 然后我尝试在

回答 1 投票 0

© www.soinside.com 2019 - 2024. All rights reserved.