huahua_motion

简体中文 | English

Composable, focus-driven motion primitives for Flutter interfaces.

huahua_motion is a collection of small widgets that translate application state into coordinated motion. The package owns reusable visual and interaction primitives; the application keeps control of data, scrolling policy, navigation, timing, and feedback.

Features

  • Drive scale, opacity, and translation with one normalized focus value.
  • Calculate focus automatically for items in a fixed-extent scrolling list.
  • Add an interactive edge timeline with discrete and continuous selection.
  • Import the complete collection, a motion domain, or one primitive.
  • Use any widget as content without adopting a package-specific data model.
  • Run on Android, iOS, Web, Windows, macOS, and Linux.

Installation

Add the package from pub.dev:

flutter pub add huahua_motion

Or declare it directly:

dependencies:
  huahua_motion: ^0.0.2

The current package requires Dart ^3.12.2 and Flutter >=1.17.0.

Choose an import

Import the complete collection when a feature uses primitives from several domains:

import 'package:huahua_motion/huahua_motion.dart';

Import one domain when related primitives are used together:

import 'package:huahua_motion/focus.dart';
import 'package:huahua_motion/timeline.dart';

Import an individual primitive to make a file's dependency explicit:

import 'package:huahua_motion/focus_transform.dart';
import 'package:huahua_motion/scroll_focus_transform.dart';
import 'package:huahua_motion/timeline_scrubber.dart';

Do not import files under lib/src/; they are implementation details and may change without notice. Import granularity controls API visibility, not release binary size: Flutter's tree shaker can remove unused code even when the complete collection entrypoint is imported.

Motion primitives

HuahuaFocusTransform

HuahuaFocusTransform maps a normalized progress value to scale, opacity, and translation. A value of 0 applies the unfocused state and 1 applies the focused state. Values outside the range are clamped before the curve is applied.

import 'package:flutter/widgets.dart';
import 'package:huahua_motion/focus_transform.dart';

HuahuaFocusTransform(
  progress: progress,
  minScale: 0.88,
  maxScale: 1,
  minOpacity: 0.25,
  maxOpacity: 1,
  unfocusedOffset: const Offset(0, 12),
  focusedOffset: Offset.zero,
  curve: Curves.easeOutCubic,
  child: card,
)

The caller owns progress, so it can come from an animation, gesture, scroll measurement, sensor, or any other state source.

HuahuaScrollFocusTransform

HuahuaScrollFocusTransform measures a fixed-extent list item against a focus point in the viewport. Only its lightweight transform wrappers rebuild during scrolling; the supplied child is retained by AnimatedBuilder.

import 'package:huahua_motion/scroll_focus_transform.dart';

HuahuaScrollFocusTransform(
  controller: scrollController,
  itemOffset: leadingPadding + index * itemExtent,
  itemExtent: itemExtent,
  viewportExtent: viewportHeight,
  focusAlignment: 0.5,
  focusDistanceFactor: 1.2,
  minScale: 0.82,
  minOpacity: 0.22,
  child: RepaintBoundary(child: itemBuilder(context, index)),
)

itemOffset is the item's leading position in scroll-content coordinates and must include leading list padding. This primitive is intended for lists whose main-axis item extent is known and fixed. It does not add snapping or change the list's ScrollPhysics.

HuahuaTimelineScrubber

HuahuaTimelineScrubber is a transient, edge-aligned selector for a vertical list. Provide one entry per list item so a timeline position maps directly to a list index.

import 'package:huahua_motion/timeline_scrubber.dart';

final entries = <HuahuaTimelineEntry>[
  const HuahuaTimelineEntry(label: 'Sep 10', isImportant: true),
  const HuahuaTimelineEntry(),
  const HuahuaTimelineEntry(label: 'Aug 28', isImportant: true),
];

