Flutter ViewPage滑動速度調(diào)整

做flutter技術(shù)已經(jīng)有小半年了寨昙,最近在使用Flutter自帶的ViewPage組件面哥,滑動效果有一絲絲微妙感。最后收尾效果是物理線形的彈簧的效果(就這么奇葩)毅待。

先給大家感受一下原有的ViewPage效果吧。


原pageView實現(xiàn)效果.gif

關(guān)于修改這個動畫效果的參考資料很少归榕。今天簡單說一下修改方式:
flutter動畫基本上分為兩大派系:補(bǔ)間動畫 和 物理動畫(比如失重尸红、超重、動量守恒)。我就不展開說了外里,這個參考資料應(yīng)該很多怎爵。

源碼探索

從physics屬性開始找起,它是一個控制物理動畫的組件:

page_view.data
class _PageViewState extends State<PageView> {
...
Widget build(BuildContext context) {
  final AxisDirection axisDirection = _getDirection(context);
  final ScrollPhysics physics = _ForceImplicitScrollPhysics(
    allowImplicitScrolling: widget.allowImplicitScrolling,
  ).applyTo(widget.pageSnapping
      ? _kPagePhysics.applyTo(widget.physics)
      : widget.physics);
...
}

從這里看出盅蝗,如果不設(shè)置pageSnapping的話_kPagePhysics就是viewpage動畫的實現(xiàn)類鳖链。再往下找:

const PageScrollPhysics _kPagePhysics = PageScrollPhysics();
/// Scroll physics used by a [PageView].
///
/// These physics cause the page view to snap to page boundaries.
///
/// See also:
///
///  * [ScrollPhysics], the base class which defines the API for scrolling
///    physics.
///  * [PageView.physics], which can override the physics used by a page view.
class PageScrollPhysics extends ScrollPhysics {
  /// Creates physics for a [PageView].
  const PageScrollPhysics({ ScrollPhysics parent }) : super(parent: parent);
  @override
  PageScrollPhysics applyTo(ScrollPhysics ancestor) {
    return PageScrollPhysics(parent: buildParent(ancestor));
  }
…
  @override
  Simulation createBallisticSimulation(ScrollMetrics position, double velocity) {
    // If we're out of range and not headed back in range, defer to the parent
    // ballistics, which should put us back in range at a page boundary.
    if ((velocity <= 0.0 && position.pixels <= position.minScrollExtent) ||
        (velocity >= 0.0 && position.pixels >= position.maxScrollExtent))
      return super.createBallisticSimulation(position, velocity);
    final Tolerance tolerance = this.tolerance;
    final double target = _getTargetPixels(position, tolerance, velocity);
    if (target != position.pixels)
      return ScrollSpringSimulation(spring, position.pixels, target, velocity, tolerance: tolerance);
    return null;
  }
...
}

嗯,在這里我們找到里每次滑動的實現(xiàn)類墩莫,ScrollSpringSimulation(漩渦彈簧模擬)對每次滑動進(jìn)行渲染芙委。
找到這個,我們就可以嘗試修改一下源碼:

return ScrollSpringSimulation(SpringDescription({
    this.mass, //質(zhì)量狂秦,控制滾動的慣性
    this.stiffness,//剛性灌侣,滾動收尾速度
    this.damping,//阻尼,俗稱摩擦力
}), position.pixels, target, velocity, tolerance: tolerance);

要說明一下:(對物理感知敏感的小伙伴繞道)
mass:控制質(zhì)量裂问,數(shù)值越大越容易還原到靜止?fàn)顟B(tài)
stiffness:控制滑動力度侧啼,數(shù)值越大滑動速度遠(yuǎn)快(勁越大)
damping:阻力,當(dāng)小于1時則可以取消回彈動畫

現(xiàn)在堪簿,可以整點騷東西:


viewPage滑動測試.gif

畢竟我們改源碼是沒有意義的痊乾,git并不會記錄我們對源碼的修改。剛剛分析的途中椭更,我們看到了部分貓膩

///  * [ScrollPhysics], the base class which defines the API for scrolling physics.

/// Set to false to disable page snapping, useful for custom scroll behavior.
final bool pageSnapping;

