真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

react-native滑動(dòng)吸頂效果的實(shí)現(xiàn)過(guò)程

前言

讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來(lái)自于我們對(duì)這個(gè)行業(yè)的熱愛(ài)。我們立志把好的技術(shù)通過(guò)有效、簡(jiǎn)單的方式提供給客戶,將通過(guò)不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:域名注冊(cè)、虛擬空間、營(yíng)銷軟件、網(wǎng)站建設(shè)、崇仁網(wǎng)站維護(hù)、網(wǎng)站推廣。

最近公司開(kāi)發(fā)方向偏向移動(dòng)端,于是就被調(diào)去做RN(react-native),體驗(yàn)還不錯(cuò),當(dāng)前有個(gè)需求是首頁(yè)中間吸頂?shù)男Ч?,雖然已經(jīng)很久沒(méi)寫(xiě)樣式了,不過(guò)這種常見(jiàn)樣式應(yīng)該是so-easy,沒(méi)成想翻車了,網(wǎng)上搜索換了幾個(gè)方案都不行,最后去github上復(fù)制封裝好的庫(kù)來(lái)實(shí)現(xiàn),現(xiàn)在把翻車過(guò)程記錄下來(lái)。

需求效果

react-native滑動(dòng)吸頂效果的實(shí)現(xiàn)過(guò)程

翻車過(guò)程

第一種方案 失敗

一開(kāi)始的思路是這樣的,大眾思路,我們需要監(jiān)聽(tīng)頁(yè)面的滾動(dòng)狀態(tài),當(dāng)頁(yè)面滾動(dòng)到要吸頂元素所處的位置的時(shí)候,我們?cè)O(shè)置它為固定定位,不過(guò)很遺憾,RN對(duì)于position屬性只提供了兩種布局方式:absolute和relative,既沒(méi)有fixed也沒(méi)有仍處于試驗(yàn)的api:sticky。尷尬了😅

第二種方案 失敗

不過(guò)也不慌,看網(wǎng)上有第二種方案,把圖上第二 三塊地方作為ScrollView,然后ScrollView滑動(dòng)監(jiān)聽(tīng)距離,把第一塊的marginTop設(shè)為負(fù)值,但是這樣第一部分不能滑動(dòng),不符合需求,pass

第三種方案 完全失敗

從網(wǎng)上找到第三種方案,就是一二三部分作為ScrollView,

第一部分position設(shè)為absolute,剩下的不設(shè)置,默認(rèn)是relative

第二部分(吸頂部分)marginTop設(shè)置(setState)為第一部分高度的state,

添加滑動(dòng)onScroll事件=》滑動(dòng)距離y等于第二部分marginTop的state,但是當(dāng)滑動(dòng)超過(guò)第一部分高度的時(shí)候把第二部分(吸頂部分)position設(shè)為absolute,并把其marginTop設(shè)為0,看起來(lái)不錯(cuò),實(shí)際用ios模擬器一跑就無(wú)語(yǔ)了😅,效果很奇葩,手指滑動(dòng)時(shí)不吸頂直接劃上去隱藏掉大半,一松突然吸頂了。。。

見(jiàn)下圖

react-native滑動(dòng)吸頂效果的實(shí)現(xiàn)過(guò)程

ios的系統(tǒng),手指在屏幕上滾動(dòng)時(shí),onScroll一直在觸發(fā),如果里面有setState方法,也會(huì)不停執(zhí)行并計(jì)算state,但是改變r(jià)eact的state是異步的,只要手指不離開(kāi)屏幕,改變的state就無(wú)法生效(觸發(fā)界面渲染)

實(shí)現(xiàn)方案

我最終意識(shí)到由于ios的機(jī)制,react的state機(jī)制不能滿足需求,RN里面肯定有借助原生渲染的方式,于是github找了現(xiàn)成的代碼實(shí)現(xiàn)之后,反過(guò)來(lái)進(jìn)行研究,大家有RN豐富經(jīng)驗(yàn)的也可以直接看最下面代碼👇

RN的Animator

RN的Animator動(dòng)畫(huà)庫(kù)旨在解決動(dòng)畫(huà)問(wèn)題,由于js橋接過(guò)程,動(dòng)畫(huà)通常不能很好展現(xiàn),最好是把動(dòng)畫(huà)的 數(shù)據(jù) 和 變化方法 一次性發(fā)給原生,由原生進(jìn)行處理,這就是Animator庫(kù)的核心作用。

記得原來(lái)RN的動(dòng)畫(huà)一直被吐槽,不過(guò)現(xiàn)在效果還挺不錯(cuò)的,可能與近年來(lái)手機(jī)硬件提升也越來(lái)越大也有關(guān)系吧。

簡(jiǎn)單用法

由于Animator內(nèi)部封裝了這四個(gè)組件,所以默認(rèn)可以導(dǎo)出,,,

在這幾個(gè)組件里面想做一些動(dòng)畫(huà)處理,數(shù)據(jù)方面也是react的state,但是賦值要給Animated.Value,如下👇

