@@ -5,14 +5,17 @@ import useInnerProps, { getCustomEvent } from './getInnerListeners'
55import { extendObject , useLayout , useTransformStyle , GestureHandler , flatGesture } from './utils'
66interface ListItem {
77 isSectionHeader ?: boolean ;
8+ isSectionFooter ?: boolean ;
89 _originalItemIndex ?: number ;
910 [ key : string ] : any ;
1011}
1112
1213interface Section {
1314 headerData : ListItem | null ;
15+ footerData : ListItem | null ;
1416 data : ListItem [ ] ;
1517 hasSectionHeader ?: boolean ;
18+ hasSectionFooter ?: boolean ;
1619 _originalItemIndex ?: number ;
1720}
1821
@@ -32,13 +35,15 @@ interface SectionListProps {
3235 style ?: Record < string , any > ;
3336 itemHeight ?: ItemHeightType ;
3437 sectionHeaderHeight ?: ItemHeightType ;
38+ sectionFooterHeight ?: ItemHeightType ;
3539 listHeaderData ?: any ;
3640 listHeaderHeight ?: ItemHeightType ;
3741 useListHeader ?: boolean ;
3842 listFooterData ?: any ;
3943 useListFooter ?: boolean ;
4044 'genericrecycle-item' ?: string ;
4145 'genericsection-header' ?: string ;
46+ 'genericsection-footer' ?: string ;
4247 'genericlist-header' ?: string ;
4348 'genericlist-footer' ?: string ;
4449 'enable-var' ?: boolean ;
@@ -91,13 +96,15 @@ const _SectionList = forwardRef<any, SectionListProps>((props = {}, ref) => {
9196 style = { } ,
9297 itemHeight = { } ,
9398 sectionHeaderHeight = { } ,
99+ sectionFooterHeight = { } ,
94100 listHeaderHeight = { } ,
95101 listHeaderData = null ,
96102 useListHeader = false ,
97103 listFooterData = null ,
98104 useListFooter = false ,
99105 'genericrecycle-item' : genericrecycleItem ,
100106 'genericsection-header' : genericsectionHeader ,
107+ 'genericsection-footer' : genericsectionFooter ,
101108 'genericlist-header' : genericListHeader ,
102109 'genericlist-footer' : genericListFooter ,
103110 'enable-var' : enableVar ,
@@ -120,7 +127,6 @@ const _SectionList = forwardRef<any, SectionListProps>((props = {}, ref) => {
120127 const scrollViewRef = useRef < any > ( null )
121128 const sectionListGestureRef = useRef < any > ( )
122129
123-
124130 const indexMap = useRef < { [ key : string ] : string | number } > ( { } )
125131
126132 const reverseIndexMap = useRef < { [ key : string ] : number } > ( { } )
@@ -164,7 +170,7 @@ const _SectionList = forwardRef<any, SectionListProps>((props = {}, ref) => {
164170 }
165171
166172 // 通过sectionIndex和rowIndex获取原始索引
167- const getOriginalIndex = ( sectionIndex : number , rowIndex : number | 'header' ) : number => {
173+ const getOriginalIndex = ( sectionIndex : number , rowIndex : number | 'header' | 'footer' ) : number => {
168174 const key = `${ sectionIndex } _${ rowIndex } `
169175 return reverseIndexMap . current [ key ] ?? - 1 // 如果找不到,返回-1
170176 }
@@ -174,9 +180,15 @@ const _SectionList = forwardRef<any, SectionListProps>((props = {}, ref) => {
174180 // 通过索引映射表快速定位位置
175181 const position = indexMap . current [ index ]
176182 const [ sectionIndex , itemIndex ] = ( position as string ) . split ( '_' )
183+ const targetSectionIndex = Number ( sectionIndex ) || 0
184+ const targetItemIndex = itemIndex === 'header'
185+ ? 0
186+ : itemIndex === 'footer'
187+ ? convertedListData [ targetSectionIndex ] . data . length + 1
188+ : Number ( itemIndex ) + 1
177189 scrollViewRef . current . scrollToLocation ?.( {
178- itemIndex : itemIndex === 'header' ? 0 : Number ( itemIndex ) + 1 ,
179- sectionIndex : Number ( sectionIndex ) || 0 ,
190+ itemIndex : targetItemIndex ,
191+ sectionIndex : targetSectionIndex ,
180192 animated,
181193 viewOffset,
182194 viewPosition
@@ -211,6 +223,19 @@ const _SectionList = forwardRef<any, SectionListProps>((props = {}, ref) => {
211223 }
212224 }
213225
226+ const getSectionFooterHeight = ( { sectionIndex } : { sectionIndex : number } ) => {
227+ const item = convertedListData [ sectionIndex ]
228+ const { hasSectionFooter } = item
229+ // 使用getOriginalIndex获取原始索引
230+ const originalIndex = getOriginalIndex ( sectionIndex , 'footer' )
231+ if ( ! hasSectionFooter ) return 0
232+ if ( ( sectionFooterHeight as ItemHeightType ) . getter ) {
233+ return ( sectionFooterHeight as ItemHeightType ) . getter ?.( item , originalIndex ) || 0
234+ } else {
235+ return ( sectionFooterHeight as ItemHeightType ) . value || 0
236+ }
237+ }
238+
214239 const convertedListData = useMemo ( ( ) => {
215240 const sections : Section [ ] = [ ]
216241 let currentSection : Section | null = null
@@ -233,23 +258,48 @@ const _SectionList = forwardRef<any, SectionListProps>((props = {}, ref) => {
233258 // 创建新的 section
234259 currentSection = {
235260 headerData : item ,
261+ footerData : null ,
236262 data : [ ] ,
237263 hasSectionHeader : true ,
264+ hasSectionFooter : false ,
238265 _originalItemIndex : index
239266 }
240267 // 为 section header 添加索引映射
241268 const sectionIndex = sections . length
242269 indexMap . current [ index ] = `${ sectionIndex } _header`
243270 // 添加反向索引映射
244271 reverseIndexMap . current [ `${ sectionIndex } _header` ] = index
272+ } else if ( item . isSectionFooter ) {
273+ // 如果没有当前 section,创建一个默认的
274+ if ( ! currentSection ) {
275+ // 创建默认section (无header的section)
276+ currentSection = {
277+ headerData : null ,
278+ footerData : null ,
279+ data : [ ] ,
280+ hasSectionHeader : false ,
281+ hasSectionFooter : false ,
282+ _originalItemIndex : - 1
283+ }
284+ }
285+ const sectionIndex = sections . length
286+ currentSection . footerData = item
287+ currentSection . hasSectionFooter = true
288+ indexMap . current [ index ] = `${ sectionIndex } _footer`
289+ // 添加反向索引映射
290+ reverseIndexMap . current [ `${ sectionIndex } _footer` ] = index
291+ sections . push ( currentSection )
292+ currentSection = null
245293 } else {
246294 // 如果没有当前 section,创建一个默认的
247295 if ( ! currentSection ) {
248296 // 创建默认section (无header的section)
249297 currentSection = {
250298 headerData : null ,
299+ footerData : null ,
251300 data : [ ] ,
252301 hasSectionHeader : false ,
302+ hasSectionFooter : false ,
253303 _originalItemIndex : - 1
254304 }
255305 }
@@ -313,17 +363,19 @@ const _SectionList = forwardRef<any, SectionListProps>((props = {}, ref) => {
313363
314364 // 添加该 section 尾部位置信息
315365 // 因为即使 sectionList 没传 renderSectionFooter,getItemLayout 中的 index 的计算也会包含尾部节点
366+ const footerHeight = getSectionFooterHeight ( { sectionIndex } )
316367 layouts . push ( {
317- length : 0 ,
368+ length : footerHeight ,
318369 offset,
319370 index : layouts . length
320371 } )
372+ offset += footerHeight
321373 } )
322374 return {
323375 itemLayouts : layouts ,
324376 getItemLayout : ( data : any , index : number ) => layouts [ index ]
325377 }
326- } , [ convertedListData , useListHeader , itemHeight . value , itemHeight . getter , sectionHeaderHeight . value , sectionHeaderHeight . getter , listHeaderHeight . value , listHeaderHeight . getter ] )
378+ } , [ convertedListData , useListHeader , itemHeight . value , itemHeight . getter , sectionHeaderHeight . value , sectionHeaderHeight . getter , sectionFooterHeight . value , sectionFooterHeight . getter , listHeaderHeight . value , listHeaderHeight . getter ] )
327379
328380 const scrollAdditionalProps = extendObject (
329381 {
@@ -413,6 +465,18 @@ const _SectionList = forwardRef<any, SectionListProps>((props = {}, ref) => {
413465 [ generichash , genericsectionHeader ]
414466 )
415467
468+ const renderSectionFooter = useMemo (
469+ ( ) => {
470+ const SectionFooterComponent = getGeneric ( generichash , genericsectionFooter )
471+ if ( ! SectionFooterComponent ) return undefined
472+ return ( sectionData : { section : Section } ) => {
473+ if ( ! sectionData . section . hasSectionFooter ) return null
474+ return createElement ( SectionFooterComponent , { itemData : sectionData . section . footerData } )
475+ }
476+ } ,
477+ [ generichash , genericsectionFooter ]
478+ )
479+
416480 const ListHeaderComponent = useMemo (
417481 ( ) => {
418482 if ( ! useListHeader ) return null
@@ -447,6 +511,7 @@ const _SectionList = forwardRef<any, SectionListProps>((props = {}, ref) => {
447511 ListHeaderComponent : useListHeader ? ListHeaderComponent : null ,
448512 ListFooterComponent : useListFooter ? ListFooterComponent : null ,
449513 renderSectionHeader : renderSectionHeader ,
514+ renderSectionFooter : renderSectionFooter ,
450515 refreshControl : refresherEnabled
451516 ? createElement ( RefreshControl , {
452517 onRefresh : onRefresh ,
0 commit comments