HuahuaTimelineScrubber(
  entries: entries,
  currentIndex: currentIndex,
  currentPosition: currentPosition,
  onIndexChanged: handleIndexChanged,
  onPositionChanged: handlePositionChanged,
  onDragStart: handleDragStart,
  onDragEnd: handleDragEnd,
)

The callbacks serve different integration needs:

  • onIndexChanged reports the nearest discrete node and is suitable for selection state or haptic feedback.
  • onPositionChanged reports a fractional position during direct manipulation and is suitable for driving a list continuously.
  • onDragEnd reports velocity in item positions per second, which can seed a spring simulation.

Sparse timelines are centered. Dense timelines keep a fixed node spacing and move a window through the full set instead of compressing every node. Important entries may show a short label. Set reverseDragDirection when the controlled content uses the opposite index direction.

Backdrop blur is enabled by default. Disable it on performance-sensitive screens:

HuahuaTimelineScrubber(
  // ...
  enableBackdropBlur: false,
)

HuahuaFixedExtentScrollTimeline

Use HuahuaFixedExtentScrollTimeline when you want the complete interaction shown by the example. This high-level core widget combines focus transforms, bidirectional timeline synchronization, fixed-extent snapping, automatic visibility, and optional selection haptics.

import 'package:huahua_motion/fixed_extent_scroll_timeline.dart';

HuahuaFixedExtentScrollTimeline(
  entries: timelineEntries,
  itemExtent: 288,
  itemBuilder: (context, index) => MyMomentWidget(
    moment: moments[index],
  ),
)

itemBuilder accepts any Widget. The core package neither requires nor loads images: image cards, text, editors, and other application widgets can all take part in the focus interaction. Items must share one main-axis extent.

See the fixed-extent scroll timeline guide for controller ownership, focus customization, and integration constraints.

Package boundary

The package provides both low-level primitives and an optional high-level composition for fixed-extent lists.

Provided by huahua_motion Owned by the application
Focus interpolation Focus progress source
Fixed-extent scroll measurement List data and Widget content
Fixed-extent snapping and elastic physics Variable-height geometry mapping
Timeline painting, gestures, and bidirectional synchronization Grouping, pagination, and business selection state
Optional haptics and automatic visibility Sound and route transitions
Optional backdrop blur Image loading and error states

The high-level widget still receives application content through itemBuilder, so it imposes no image, navigation, state-management, or data architecture. Compose the lower-level primitives directly for custom or variable-height geometry.

Performance guidance

  • Keep scrolling children stable; avoid constructing a new expensive subtree on every scroll tick.
  • Wrap image-heavy or paint-heavy cards in RepaintBoundary when profiling shows repaint cost.
  • Disable timeline backdrop blur when composition cost is more important than the glass effect.
  • When composing primitives yourself, throttle timeline-to-scroll writes to one update per frame. HuahuaFixedExtentScrollTimeline does this internally.
  • Profile on representative physical devices before choosing final effects.

Example

The example opens with a catalog of independently runnable demos:

  • An isolated focus-transform playground.
  • A composed fixed-extent gallery with focus transforms, an edge timeline, snapping physics, haptics, and deterministic Picsum images.

The scrolling demo uses the core HuahuaFixedExtentScrollTimeline; its network images and card content still come from the example's itemBuilder.

cd example
flutter run

The scrolling gallery requires an internet connection for images. Loading and failure placeholders preserve card dimensions and scroll geometry.

API status

The package is currently at 0.0.2. Public entrypoints are available, but the API should still be treated as early-stage.

License

See LICENSE.

Libraries

fixed_extent_scroll_timeline
A coordinated fixed-extent focus list and edge timeline.
focus
Focus-driven motion primitives.
focus_transform
A focus-driven scale, opacity, and translation transform.
huahua_motion
All composable motion primitives provided by huahua_motion.
scroll_focus_transform
A focus transform driven by a fixed-extent scroll position.
timeline
Timeline motion primitives.
timeline_scrubber
An edge-aligned timeline selector for vertically scrolling content.