this.state = {
  scrollY: new Animated.Value(0)
}

這里雖然使用的還是原生state,但是經(jīng)過(guò)Animated處理,渲染機(jī)制完全不一樣了

簡(jiǎn)單原理

經(jīng)過(guò)Animator包裝后的組件,會(huì)遍歷傳入的props和自身的state,查找是否有Animated.Value的實(shí)例,并綁定進(jìn)相應(yīng)的原生操作。

props和自身的state變化時(shí),將Animated.Value值逐個(gè)轉(zhuǎn)化為普通數(shù)值,再交給原生進(jìn)行渲染,但是值得注意的是,這里并不會(huì)觸發(fā)react 的 render,更不會(huì)有什么domdiff ,是一種特殊處理,類似于Animated.Value改變時(shí)每次的shouldUpdateComponent返回都是false(毫秒級(jí)的渲染react性能扛不?。?,shouldUpdateComponent函數(shù)里面判斷Animated.Value,然后會(huì)把數(shù)據(jù)變化發(fā)給原生組件

完整的介紹請(qǐng)移步中文官網(wǎng)Animator庫(kù)介紹

實(shí)現(xiàn)思路

既然用了Animator組件了,渲染的問(wèn)題解決了,下面思路是動(dòng)態(tài)設(shè)置吸頂組件的translateY屬性。style:{ transform: [{ translateY:translateY }] }

  • 當(dāng)向下滑動(dòng)時(shí),不管它
  • 向上滑,但是當(dāng)頭部還沒(méi)有完全隱藏時(shí),也不管它
  • 向上滑,頭部完全不見(jiàn)了,這時(shí)向上再滑一點(diǎn),那么他的translateY就應(yīng)該 = 上劃總距離 - 頭部高度,這樣越往上滑,把吸頂組件使勁往下推,這樣吸頂組件就牢牢固定在頂部了

下面利用插值來(lái)實(shí)現(xiàn)

const translateY = ScrollY.interpolate({
  inputRange: [-1, 0, headerHeight, headerHeight + 1],
  outputRange: [0, 0, 0, 1],
});

插值interpolate略難理解,需要一點(diǎn)基礎(chǔ),這里再細(xì)說(shuō)起來(lái)這篇文章就太長(zhǎng)了官網(wǎng)介紹,

如果還不懂可以去網(wǎng)上找找這方面的資料

實(shí)現(xiàn)源碼

實(shí)現(xiàn)的圖中第二部分吸頂功能的核心代碼

import * as React from 'react';
import { StyleSheet, Animated } from "react-native";

/**
 * 滑動(dòng)吸頂效果組件
 * @export
 * @class StickyHeader
 */
export default class StickyHeader extends React.Component{

  static defaultProps = {
    stickyHeaderY: -1,
    stickyScrollY: new Animated.Value(0)
  }
  
  constructor(props) {
    super(props);
    this.state = {
      stickyLayoutY: 0,
    };
  }
  // 兼容代碼,防止沒(méi)有傳頭部高度
  _onLayout = (event) => {
    this.setState({
      stickyLayoutY: event.nativeEvent.layout.y,
    });
  }

  render() {
    const { stickyHeaderY, stickyScrollY, children, style } = this.props
    const { stickyLayoutY } = this.state
    let y = stickyHeaderY != -1 ? stickyHeaderY : stickyLayoutY;
    const translateY = stickyScrollY.interpolate({
      inputRange: [-1, 0, y, y + 1],
      outputRange: [0, 0, 0, 1],
    });
    return (
      

      { children }

      
    )
  }
}

const styles = StyleSheet.create({
  container: {
    zIndex: 100
  },
});

頁(yè)面里實(shí)際用法如下

// 在頁(yè)面constructor里聲明state
this.state = {
  scrollY: new Animated.Value(0),
  headHeight:-1
};


   {
    let { height } = e.nativeEvent.layout;
    this.setState({ headHeight: height }); // 給頭部高度賦值
  }}>
    // 里面放入第一部分組件
  
  
  
    // 里面放入第二部分組件
  
  
  // 這是第三部分的列表組件
   this._createListItem(item)}
  />
  

收尾

具體代碼就是這樣實(shí)現(xiàn)了,算是比較完美的方案,特別是照顧了性能,各位可以基于這個(gè)封裝來(lái)實(shí)現(xiàn)更復(fù)雜的需求,原理大概就是這個(gè)原理了,在前端動(dòng)畫(huà)領(lǐng)域,自己確實(shí)也就剛?cè)腴T(mén)水平,如有問(wèn)題,請(qǐng)直接指出。

另外,這是我找的那個(gè) 組件 github的代碼地址:https://github.com/jiasongs/react-native-stickyheader,原地址附上,建議如果項(xiàng)目用了給人家一個(gè)star

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)創(chuàng)新互聯(lián)的支持。


新聞名稱:react-native滑動(dòng)吸頂效果的實(shí)現(xiàn)過(guò)程
地址分享:http://weahome.cn/article/igggio.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部