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

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歌单失败时会无限重试的问题
- 尝试修复弹出菜单、列表位置不正确的问题

View File

@ -11,7 +11,6 @@ const styles = StyleSheet.create({
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'rgba(0,0,0,0.2)',
},
modalView: {
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])
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.modalView} onStartShouldSetResponder={() => true}>
<View style={{ ...styles.header, backgroundColor: theme.secondary }}>

View File

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

View File

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

View File

@ -1,13 +1,26 @@
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(({
visible = false,
hideModal = () => {},
keyHide = true,
bgHide = true,
bgColor = 'rgba(0,0,0,0)',
children,
}) => {
const { window: windowSize } = useDimensions()
const handleRequestClose = useCallback(() => {
if (keyHide) hideModal(false)
}, [hideModal, keyHide])
@ -24,9 +37,12 @@ export default memo(({
visible={visible}
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>
{children}
</>
</Modal>
)
})

View File

@ -1,15 +1,16 @@
import { useEffect, useState } from 'react'
import { Dimensions } from 'react-native'
import { getWindowSise } from '@/utils/tools'
export default () => {
const [dimensions, setDimensions] = useState({
window: Dimensions.get('window'),
window: getWindowSise(),
screen: Dimensions.get('screen'),
})
useEffect(() => {
const onChange = ({ window, screen }) => {
setDimensions({ window, screen })
setDimensions({ window: getWindowSise(window), screen })
}
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 { storageDataPrefix } from '@/config'
import { throttle } from './index'
@ -22,6 +23,30 @@ const handleSaveListScrollPosition = throttle(data => {
setData(listPositionPrefix, data)
}, 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
* @param {String} message 消息