u
This commit is contained in:
1 parent
6b216ffdab
commit
f384a2a6e9
352 files changed
+450
-41539
No files matched your search
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"$schema": "./node_modules/oxfmt/configuration_schema.json",
|
||||
"ignorePatterns": []
|
||||
}
|
||||
+14
-4
@@ -1,7 +1,17 @@
|
||||
{
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll": "explicit",
|
||||
"source.organizeImports": "explicit",
|
||||
"source.sortMembers": "explicit"
|
||||
"oxc.fmt.configPath": ".oxfmtrc.json",
|
||||
"editor.defaultFormatter": "oxc.oxc-vscode",
|
||||
"editor.formatOnSave": true,
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "oxc.oxc-vscode",
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "oxc.oxc-vscode",
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[typescriptreact]": {
|
||||
"editor.defaultFormatter": "oxc.oxc-vscode",
|
||||
"editor.formatOnSave": true
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,8 @@
|
||||
"imageWidth": 76
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
"expo-web-browser"
|
||||
],
|
||||
"experiments": {
|
||||
"typedRoutes": true,
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
module.exports = function (api) {
|
||||
api.cache(true);
|
||||
return {
|
||||
presets: ['babel-preset-expo'],
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
// Learn more https://docs.expo.io/guides/customizing-metro
|
||||
const { getDefaultConfig } = require('expo/metro-config');
|
||||
|
||||
/** @type {import('expo/metro-config').MetroConfig} */
|
||||
const config = getDefaultConfig(__dirname);
|
||||
|
||||
module.exports = config;
|
||||
@@ -14,21 +14,21 @@
|
||||
"@react-navigation/bottom-tabs": "^7.15.5",
|
||||
"@react-navigation/elements": "^2.9.10",
|
||||
"@react-navigation/native": "^7.1.33",
|
||||
"expo": "~55.0.12",
|
||||
"expo-blur": "~55.0.13",
|
||||
"expo-constants": "~55.0.12",
|
||||
"expo-device": "~55.0.13",
|
||||
"expo": "~55.0.13",
|
||||
"expo-blur": "~55.0.14",
|
||||
"expo-constants": "~55.0.13",
|
||||
"expo-device": "~55.0.14",
|
||||
"expo-font": "~55.0.6",
|
||||
"expo-glass-effect": "~55.0.10",
|
||||
"expo-image": "~55.0.8",
|
||||
"expo-linear-gradient": "~55.0.12",
|
||||
"expo-linking": "~55.0.11",
|
||||
"expo-linear-gradient": "~55.0.13",
|
||||
"expo-linking": "~55.0.12",
|
||||
"expo-router": "~55.0.11",
|
||||
"expo-splash-screen": "~55.0.16",
|
||||
"expo-splash-screen": "~55.0.17",
|
||||
"expo-status-bar": "~55.0.5",
|
||||
"expo-symbols": "~55.0.7",
|
||||
"expo-system-ui": "~55.0.14",
|
||||
"expo-web-browser": "~55.0.13",
|
||||
"expo-system-ui": "~55.0.15",
|
||||
"expo-web-browser": "~55.0.14",
|
||||
"react": "19.2.0",
|
||||
"react-dom": "19.2.0",
|
||||
"react-native": "0.83.4",
|
||||
@@ -41,6 +41,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "~19.2.2",
|
||||
"oxfmt": "^0.44.0",
|
||||
"typescript": "~5.9.2"
|
||||
},
|
||||
"private": true
|
||||
|
||||
Generated
+402
-172
File diff suppressed because it is too large.
Load diff
@@ -1,318 +1,8 @@
|
||||
import { Feather, Ionicons } from '@expo/vector-icons';
|
||||
import { BlurView } from "expo-blur";
|
||||
import React, { useState } from "react";
|
||||
import {
|
||||
Platform,
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
} from "react-native";
|
||||
import React from "react";
|
||||
import { StyleSheet, View } from "react-native";
|
||||
|
||||
export default function QQStyleTabBar() {
|
||||
const [activeTab, setActiveTab] = useState("消息");
|
||||
const [unreadCount] = useState(12);
|
||||
const [hasNewMoment] = useState(true);
|
||||
|
||||
const tabs = [
|
||||
{ id: "消息", label: "消息", icon: "chatbubble" },
|
||||
{ id: "频道", label: "频道", icon: "people" },
|
||||
{ id: "联系人", label: "联系人", icon: "person" },
|
||||
{ id: "动态", label: "动态", icon: "refresh-cw" },
|
||||
];
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
{/* 模拟聊天列表 - 作为模糊背景 */}
|
||||
<ScrollView
|
||||
contentContainerStyle={{ paddingTop: 40, paddingBottom: 100 }}
|
||||
showsVerticalScrollIndicator={false}
|
||||
>
|
||||
{Array.from({ length: 20 }).map((_, i) => {
|
||||
const isMe = i % 2 === 0;
|
||||
const messageType = i % 3;
|
||||
|
||||
return (
|
||||
<View
|
||||
key={i}
|
||||
style={[
|
||||
styles.messageRow,
|
||||
isMe ? styles.right : styles.left,
|
||||
]}
|
||||
>
|
||||
<View style={styles.avatarContainer}>
|
||||
<View style={styles.avatar} />
|
||||
</View>
|
||||
|
||||
<View
|
||||
style={[
|
||||
styles.bubble,
|
||||
isMe ? styles.myBubble : styles.otherBubble,
|
||||
]}
|
||||
>
|
||||
<Text style={[
|
||||
styles.msgText,
|
||||
isMe && styles.myMsgText
|
||||
]}>
|
||||
{isMe
|
||||
? `我发的消息 ${i + 1}`
|
||||
: messageType === 0
|
||||
? `你好,最近怎么样? ${i + 1}`
|
||||
: messageType === 1
|
||||
? `今晚有空吗?一起吃个饭? ${i + 1}`
|
||||
: `上次说的那个项目有进展了 ${i + 1}`}
|
||||
</Text>
|
||||
<Text style={styles.timeText}>昨天 14:3{i}</Text>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
})}
|
||||
</ScrollView>
|
||||
|
||||
{/* TabBar - 使用expo-blur实现毛玻璃效果 */}
|
||||
<View style={styles.tabBarContainer}>
|
||||
<BlurView
|
||||
intensity={80} // 稍微降低强度,让白色更明显
|
||||
tint="light"
|
||||
style={StyleSheet.absoluteFill}
|
||||
/>
|
||||
|
||||
{/* 磨砂白色层 - 调整透明度 */}
|
||||
<View style={styles.whiteOverlay} />
|
||||
|
||||
{/* TabBar内容 */}
|
||||
<View style={styles.tabs}>
|
||||
{tabs.map((tab) => {
|
||||
const isActive = activeTab === tab.id;
|
||||
const isMessageTab = tab.id === "消息";
|
||||
const isMomentTab = tab.id === "动态";
|
||||
|
||||
return (
|
||||
<TouchableOpacity
|
||||
key={tab.id}
|
||||
style={styles.tabItem}
|
||||
onPress={() => setActiveTab(tab.id)}
|
||||
activeOpacity={0.7}
|
||||
>
|
||||
<View style={styles.iconContainer}>
|
||||
{isMessageTab || tab.id === "联系人" || tab.id === "频道" ? (
|
||||
isActive ? (
|
||||
<Ionicons
|
||||
name={tab.icon}
|
||||
size={24}
|
||||
color="#0066FF"
|
||||
/>
|
||||
) : (
|
||||
<Ionicons
|
||||
name={`${tab.icon}-outline`}
|
||||
size={24}
|
||||
color="#000000"
|
||||
/>
|
||||
)
|
||||
) : (
|
||||
<Feather
|
||||
name={tab.icon}
|
||||
size={24}
|
||||
color={isActive ? "#0066FF" : "#000000"}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* 消息角标 */}
|
||||
{isMessageTab && unreadCount > 0 && (
|
||||
<View style={styles.badge}>
|
||||
<Text style={styles.badgeText}>
|
||||
{unreadCount > 99 ? "99+" : unreadCount}
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
|
||||
{/* 动态红点角标 */}
|
||||
{isMomentTab && hasNewMoment && !isActive && (
|
||||
<View style={styles.dotBadge} />
|
||||
)}
|
||||
</View>
|
||||
|
||||
<Text
|
||||
style={[
|
||||
styles.tabLabel,
|
||||
isActive && styles.tabLabelActive
|
||||
]}
|
||||
>
|
||||
{tab.label}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
|
||||
{/* 顶部细线 */}
|
||||
<View style={styles.topBorder} />
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
export default function OnlyBlurDemo() {
|
||||
return <View style={{ flex: 1, backgroundColor: "#fff" }}></View>;
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: "#EFEFF4", // 与QQ类似的浅灰色背景
|
||||
},
|
||||
|
||||
// 聊天布局
|
||||
messageRow: {
|
||||
paddingHorizontal: 12,
|
||||
marginVertical: 8,
|
||||
flexDirection: "row",
|
||||
alignItems: "flex-end",
|
||||
},
|
||||
|
||||
left: {
|
||||
justifyContent: "flex-start",
|
||||
},
|
||||
|
||||
right: {
|
||||
justifyContent: "flex-end",
|
||||
},
|
||||
|
||||
avatarContainer: {
|
||||
width: 40,
|
||||
height: 40,
|
||||
borderRadius: 6,
|
||||
marginRight: 10,
|
||||
backgroundColor: "#E0E0E0",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
},
|
||||
|
||||
avatar: {
|
||||
width: 36,
|
||||
height: 36,
|
||||
borderRadius: 4,
|
||||
backgroundColor: "#C0C0C0",
|
||||
},
|
||||
|
||||
bubble: {
|
||||
maxWidth: "70%",
|
||||
paddingVertical: 10,
|
||||
paddingHorizontal: 12,
|
||||
borderRadius: 8,
|
||||
},
|
||||
|
||||
myBubble: {
|
||||
backgroundColor: "#4EA0FF",
|
||||
borderTopRightRadius: 0,
|
||||
},
|
||||
|
||||
otherBubble: {
|
||||
backgroundColor: "#FFFFFF",
|
||||
borderTopLeftRadius: 0,
|
||||
},
|
||||
|
||||
msgText: {
|
||||
color: "#333333",
|
||||
fontSize: 16,
|
||||
},
|
||||
|
||||
myMsgText: {
|
||||
color: "#FFFFFF",
|
||||
},
|
||||
|
||||
timeText: {
|
||||
fontSize: 12,
|
||||
color: "#999999",
|
||||
marginTop: 4,
|
||||
alignSelf: "flex-end",
|
||||
},
|
||||
|
||||
// TabBar样式
|
||||
tabBarContainer: {
|
||||
position: "absolute",
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
height: Platform.OS === "ios" ? 85 : 60,
|
||||
overflow: "hidden",
|
||||
},
|
||||
|
||||
whiteOverlay: {
|
||||
...StyleSheet.absoluteFillObject,
|
||||
// 关键参数调整:稍微增加不透明度,让白色更明显
|
||||
backgroundColor: "rgba(249, 249, 249, 0.95)",
|
||||
},
|
||||
|
||||
topBorder: {
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
height: 0.5,
|
||||
backgroundColor: "rgba(0, 0, 0, 0.1)", // 顶部细线
|
||||
},
|
||||
|
||||
tabs: {
|
||||
flex: 1,
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-around",
|
||||
paddingBottom: Platform.OS === "ios" ? 20 : 0,
|
||||
},
|
||||
|
||||
tabItem: {
|
||||
flex: 1,
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
},
|
||||
|
||||
iconContainer: {
|
||||
width: 24,
|
||||
height: 24,
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
marginBottom: 4,
|
||||
position: "relative",
|
||||
},
|
||||
|
||||
tabLabel: {
|
||||
fontSize: 10,
|
||||
color: "#000000",
|
||||
fontWeight: "500",
|
||||
},
|
||||
|
||||
tabLabelActive: {
|
||||
color: "#0066FF",
|
||||
},
|
||||
|
||||
badge: {
|
||||
position: "absolute",
|
||||
top: -6,
|
||||
right: -12,
|
||||
minWidth: 18,
|
||||
height: 18,
|
||||
borderRadius: 9,
|
||||
backgroundColor: "#FF3B30",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
paddingHorizontal: 4,
|
||||
borderWidth: 2,
|
||||
borderColor: "#FAFAFA", // 与TabBar背景色保持一致
|
||||
},
|
||||
|
||||
badgeText: {
|
||||
color: "#FFFFFF",
|
||||
fontSize: 10,
|
||||
fontWeight: "bold",
|
||||
},
|
||||
|
||||
dotBadge: {
|
||||
position: "absolute",
|
||||
top: -4,
|
||||
right: -6,
|
||||
width: 8,
|
||||
height: 8,
|
||||
borderRadius: 4,
|
||||
backgroundColor: "#FF3B30",
|
||||
borderWidth: 1.5,
|
||||
borderColor: "#FAFAFA", // 与TabBar背景色保持一致
|
||||
},
|
||||
});
|
||||
const styles = StyleSheet.create({});
|
||||
Reference in new issue
Block a user