ReactNative【實戰系列教程】我的小紅書 5 -- 文章詳情(含輪播圖 ImageSlider,點亮紅心動畫 Heart,嵌套評論等)

最終效果

在這里插入圖片描述

安裝依賴

npm i dayjs

用于對時間進行格式化

必備組件

輪播圖 ImageSlider

https://blog.csdn.net/weixin_41192489/article/details/149224510

點亮紅心動畫 Heart

components/Heart.tsx

import AntDesign from "@expo/vector-icons/AntDesign";
import React, { useEffect, useRef, useState } from "react";
import { Animated, TouchableOpacity } from "react-native";
type Props = {value: boolean;onValueChanged?: (value: boolean) => void;size?: number;color?: string;
};
// eslint-disable-next-line react/display-name
export default (props: Props) => {const { value, onValueChanged, size = 20, color = "black" } = props;const [showState, setShowState] = useState<boolean>(false);const scale = useRef<Animated.Value>(new Animated.Value(0)).current;const alpha = useRef<Animated.Value>(new Animated.Value(0)).current;useEffect(() => {setShowState(value);}, [value]);const onHeartPress = () => {const newState = !showState;setShowState(newState);onValueChanged?.(newState);if (newState) {alpha.setValue(1);const scaleAnim = Animated.timing(scale, {toValue: 1.8,duration: 300,useNativeDriver: false,});const alphaAnim = Animated.timing(alpha, {toValue: 0,duration: 400,useNativeDriver: false,delay: 200,});Animated.parallel([scaleAnim, alphaAnim]).start();} else {scale.setValue(0);alpha.setValue(0);}};return (<TouchableOpacity onPress={onHeartPress}>{showState ? (<AntDesign name="heart" size={size} color="red" />) : (<AntDesign name="hearto" size={size} color={color} />)}<Animated.Viewstyle={{width: size,height: size,borderRadius: size / 2,borderWidth: size / 20,position: "absolute",borderColor: "#ff2442",transform: [{ scale: scale }],opacity: alpha,}}/></TouchableOpacity>);
};

獲取路由參數

import { useLocalSearchParams } from "expo-router";
  const params = useLocalSearchParams();const { id } = params;

此種路由參數為路由添加的查詢條件

router.push(`/articleDetail?id=${article.id}`);

代碼實現

app/_layout.tsx

注冊路由

              <Stack.Screenname="articleDetail"options={{ headerShown: false }}/>

app/articleDetail.tsx

文章詳情頁

