尝试修复弹出菜单、列表位置不正确的问题

This commit is contained in:
lyswhut 2021-06-05 15:40:04 +08:00
parent 4e8605cae6
commit 1385d80c93
7 changed files with 87 additions and 56 deletions

View File

@ -7,3 +7,4 @@
- 修复定时播放开启歌曲播放完毕再停止时,若倒计时已结束会导致无法播放歌曲的问题 - 修复定时播放开启歌曲播放完毕再停止时,若倒计时已结束会导致无法播放歌曲的问题
- 修复打开歌单失败时会导致应用崩溃的问题 - 修复打开歌单失败时会导致应用崩溃的问题
- 修复打开kw歌单失败时会无限重试的问题 - 修复打开kw歌单失败时会无限重试的问题
- 尝试修复弹出菜单、列表位置不正确的问题

View File

@ -11,7 +11,6 @@ const styles = StyleSheet.create({
flex: 1, flex: 1,
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
backgroundColor: 'rgba(0,0,0,0.2)',
}, },
modalView: { modalView: {
maxWidth: '90%', maxWidth: '90%',
@ -71,7 +70,7 @@ export default ({
const closeBtnComponent = useMemo(() => closeBtn ? <TouchableHighlight style={styles.closeBtn} underlayColor={theme.secondary_5} onPress={hideDialog}><Icon name="close" style={{ color: theme.secondary40, fontSize: 10 }} /></TouchableHighlight> : null, [closeBtn, hideDialog, theme]) const closeBtnComponent = useMemo(() => closeBtn ? <TouchableHighlight style={styles.closeBtn} underlayColor={theme.secondary_5} onPress={hideDialog}><Icon name="close" style={{ color: theme.secondary40, fontSize: 10 }} /></TouchableHighlight> : null, [closeBtn, hideDialog, theme])
return ( return (
<Modal visible={visible} hideModal={hideDialog} keyHide={keyHide} bgHide={bgHide}> <Modal visible={visible} hideModal={hideDialog} keyHide={keyHide} bgHide={bgHide} bgColor="rgba(0,0,0,0.2)">
<View style={{ ...styles.centeredView, paddingBottom: keyboardShown ? keyboardHeight : 0 }}> <View style={{ ...styles.centeredView, paddingBottom: keyboardShown ? keyboardHeight : 0 }}>
<View style={styles.modalView} onStartShouldSetResponder={() => true}> <View style={styles.modalView} onStartShouldSetResponder={() => true}>
<View style={{ ...styles.header, backgroundColor: theme.secondary }}> <View style={{ ...styles.header, backgroundColor: theme.secondary }}>

View File

@ -1,5 +1,5 @@
import React, { useMemo, useCallback, memo } from 'react' import React, { useMemo, useCallback, memo } from 'react'
import { StyleSheet, View, Text, ScrollView, TouchableHighlight } from 'react-native' import { StyleSheet, View, Text, ScrollView, TouchableHighlight, TouchableWithoutFeedback } from 'react-native'
import { useDimensions } from '@/utils/hooks' import { useDimensions } from '@/utils/hooks'
import Modal from '@/components/common/Modal' import Modal from '@/components/common/Modal'
@ -33,37 +33,28 @@ const styles = StyleSheet.create({
const Panel = ({ const Panel = ({
buttonPosition, buttonPosition,
panelStyle = {}, panelStyle = {},
hidePanel,
children, children,
}) => { }) => {
const dimensions = useDimensions() // const dimensions = useDimensions()
const { window: windowSize } = useDimensions()
// const theme = useGetter('common', 'theme') // const theme = useGetter('common', 'theme')
// const fadeAnim = useRef(new Animated.Value(0)).current // const fadeAnim = useRef(new Animated.Value(0)).current
// console.log(buttonPosition) // console.log(buttonPosition)
const screenSize = useMemo(() => { // console.log(dimensions)
const screenSize = {}
if (dimensions.window.height > dimensions.window.width) {
screenSize.height = dimensions.screen.height
screenSize.width = dimensions.screen.width
} else {
screenSize.height = dimensions.screen.width
screenSize.width = dimensions.screen.height
}
return screenSize
}, [dimensions])
const style = useMemo(() => { const style = useMemo(() => {
const isBottom = buttonPosition.y > screenSize.height / 2 const isBottom = buttonPosition.y > windowSize.height / 2
let top let top
let height let height
let justifyContent let justifyContent
if (isBottom) { if (isBottom) {
height = buttonPosition.y - screenSize.height * 0.3 height = buttonPosition.y - windowSize.height * 0.3
top = buttonPosition.y - height top = buttonPosition.y - height
justifyContent = 'flex-end' justifyContent = 'flex-end'
} else { } else {
top = buttonPosition.y + buttonPosition.h top = buttonPosition.y + buttonPosition.h
height = screenSize.height * 0.7 - top height = windowSize.height * 0.7 - top
justifyContent = 'flex-start' justifyContent = 'flex-start'
} }
const frameStyle = { const frameStyle = {
@ -71,15 +62,19 @@ const Panel = ({
height, height,
top, top,
justifyContent, justifyContent,
width: screenSize.width, width: windowSize.width,
} }
return frameStyle return frameStyle
}, [screenSize, buttonPosition]) }, [windowSize, buttonPosition])
return ( return (
<TouchableWithoutFeedback onPress={hidePanel}>
<View style={{ ...styles.menu, ...style }}> <View style={{ ...styles.menu, ...style }}>
<View onStartShouldSetResponder={() => true}>
{children} {children}
</View> </View>
</View>
</TouchableWithoutFeedback>
) )
} }
@ -87,11 +82,9 @@ export default memo(({ visible, hidePanel, buttonPosition, children, panelStyle
// console.log(visible) // console.log(visible)
return ( return (
<Modal visible={visible} hideModal={hidePanel} onStartShouldSetResponder={() => true}> <Modal visible={visible} hideModal={hidePanel} onStartShouldSetResponder={() => true}>
<View style={{ flex: 1 }}>
<Panel buttonPosition={buttonPosition} panelStyle={panelStyle} visible={visible} hidePanel={hidePanel}> <Panel buttonPosition={buttonPosition} panelStyle={panelStyle} visible={visible} hidePanel={hidePanel}>
{children} {children}
</Panel> </Panel>
</View>
</Modal> </Modal>
) )
}) })

View File

@ -1,5 +1,5 @@
import React, { useMemo, useCallback, memo } from 'react' import React, { useMemo, useCallback, memo } from 'react'
import { StyleSheet, View, Text, Animated, useWindowDimensions, TouchableHighlight } from 'react-native' import { StyleSheet, View, Text, Animated, TouchableHighlight } from 'react-native'
import { useDimensions } from '@/utils/hooks' import { useDimensions } from '@/utils/hooks'
import Modal from './Modal' import Modal from './Modal'
@ -9,6 +9,15 @@ import { useGetter } from '@/store'
// const menuItemWidth = 100 // const menuItemWidth = 100
const styles = StyleSheet.create({ const styles = StyleSheet.create({
mask: {
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0,
opacity: 0,
backgroundColor: 'black',
},
menu: { menu: {
position: 'absolute', position: 'absolute',
borderWidth: StyleSheet.hairlineWidth, borderWidth: StyleSheet.hairlineWidth,
@ -41,31 +50,20 @@ const Menu = ({
width = 100, width = 100,
height = 42, height = 42,
}) => { }) => {
const dimensions = useDimensions()
const theme = useGetter('common', 'theme') const theme = useGetter('common', 'theme')
const { window: windowSize } = useDimensions()
// const fadeAnim = useRef(new Animated.Value(0)).current // const fadeAnim = useRef(new Animated.Value(0)).current
// console.log(buttonPosition) // console.log(buttonPosition)
const screenSize = useMemo(() => {
const screenSize = {}
if (dimensions.window.height > dimensions.window.width) {
screenSize.height = dimensions.screen.height
screenSize.width = dimensions.screen.width
} else {
screenSize.height = dimensions.screen.width
screenSize.width = dimensions.screen.height
}
return screenSize
}, [dimensions])
const menuStyle = useMemo(() => { const menuStyle = useMemo(() => {
let menuHeight = menus.length * height + 1 let menuHeight = menus.length * height + 1
const topHeight = buttonPosition.y - 20 const topHeight = buttonPosition.y - 20
const bottomHeight = screenSize.height - buttonPosition.y - buttonPosition.h - 20 const bottomHeight = windowSize.height - buttonPosition.y - buttonPosition.h - 20
if (menuHeight > topHeight && menuHeight > bottomHeight) menuHeight = Math.max(topHeight, bottomHeight) if (menuHeight > topHeight && menuHeight > bottomHeight) menuHeight = Math.max(topHeight, bottomHeight)
const menuWidth = width const menuWidth = width
const bottomSpace = screenSize.height - buttonPosition.y - buttonPosition.h - 20 const bottomSpace = windowSize.height - buttonPosition.y - buttonPosition.h - 20
const rightSpace = screenSize.width - buttonPosition.x - menuWidth - 20 const rightSpace = windowSize.width - buttonPosition.x - menuWidth - 20
const showInBottom = bottomSpace >= menuHeight const showInBottom = bottomSpace >= menuHeight
const showInRight = rightSpace >= menuWidth const showInRight = rightSpace >= menuWidth
const frameStyle = { const frameStyle = {
@ -75,10 +73,10 @@ const Menu = ({
if (showInRight) { if (showInRight) {
frameStyle.left = buttonPosition.x frameStyle.left = buttonPosition.x
} else { } else {
frameStyle.right = screenSize.width - buttonPosition.x - buttonPosition.w frameStyle.right = windowSize.width - buttonPosition.x - buttonPosition.w
} }
return frameStyle return frameStyle
}, [screenSize, buttonPosition, menus, width, height]) }, [windowSize, buttonPosition, menus, width, height])
const menuPress = useCallback((menu, index) => { const menuPress = useCallback((menu, index) => {
// if (menu.disabled) return // if (menu.disabled) return
@ -131,9 +129,7 @@ export default memo(({ visible, hideMenu, buttonPosition, menus, longPress, onPr
// console.log(visible) // console.log(visible)
return ( return (
<Modal visible={visible} hideModal={hideMenu} onStartShouldSetResponder={() => true}> <Modal visible={visible} hideModal={hideMenu} onStartShouldSetResponder={() => true}>
<View style={{ flex: 1 }}>
<Menu menus={menus} buttonPosition={buttonPosition} longPress={longPress} onPress={onPress} visible={visible} hideMenu={hideMenu} width={width} height={height} /> <Menu menus={menus} buttonPosition={buttonPosition} longPress={longPress} onPress={onPress} visible={visible} hideMenu={hideMenu} width={width} height={height} />
</View>
</Modal> </Modal>
) )
}) })

View File

@ -1,13 +1,26 @@
import React, { memo, useCallback } from 'react' import React, { memo, useCallback } from 'react'
import { Modal, TouchableWithoutFeedback } from 'react-native' import { Modal, TouchableWithoutFeedback, StyleSheet, View } from 'react-native'
import { useDimensions } from '@/utils/hooks'
const styles = StyleSheet.create({
mask: {
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0,
},
})
export default memo(({ export default memo(({
visible = false, visible = false,
hideModal = () => {}, hideModal = () => {},
keyHide = true, keyHide = true,
bgHide = true, bgHide = true,
bgColor = 'rgba(0,0,0,0)',
children, children,
}) => { }) => {
const { window: windowSize } = useDimensions()
const handleRequestClose = useCallback(() => { const handleRequestClose = useCallback(() => {
if (keyHide) hideModal(false) if (keyHide) hideModal(false)
}, [hideModal, keyHide]) }, [hideModal, keyHide])
@ -24,9 +37,12 @@ export default memo(({
visible={visible} visible={visible}
onRequestClose={handleRequestClose} onRequestClose={handleRequestClose}
> >
<TouchableWithoutFeedback onPress={handleBgClose}> <>
{children} <TouchableWithoutFeedback style={{ ...styles.mask, width: windowSize.width, height: windowSize.height }} onPress={handleBgClose}>
<View style={{ ...styles.mask, width: windowSize.width, height: windowSize.height, backgroundColor: bgColor }}></View>
</TouchableWithoutFeedback> </TouchableWithoutFeedback>
{children}
</>
</Modal> </Modal>
) )
}) })

View File

@ -1,15 +1,16 @@
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import { Dimensions } from 'react-native' import { Dimensions } from 'react-native'
import { getWindowSise } from '@/utils/tools'
export default () => { export default () => {
const [dimensions, setDimensions] = useState({ const [dimensions, setDimensions] = useState({
window: Dimensions.get('window'), window: getWindowSise(),
screen: Dimensions.get('screen'), screen: Dimensions.get('screen'),
}) })
useEffect(() => { useEffect(() => {
const onChange = ({ window, screen }) => { const onChange = ({ window, screen }) => {
setDimensions({ window, screen }) setDimensions({ window: getWindowSise(window), screen })
} }
Dimensions.addEventListener('change', onChange) Dimensions.addEventListener('change', onChange)

View File

@ -1,4 +1,5 @@
import { Platform, NativeModules, ToastAndroid, BackHandler, Linking } from 'react-native' import { Platform, NativeModules, ToastAndroid, BackHandler, Linking, Dimensions } from 'react-native'
import ExtraDimensions from 'react-native-extra-dimensions-android'
import { getData, setData, getAllKeys, removeData, removeDataMultiple, setDataMultiple, getDataMultiple } from '@/plugins/storage' import { getData, setData, getAllKeys, removeData, removeDataMultiple, setDataMultiple, getDataMultiple } from '@/plugins/storage'
import { storageDataPrefix } from '@/config' import { storageDataPrefix } from '@/config'
import { throttle } from './index' import { throttle } from './index'
@ -22,6 +23,30 @@ const handleSaveListScrollPosition = throttle(data => {
setData(listPositionPrefix, data) setData(listPositionPrefix, data)
}, 1000) }, 1000)
// fix https://github.com/facebook/react-native/issues/4934
export const getWindowSise = windowDimensions => {
if (!windowDimensions) windowDimensions = Dimensions.get('window')
if (Platform.OS === 'ios') return windowDimensions
const windowSize = {
width: ExtraDimensions.getRealWindowWidth(),
height: ExtraDimensions.getRealWindowHeight(),
}
if (
(windowDimensions.height > windowDimensions.width && windowSize.height < windowSize.width) ||
(windowDimensions.width > windowDimensions.height && windowSize.width < windowSize.height)
) {
windowSize.height = windowSize.width
}
windowSize.width = windowDimensions.width
if (ExtraDimensions.isSoftMenuBarEnabled()) {
windowSize.height -= ExtraDimensions.getSoftMenuBarHeight()
}
return windowSize
}
/** /**
* 显示toast * 显示toast
* @param {String} message 消息 * @param {String} message 消息