ok哪审,只要我們重寫一個PageScrollPhysics 再搭配上 pageSnapping 屬性即可完成這一切:
怎么重寫PageScrollPhysics?簡單甜孤,command+c command+v协饲。

調(diào)整實現(xiàn)

第一步:重寫一個正常的PageScrollPhysics

class pageScrollPhysics extends PageScrollPhysics {
  const pageScrollPhysics({ScrollPhysics parent}) : super(parent: parent);

  @override
  pageScrollPhysics applyTo(ScrollPhysics ancestor) {
    return pageScrollPhysics(parent: buildParent(ancestor));
  }

  double _getPage(ScrollMetrics position) {
    if (position is _PagePosition) return position.page;
    return position.pixels / position.viewportDimension;
  }

  double _getPixels(ScrollMetrics position, double page) {
    if (position is _PagePosition) return position.getPixelsFromPage(page);
    return page * position.viewportDimension;
  }

  double _getTargetPixels(
      ScrollMetrics position, Tolerance tolerance, double velocity) {
    double page = _getPage(position);
    if (velocity < -tolerance.velocity)
      page -= 0.5;
    else if (velocity > tolerance.velocity) page += 0.5;
    return _getPixels(position, page.roundToDouble());
  }

  @override
  Simulation createBallisticSimulation(
      ScrollMetrics position, double velocity) {
    if ((velocity <= 0.0 && position.pixels <= position.minScrollExtent) ||
        (velocity >= 0.0 && position.pixels >= position.maxScrollExtent))
      return super.createBallisticSimulation(position, velocity);
    final Tolerance tolerance = this.tolerance;
    final double target = _getTargetPixels(position, tolerance, velocity);
    if (target != position.pixels)
      return ScrollSpringSimulation(SpringDescription(
        mass: 8,
        stiffness: 150,
        damping: 15,
      ), position.pixels, target, velocity,
          tolerance: tolerance);
    return null;
  }

  @override
  bool get allowImplicitScrolling => false;
}
……(剩下的自己copy)

第二步:pageView設(shè)置物理動畫空間

PageView.builder(
    pageSnapping:false,//必須
    physics:ClampingScrollPhysics()
    itemBuilder: (context, index) {
      return item(data);
    });

效果:


viewPage滑動效果調(diào)整.gif

大功告成、可喜可賀缴川。下次分享見茉稠!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市把夸,隨后出現(xiàn)的幾起案子而线,更是在濱河造成了極大的恐慌,老刑警劉巖恋日,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件膀篮,死亡現(xiàn)場離奇詭異,居然都是意外死亡岂膳,警方通過查閱死者的電腦和手機(jī)誓竿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來谈截,“玉大人筷屡,你說我怎么就攤上這事涧偷。” “怎么了毙死?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵燎潮,是天一觀的道長。 經(jīng)常有香客問我扼倘,道長确封,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任再菊,我火速辦了婚禮爪喘,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘袄简。我一直安慰自己腥放,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布绿语。 她就那樣靜靜地躺著秃症,像睡著了一般。 火紅的嫁衣襯著肌膚如雪吕粹。 梳的紋絲不亂的頭發(fā)上种柑,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天,我揣著相機(jī)與錄音匹耕,去河邊找鬼聚请。 笑死,一個胖子當(dāng)著我的面吹牛稳其,可吹牛的內(nèi)容都是我干的驶赏。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼既鞠,長吁一口氣:“原來是場噩夢啊……” “哼煤傍!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起嘱蛋,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤蚯姆,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后洒敏,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體龄恋,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年凶伙,在試婚紗的時候發(fā)現(xiàn)自己被綠了郭毕。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡函荣,死狀恐怖显押,靈堂內(nèi)的尸體忽然破棺而出链韭,到底是詐尸還是另有隱情,我是刑警寧澤煮落,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站踊谋,受9級特大地震影響蝉仇,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜殖蚕,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一轿衔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧睦疫,春花似錦害驹、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至瓦糕,卻和暖如春底洗,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背咕娄。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工亥揖, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人圣勒。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓费变,卻偏偏與公主長得像,于是被迫代替她去往敵國和親圣贸。 傳聞我的和親對象是個殘疾皇子挚歧,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,916評論 2 344