react-native仿京东首页搜索栏联动效果

效果截图
这个效果在前几年一直没有思路实现,网上的资料也很少,甚至没有,实现过程中最多想到的就是在滚动的时候去setNativeProps,但是在弄的过程中总会出现布局抖动,而且抖动特别明显,几乎不可用,随着rn的更新迭代,也随之出现了很多性能较好的动画库,这个效果今天在闲鱼时间拿出来再做一次,它变得如此容易了。

必备第三方库:react-native-reanimated

效果简述:

布局下方是滚动区,上方看做一个headerBar,滚动的过程中 headerBar是固定的且随滚动距离变化高度,且搜索栏会伸缩向上。

我试过这样做:

	<View>
		<View>
		{
    
    /*headerBar*/}
		</View>
		{
    
    /*scroll*/}
		<ScrollView>
		</ScrollView>
	</View>

我的一次次尝试告诉我这样是不可以的,我通过ScrollView onScroll回调 其中配合使用了动画库reanimated的强大hook useAnimatedScrollHandler,依然做出来效果不堪入目,抖动剧烈。

那怎么办? 换思路? 固定区域不放外面,放哪? 放scrollView? 回想,放进去也不是固定不了,想想上一篇仿飞猪效果不也是放滚动区内部了?撸起袖子干!!!

我的实现与尝试:

在这里插入图片描述
首先把这个view在滚动的时候固定住,我这里添加了zIndex , 因为我在调试过程中,发现后渲染的layout层级高于前置渲染layout,会覆盖,做成了飞猪布局,这里很简单 我们调整下层级就ok了。

然后就是处理我们的headerBar,先看下图

在这里插入图片描述
我圈住的部分就是headerBar,这里我们把搜索栏 放置在跟headerBar同一级下,接下来,在滚动的时候,需要做3件事

  1. 调整searchBar的宽度与高度,并且加阻尼
  2. 调整headerBar的高度,加阻尼
  3. 超值判断,headerBar最小高度应该等值与一个searchbar的高度,searchbar的最小宽度应该等于 屏幕宽度减去右边layout的宽度且减去其自身的边距值。

注意⚠️:这里我们需要设置父级alignItems:
“flex-start”,这样你在变化宽度的时候,searchbar就是按照父级的约束去改变,android中是通过约束布局去对左右相对约束去做的,我们rn目前只能这样子做,相对来说,android更加规范!!!

贴代码:

const JdScrollPage = props => {
    
    

  const {
    
     width } = useWindowDimensions();
  const translationY = useSharedValue(0);
  const maxWid = width - 100 - 20;

  const scrollHandler = useAnimatedScrollHandler((event) => {
    
    
    translationY.value = event.contentOffset.y;
  }, []);

  const headerViewAni = useAnimatedStyle(() => {
    
    
    const val = width - 20 - translationY.value;
    return {
    
    
      width: (val <= maxWid) ? maxWid : val,
    };
  }, []);

  const fixedView = useAnimatedStyle(() => {
    
    
    return {
    
    
      transform: [
        {
    
    
          translateY: translationY.value,
        },
      ],
    };
  });

  const parentBlackView = useAnimatedStyle(() => {
    
    
    const val = 100 - translationY.value / 8;
    return {
    
    

      height: val <= 50 ? 50 : val,
    };
  });

  return (
    <View style={
    
    {
    
     flex: 1 }}>


      <Animated.ScrollView onScroll={
    
    scrollHandler}>

        <Animated.View style={
    
    [{
    
     alignItems: "flex-start",zIndex:10 }, fixedView]}>

          <Animated.View style={
    
    [styles.headerLayout, parentBlackView]}>

            <View style={
    
    styles.logoLayout}>
              <Image source={
    
    require('./logo.jpg')} style={
    
    styles.logoPic} resizeMode={
    
    "contain"}/>
            </View>

            <View style={
    
    styles.rightLayout}>
              <Text>this is layout</Text>
            </View>

          </Animated.View>

          {
    
    /*search bar*/}
          <Animated.View style={
    
    [styles.search,{
    
    width:width-20}, headerViewAni]}>
            <Text>请输入搜索内容</Text>
          </Animated.View>

        </Animated.View>

        {
    
    /*scroll content*/}
        <View style={
    
    {
    
     backgroundColor: "#ccc", height: 80 }}>
          <Text>hello1</Text>
        </View>
        <View style={
    
    {
    
     backgroundColor: "#ccc", height: 80 }}>
          <Text>hello</Text>
        </View>
        <View style={
    
    {
    
     backgroundColor: "#ccc", height: 80 }}>
          <Text>hello</Text>
        </View>
        
      </Animated.ScrollView>


    </View>
  );
};

如果想改成,美团,拼多多的那种搜索栏效果,我们只需要把
在这里插入图片描述
alignItem:“flex-start” 改成“center”,就可以实现基本一致的效果,你可以根据实际需求稍加调整,就可以完美实现这个交互效果了

最后在贴上github地址:点击这里查看demo 分支切换到:jdExample

怎么样,rn现在去做这些东西还是比较简单的吧,欢迎小伙伴们给我留言评论,互相学习!

猜你喜欢

转载自blog.csdn.net/qq_37399372/article/details/122289342