import Heart from "@/components/Heart";
import { ImageSlider } from "@/components/slidePager";
import AntDesign from "@expo/vector-icons/AntDesign";
import Entypo from "@expo/vector-icons/Entypo";
import EvilIcons from "@expo/vector-icons/EvilIcons";
import dayjs from "dayjs";
import { useLocalSearchParams } from "expo-router";
import { useEffect, useState } from "react";
import {Dimensions,Image,ScrollView,StyleSheet,Text,TextInput,TouchableOpacity,View,
} from "react-native";
export default function Index() {const [height, setHeight] = useState<number>(300);const { width: SCREEN_WIDTH } = Dimensions.get("window");const userInfo = {avatar:"https://gips1.baidu.com/it/u=705524004,2611014536&fm=3074&app=3074&f=PNG?w=2048&h=2048",};const detail = {avatarUrl:"https://img2.baidu.com/it/u=902203086,3868774028&fm=253&app=138&f=JPEG?w=500&h=500",userName: "張三",images: ["https://img0.baidu.com/it/u=1168912228,741609775&fm=253&fmt=auto&app=120&f=JPEG?w=1422&h=800","https://gips3.baidu.com/it/u=1014935733,598223672&fm=3074&app=3074&f=PNG?w=1440&h=2560","https://img0.baidu.com/it/u=2779316202,721068756&fm=253&app=120&f=JPEG?w=1422&h=800",],title: "讓我抱抱,一起溫暖,真的好治愈",desc: "家里雞蛋不知道怎么吃的,可以去試試這個火腿腸炒蛋,\n我媽說居然這么好吃。\n香辣過癮真的忒下飯了,做法雞蛋,你們也去安排起來。",tag: ["每秒都值得記錄", "治愈系", "治愈貓咪"],dateTime: "2023-02-27 12:20",location: "廣東",favoriteCount: 1098,collectionCount: 208,isFavorite: false,isCollection: false,comments: [{userName: "胖胖胖",avatarUrl:"https://img0.baidu.com/it/u=2875122849,1736556673&fm=253&app=138&f=JPEG?w=500&h=500",message:"果斷關注,這個博主做的菜真實色香味俱全。每天跟著學做菜,我要做大廚了,啊哈哈~",dateTime: "2023-02-28 07:23",location: "成都",favoriteCount: 45,isFavorite: false,children: [{userName: "小飛飛愛貓咪",avatarUrl:"https://img2.baidu.com/it/u=1922178401,3519789815&fm=253&app=138&f=JPEG?w=500&h=500",message: "安排起來,這個做法很簡單的哦。",dateTime: "2023-02-28 13:23",location: "廣東",favoriteCount: 1,isFavorite: false,},],},{userName: "左半",avatarUrl:"https://img2.baidu.com/it/u=3118961545,1128223138&fm=253&app=138&f=JPEG?w=500&h=500",message: "看著真有食欲",dateTime: "2023-02-28 09:09",location: "福建",favoriteCount: 2,isFavorite: false,children: undefined,},],};useEffect(() => {if (!detail?.images) {return;}const firstImg = detail?.images[0];Image.getSize(firstImg, (width: number, height: number) => {const showHeight = (SCREEN_WIDTH * height) / width;setHeight(showHeight);});// eslint-disable-next-line react-hooks/exhaustive-deps}, []);const params = useLocalSearchParams();const { id } = params;// 此處省略訪問接口獲取文章詳情console.log(id);const renderImages = () => {const { images } = detail;if (!images?.length) {return null;}const data: any[] = detail.images.map((i) => {return { img: i };});return (<View style={{ paddingBottom: 30 }}><ImageSliderdata={data}autoPlay={false}closeIconColor="white"caroselImageStyle={{ height }}indicatorContainerStyle={{ bottom: -40 }}activeIndicatorStyle={styles.activeDot}inActiveIndicatorStyle={styles.inActiveDot}/></View>);};const renderInfo = () => {const tags = detail.tag?.map((i) => `# ${i}`).join(" ");return (<><Text style={styles.articleTitleTxt}>{detail.title}</Text><Text style={styles.descTxt}>{detail.desc}</Text><Text style={styles.tagsTxt}>{tags}</Text><Text style={styles.timeAndLocationTxt}>{detail.dateTime} {detail.location}</Text><View style={styles.line} /></>);};const renderComments = () => {const count = detail.comments?.length || 0;const styles = StyleSheet.create({commentsCountTxt: {fontSize: 14,color: "#666",marginTop: 20,marginLeft: 16,},inputLayout: {width: "100%",padding: 16,flexDirection: "row",alignItems: "center",},userAvatarImg: {width: 32,height: 32,borderRadius: 16,resizeMode: "cover",},commentInput: {flex: 1,height: 40,borderRadius: 16,marginLeft: 12,backgroundColor: "#f0f0f0",color: "#333",paddingVertical: 4,paddingHorizontal: 12,},commentsContainer: {paddingHorizontal: 16,paddingTop: 16,paddingBottom: 32,},commentItem: {width: "100%",flexDirection: "row",},cAvatar: {width: 36,height: 36,resizeMode: "cover",borderRadius: 18,},contentLayout: {flex: 1,marginHorizontal: 12,},nameTxt: {fontSize: 12,color: "#999",},messageTxt: {fontSize: 14,color: "#333",marginTop: 6,},timeLocationTxt: {fontSize: 12,color: "#bbb",},countLayout: {alignItems: "center",},fCount: {fontSize: 12,color: "#666",marginTop: 2,},divider: {marginLeft: 50,marginRight: 0,height: StyleSheet.hairlineWidth,backgroundColor: "#eee",marginVertical: 16,},});return (<><Text style={styles.commentsCountTxt}>{count ? `共 ${count} 條評論` : "暫無評論"}</Text><View style={styles.inputLayout}><Imagestyle={styles.userAvatarImg}source={{ uri: userInfo.avatar }}/><TextInputstyle={styles.commentInput}placeholder="說點什么吧,萬一火了呢~"placeholderTextColor={"#bbb"}/></View>{!!count && (<View style={styles.commentsContainer}>{detail.comments?.map((i: ArticleComment, index: number) => {return (<View key={`${index}`} style={{}}><View style={styles.commentItem}><Imagestyle={styles.cAvatar}source={{ uri: i.avatarUrl }}/><View style={styles.contentLayout}><Text style={styles.nameTxt}>{i.userName}</Text><Text style={styles.messageTxt}>{i.message}<Text style={styles.timeLocationTxt}>{dayjs(i.dateTime).format("MM-DD")} {i.location}</Text></Text>{!!i.children?.length &&i.children.map((j: ArticleComment, subIndex: number) => {return (<Viewkey={`${index}-${subIndex}`}style={[styles.commentItem,{ marginTop: 12, width: SCREEN_WIDTH - 80 },]}><Imagestyle={[styles.cAvatar,{ width: 32, height: 32 },]}source={{ uri: j.avatarUrl }}/><View style={styles.contentLayout}><Text style={styles.nameTxt}>{j.userName}</Text><Text style={styles.messageTxt}>{j.message}<Text style={styles.timeLocationTxt}>{dayjs(j.dateTime).format("MM-DD")}{" "}{j.location}</Text></Text></View><View style={styles.countLayout}><Heart size={20} value={j.isFavorite} /><Text style={styles.fCount}>{j.favoriteCount}</Text></View></View>);})}</View><View style={styles.countLayout}><Heart size={20} value={i.isFavorite} /><Text style={styles.fCount}>{i.favoriteCount}</Text></View></View><View style={styles.divider} /></View>);})}</View>)}</>);};const renderBottom = () => {return (<View style={styles.bottomLayout}><View style={styles.bottomEditLayout}><AntDesign name="edit" size={20} color="#333" /><TextInputstyle={styles.bottomCommentInput}placeholder="說點什么"placeholderTextColor={"#333"}/></View><Heart size={22} value={detail.isFavorite} color="grey" /><Text style={styles.bottomCount}>{detail.favoriteCount}</Text><AntDesign name="staro" size={22} color="grey" /><Text style={styles.bottomCount}>{detail.collectionCount}</Text><AntDesign name="message1" size={22} color="grey" /><Text style={styles.bottomCount}>{detail.comments?.length || 0}</Text></View>);};return (<View style={styles.page}><View style={styles.topBar}><TouchableOpacityonPress={() => {console.log("返回");}}><Entypo name="chevron-left" size={24} color="black" /></TouchableOpacity><Image style={styles.avatarImg} source={{ uri: detail.avatarUrl }} /><Text style={styles.nameTxt}>{detail.userName}</Text><TouchableOpacityonPress={() => {console.log("關注");}}><Text style={styles.followBtn}>關注</Text></TouchableOpacity><TouchableOpacityonPress={() => {console.log("轉發");}}><EvilIconsstyle={styles.shareIcon}name="external-link"size={32}color="black"/></TouchableOpacity></View><ScrollView showsVerticalScrollIndicator={false}>{renderImages()}{renderInfo()}{renderComments()}</ScrollView>{renderBottom()}</View>);
}
const styles = StyleSheet.create({page: {backgroundColor: "white",width: "100%",height: "100%",},bottomLayout: {width: "100%",height: 64,flexDirection: "row",alignItems: "center",paddingHorizontal: 16,borderTopWidth: 1,borderTopColor: "#eee",},bottomEditLayout: {height: 40,flex: 1,backgroundColor: "#f0f0f0",borderRadius: 20,flexDirection: "row",alignItems: "center",paddingHorizontal: 12,marginRight: 12,},bottomCommentInput: {height: "100%",paddingTop: 6,paddingLeft: 6,color: "#333",textAlignVertical: "center",paddingVertical: 0,},bottomCount: {fontSize: 14,color: "grey",marginLeft: 6,marginRight: 8,},shareIcon: {marginBottom: 4,},articleTitleTxt: {fontSize: 18,color: "#333",fontWeight: "bold",paddingHorizontal: 16,},descTxt: {fontSize: 15,color: "#333",marginTop: 6,paddingHorizontal: 16,},tagsTxt: {fontSize: 15,color: "#305090",marginTop: 6,paddingHorizontal: 16,},timeAndLocationTxt: {fontSize: 12,color: "#bbb",marginVertical: 16,marginLeft: 16,},line: {marginHorizontal: 16,height: StyleSheet.hairlineWidth,backgroundColor: "#eee",},topBar: {flexDirection: "row",alignItems: "center",padding: 10,},avatarImg: {width: 30,height: 30,resizeMode: "cover",borderRadius: 50,margin: 10,},nameTxt: {fontSize: 14,color: "#999",marginLeft: 6,flex: 1,},followBtn: {fontSize: 12,color: "red",borderWidth: 1,borderColor: "red",borderRadius: 10,paddingVertical: 4,paddingHorizontal: 12,marginRight: 10,},activeDot: {width: 6,height: 6,backgroundColor: "#ff2442",borderRadius: 3,},inActiveDot: {width: 6,height: 6,backgroundColor: "#c0c0c0",borderRadius: 3,},
});

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/88662.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/88662.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/88662.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

嗶哩嗶哩第三方TV-BBLL最新版

—————【下 載 地 址】——————— 【?本章下載一】&#xff1a;https://pan.xunlei.com/s/VOUtUcaymd9rpgurgDKS9pswA1?pwdp76n# 【?本章下載二】&#xff1a;https://pan.xunlei.com/s/VOUtUcaymd9rpgurgDKS9pswA1?pwdp76n# 【百款黑科技】&#xff1a;https://uc…

用YOLOv5系列教程(1)-用YOLOv5輕松實現設備狀態智能監控!工業級教程來了

用YOLOv5輕松實現設備狀態智能監控&#xff01;工業級教程來了設備運維革命&#xff1a;15分鐘教會你的攝像頭看懂指示燈狀態工業現場各種設備狀態指示燈是工程師的"眼睛"——紅燈報警、綠燈運行、黃燈待機。但人工巡檢耗時費力&#xff0c;關鍵故障容易漏檢&#xf…

筆記-分布式計算基礎

Distributed Computing 劃分數據并行&#xff08;DataParallelism&#xff09;將數據分為n份&#xff0c;發送到n個GPU上&#xff0c;每個GPU上都存在一個完整的大模型 缺點&#xff1a; 模型太大Pipeline Parallelism&#xff08;串行的&#xff09;將模型做split,每個GPU負責…

Android Studio 2024,小白入門喂飯級教程

一、下載Android Studio 1、從安卓官網安卓官網下載Android Studio。 ? ? 二、安裝Android Studio 1、雙擊android-studio-2024.3.2.15-windows.exe。 ? ?? ? ? ? ? 三、新建工程 1、雙擊桌面圖標? 打開Android Studio。 ? 選“Empty Views Activity…

AI智能體 | 使用Coze制作一鍵生成單詞洗腦循環視頻,一天批量生成100條視頻不是夢!(附保姆級教程)

目錄 一、整體工作流設計 二、制作工作流 2.1 開始節點 2.2 大模型-單詞 2.3 大模型_圖像生成 2.4 輸出 2.5 圖像生成_1 2.6 輸出_2 2.7 畫板_2 2.8 文本處理 2.9 輸出_3 2.10 speech_synthesis_1x5 2.11 get_audio_duration_1 2.12 代碼 2.13 get_audio_durati…

質量屬性場景(Quality Attribute Scenario)深度解析

本質定義:質量屬性場景(Quality Attribute Scenario)是精確描述軟件系統質量要求的結構化方法,通過標準化的場景模板將抽象的質量屬性轉化為可測量、可驗證的具體行為描述,為架構設計提供客觀評估基準。 一、質量屬性場景核心結構 1. 六元組標準模板 #mermaid-svg-AGbvPVRu…

Java_Springboot技術框架講解部分(一)

首先講解一下&#xff1a;Java技術棧中&#xff0c;目前Spring Boot在國內的關注趨勢也日漸超過Spring。Spring Boot是Spring家族中的一個全新的框架&#xff0c;它用來簡化Spring應用程序的創建和開發過程。采用Spring Boot可以非常容易和快速的構建基于Spring框架的應用程序&…

從OpenMV到執行器:當PID算法開始“調教”舵機

如果到現在還不會驅動舵機——朋友&#xff0c;電賽的元器件清單每年都在對你“明示”&#xff0c;二維云臺都快成祖傳考題了&#xff01;補課&#xff1f;現在&#xff01;立刻&#xff01;&#xff08;當然&#xff0c;如果你臉皮夠厚&#xff0c;也可以私信騷擾作者&#xf…

xml映射文件的方式操作mybatis

映射文件 在Java spring中使用mybatis有兩種方式&#xff0c;一種是注釋的方式&#xff0c;一種是xml映射文件的方式。在簡單的功能需求可以使用注釋&#xff0c;方便簡潔。而在大的功能邏輯上&#xff0c;更推薦使用xml映射文件&#xff0c;方便管理且結構清晰。 首先xml文件結…

Carla自動駕駛仿真_快速安裝與運行Carla

大家好&#xff0c;我是橙子&#xff0c;今天給大家介紹Carla的基礎安裝和使用 目錄 1.Carla介紹 2.Carla的安裝與使用 3.Carla0.9.15安裝包下載&#xff1a; ?編輯 4.運行Demo 5.運行一個簡單場景&#xff1a; 6.相關資源 1.Carla介紹 Carla 是一個開源的自動駕駛仿…

遠程登錄docker執行shell報錯input is not a terminal問題

背景 最近要遠程去k8s docker里面獲取信息&#xff0c;于是&#xff0c;寫了一個如下的命令&#xff0c;執行完之后&#xff0c;報錯了。 ssh 192.168.100.2 sudo crictl exec -it xxx.docker /usr/bin/lscpu --online --extended錯誤信息如下&#xff1a; time“2025-07-11T21…

使用FastAdmin框架開發二

繼上一篇使用FastAdmin框架開發-CSDN博客教程 部署完項目后我們就可以邊開發邊調試了 在開發前我們可以先做一些基本設置 安裝成功后會生成一個項目后臺的地址http://域名/VrHGtzlfMB.php/index/login&#xff0c;后臺入口文件是隨機生成的&#xff0c;當然我們也可以根據我…

【DB2】load報錯SQL3501W、SQL3109N、SQL2036N

最近老遇到遷移測試LOAD時報錯&#xff0c;如圖所示但是換成import又可以看描述是說load的內容將不會進入備份暫掛狀態balbala… 下面的錯誤是說ixf文件無效 這里一直以為是SQL3501W的問題&#xff0c;去各種研究load參數和db2set里面的load參數&#xff0c;各種調整都不行 又以…

YOLO家族內戰!v5/v8/v10誰才是你的真命天子?(附保姆級選擇指南)

在目標檢測領域&#xff0c;YOLO系列始終是工業部署與學術研究的焦點。從風靡全網的YOLOv5&#xff0c;到全面升級的YOLOv8&#xff0c;再到突破性能瓶頸的YOLOv10——每一次迭代都帶來全新可能。作為開發者&#xff0c;究竟該選哪一代&#xff1f;本文用千字長文對比表格為你徹…

Claude Code是什么?國內如何使用到Claude Code?附國內最新使用教程

2025年已過大半&#xff0c;相信你也聽說過 Claude——它是近年最受關注的 AI 模型之一&#xff0c;而 Claude Code 則是它面向編程場景的特別版本&#xff0c;專為代碼理解、生成與重構而生&#xff0c;尤其擅長處理大項目、長上下文&#xff0c;和開發者對話更自然。 但對于一…

雙輪驅動:政策激勵與外部制約下的國產服務器市場演進

2025年6月&#xff0c;科智咨詢正式發布《中國國產服務器市場研究報告&#xff08;2025&#xff09;》&#xff0c;報告從國產服務器產業概述、政策環境分析、市場現狀與競爭格局、面臨挑戰與市場機遇等維度&#xff0c;深入剖析國產服務器市場現狀及未來發展趨勢。2022年10月&…

【工具變量】全國省市區縣土地出讓結果公告數據(2000-2024年)

土地出讓結果公告數據是指政府主管部門在完成國有土地使用權出讓后&#xff0c;依法依規對外公開的結果信息&#xff0c;涵蓋土地出讓時間、出讓方式、競得人、成交價、用地性質、面積等關鍵信息。土地出讓數據是研究中國土地市場供需變化、城市發展軌跡以及地方財政收入結構的…

前端面試專欄-算法篇:22.樹結構(二叉樹、B樹、紅黑樹)

&#x1f525; 歡迎來到前端面試通關指南專欄&#xff01;從js精講到框架到實戰&#xff0c;漸進系統化學習&#xff0c;堅持解鎖新技能&#xff0c;祝你輕松拿下心儀offer。 前端面試通關指南專欄主頁 前端面試專欄規劃詳情 樹結構&#xff08;二叉樹、B樹、紅黑樹&#xff09…

爬蟲-數據解析

1.解析概述特性re (正則表達式)bs4 (BeautifulSoup)xpath (lxml)pyquery本質文本模式匹配HTML/XML 解析器 (DOM樹操作)XML路徑語言 (節點導航)jQuery 式 CSS 選擇器 (封裝lxml)學習曲線陡峭中等中等簡單 (熟悉jQuery/CSS)靈活性極高 (處理任意文本)高 (容錯好&#xff0c;DOM操…

MySQL8.0基于GTID的組復制分布式集群的環境部署

前言&#xff1a; 需要清楚知道&#xff1a;MySQL 復制組能夠以一種自動優先選擇的單主模式運行&#xff0c;在某個時間只有一個服務器接受更新 。但是對于更高優先級的用戶&#xff0c;組能夠以多主模式部署&#xff0c;所有的服務器都能夠接受更新&#xff0c;即使它們是同時…