下拉刷新/点击首页刷新

50 阅读2分钟

1.shuffle函数模拟刷新后的状态

项目中通过随机打乱帖子的顺序来模拟刷新后的状态

function shuffle(arr: any[]) {
    const a = arr.slice();
    for (let i = a.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [a[i], a[j]] = [a[j], a[i]];
    }
    return a;
  }

2.下拉刷新实现

@react-native-seoul/masonry-list 是基于 React Native 的 ScrollView 扩展实现的,它的设计目标是提供类似于 FlatList 的开发体验。正如搜索结果中提到的:"Current MasonryList extends ScrollView and can pass down its props."。看到的下拉旋转箭头实际上是 Android 系统对可滚动视图的默认行为,这是 Android 中内置的下拉刷新指示器。在 React Native 中,这通常通过 RefreshControl 组件来控制,它可以添加到 ScrollView、FlatList 或其他可滚动组件中。

在HomeScreen.tsx 代码中,虽然没有明确配置 refreshControl 属性,但由于 MasonryList 是基于 ScrollView 的,它继承了 ScrollView 的默认行为,包括在某些 Android 设备上显示下拉指示器。如果您想要自定义这个行为,您可以为 MasonryList 添加 refreshControl 等属性。

const [refreshing, setRefreshing] = useState(false);

// 处理刷新的函数
  const onRefresh = React.useCallback(() => {
    setRefreshing(true);
    setTimeout(() => {
      setPosts(prev => shuffle(prev));
      setRefreshing(false);
    }, 1000);
  }, []);
  
<MasonryList
  innerRef={scrollRef}
  data={posts}
  keyExtractor={(item: Post) => item.id.toString()}
  numColumns={2}
  contentContainerStyle={styles.content}
  showsVerticalScrollIndicator={true}
  refreshing={refreshing}
  onRefresh={onRefresh}
  refreshControl={true} // 启用刷新控件
  refreshControlProps={{
    colors: [COLORS.primary], // Android 上的颜色
    tintColor: COLORS.primary, // iOS 上的颜色
  }}
  ...
/>
  • refreshing={refreshing}: 控制刷新状态
  • onRefresh={onRefresh}: 设置刷新回调函数
  • refreshControl={true}: 启用刷新控件
  • refreshControlProps={{...}}: 配置刷新控件的样式和行为

这样就实现了,是不是很丝滑

下拉刷新.gif

3.点击首页刷新

如果当前在首页,然后再次点击了底部的首页导航标签,那么内容区域会回到顶部然后刷新页面

新增LoadingSpinner组件:

import React from 'react';
import { View, ActivityIndicator, StyleSheet } from 'react-native';

export default function LoadingSpinner() {
  return (
    <View style={styles.overlay}>
      <ActivityIndicator size="large" color="#ff69b4" />
    </View>
  );
}

const styles = StyleSheet.create({
  overlay: {
    ...StyleSheet.absoluteFillObject,
    backgroundColor: 'rgba(255,255,255,0.5)',
    justifyContent: 'center',
    alignItems: 'center',
    zIndex: 999,
  },
});

这里针对web端使用 DOM API (document.querySelector) 来获取元素并调用其 scrollTo 方法,而不是使用 React Native 的 ref。

const scrollRef = useRef<ScrollView | undefined>(undefined);
const [loading, setLoading] = useState(false);

const handleHomeTab = () => {
    if (Platform.OS === 'web') {
      const scrollEl = document.querySelector('.masonry-scroll-top');
      if (scrollEl) (scrollEl as HTMLElement).scrollTo(0, 0);
    } else if (scrollRef.current) {
      // 直接使用 ScrollView 的 scrollTo 方法
      scrollRef.current.scrollTo({ y: 0, animated: true });
    }
    setLoading(true);
    setTimeout(() => {
      setPosts(prev => shuffle(prev));
      setLoading(false);
    }, 1000);
  };
  
  <MasonryList
  innerRef={scrollRef}
  data={posts}
  keyExtractor={(item: Post) => item.id.toString()}
  numColumns={2}
  contentContainerStyle={styles.content}
  showsVerticalScrollIndicator={true}
  refreshing={refreshing}
  onRefresh={onRefresh}
  refreshControl={true} // 启用刷新控件
  refreshControlProps={{
    colors: [COLORS.primary], // Android 上的颜色
    tintColor: COLORS.primary, // iOS 上的颜色
  }}
  ...
/>
{loading && <LoadingSpinner />}
点击首页刷新.gif

项目地址如下,欢迎关注:github.com/ggbond11/pi…