Chuyển đến nội dung chính

Bài đăng

Hiển thị các bài đăng có nhãn Animation

Hero animations without the glitches — hướng dẫn Flutter

Heroes are the cheapest way to make navigation feel spatial. Bài này chuyển quan sát đó thành một mô hình nhỏ để bạn có thể kiểm thử, đo lường và giữ cho code dễ bảo trì khi app lớn lên. Vấn đề cốt lõi FlightShuttleBuilder, tags that do not collide, and photo galleries. Câu hỏi hữu ích không phải API hay pattern có đẹp riêng lẻ hay không, mà là state nằm ở đâu, boundary nào chịu trách nhiệm khi lỗi xảy ra, và người dùng phục hồi thế nào khi happy path biến mất. Mô hình thực tế Unique tags per item are mandatory in lists. Hãy bắt đầu bằng một owner rõ ràng cho behavior. Widget chỉ nên render và phát intent; IO, persistence, permission và retry nên nằm sau một interface nhỏ. Nhờ vậy bạn có seam để fake trong test và một chỗ ghi lại các dữ kiện cần theo dõi ở production. Trong app Flutter, boundary thường có dạng: Widget phát intent như load, submit, refresh hoặc retry. Controller hoặc use case validate intent rồi gọi boundary. Boundary trả về data có kiểu hoặc failure có kiểu,...

Hero animations without the glitches

Heroes are the cheapest way to make navigation feel spatial. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence FlightShuttleBuilder, tags that do not collide, and photo galleries. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model Unique tags per item are mandatory in lists. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an intent such as load, submit, refresh, or retry. A controller or use case validates the intent...

prefers-reduced-motion and Flutter animations — hướng dẫn Flutter

Some users get sick from motion. Honor the platform setting. Bài này chuyển quan sát đó thành một mô hình nhỏ để bạn có thể kiểm thử, đo lường và giữ cho code dễ bảo trì khi app lớn lên. Vấn đề cốt lõi MediaQuery disableAnimations and designing calm alternatives. Câu hỏi hữu ích không phải API hay pattern có đẹp riêng lẻ hay không, mà là state nằm ở đâu, boundary nào chịu trách nhiệm khi lỗi xảy ra, và người dùng phục hồi thế nào khi happy path biến mất. Mô hình thực tế Swap parallax and large transitions for opacity fades. Hãy bắt đầu bằng một owner rõ ràng cho behavior. Widget chỉ nên render và phát intent; IO, persistence, permission và retry nên nằm sau một interface nhỏ. Nhờ vậy bạn có seam để fake trong test và một chỗ ghi lại các dữ kiện cần theo dõi ở production. Trong app Flutter, boundary thường có dạng: Widget phát intent như load, submit, refresh hoặc retry. Controller hoặc use case validate intent rồi gọi boundary. Boundary trả về data có kiểu hoặc failure có ki...

Haptics and microinteractions that feel native — hướng dẫn Flutter

Small feedback loops make UIs feel expensive. Bài này chuyển quan sát đó thành một mô hình nhỏ để bạn có thể kiểm thử, đo lường và giữ cho code dễ bảo trì khi app lớn lên. Vấn đề cốt lõi HapticFeedback, spring curves, and when less is more. Câu hỏi hữu ích không phải API hay pattern có đẹp riêng lẻ hay không, mà là state nằm ở đâu, boundary nào chịu trách nhiệm khi lỗi xảy ra, và người dùng phục hồi thế nào khi happy path biến mất. Mô hình thực tế Match platform haptic patterns; do not invent new ones. Hãy bắt đầu bằng một owner rõ ràng cho behavior. Widget chỉ nên render và phát intent; IO, persistence, permission và retry nên nằm sau một interface nhỏ. Nhờ vậy bạn có seam để fake trong test và một chỗ ghi lại các dữ kiện cần theo dõi ở production. Trong app Flutter, boundary thường có dạng: Widget phát intent như load, submit, refresh hoặc retry. Controller hoặc use case validate intent rồi gọi boundary. Boundary trả về data có kiểu hoặc failure có kiểu, không trả string c...

Rive: interactive vector animation as a state machine

Rive: interactive vector animation as a state machine rive is useful because it focuses on artboards, state machines, inputs, and runtime performance. The important engineering move is to place the package behind a clear boundary, so your Flutter UI depends on a stable capability rather than a vendor-shaped API. What the library should own Keep package calls inside a named adapter or feature boundary. Make lifecycle, errors, and loading state part of a testable contract. Expose only the capability the app needs; hide implementation details from the whole tree. A focused starting point final controller = StateMachineController . fromArtboard ( artboard, 'LoginMachine' , ); if (controller != null ) { artboard. addController (controller); final success = controller. findInput < bool >( 'success' ); success ? .value = true ; } Production checklist Read the README and changelog for the exact version you pin. Add one test for life...

animations: reusable Material motion patterns

animations: reusable Material motion patterns animations is useful because it focuses on OpenContainer, shared axis, fade-through, and route transitions. The important engineering move is to place the package behind a clear boundary, so your Flutter UI depends on a stable capability rather than a vendor-shaped API. What the library should own Keep package calls inside a named adapter or feature boundary. Make lifecycle, errors, and loading state part of a testable contract. Expose only the capability the app needs; hide implementation details from the whole tree. A focused starting point return OpenContainer < bool >( closedBuilder : (_, open) => ListTile ( title : const Text ( 'Open details' ), onTap : open, ), openBuilder : (_, close) => const DetailsPage (), ); Production checklist Read the README and changelog for the exact version you pin. Add one test for lifecycle, failure, and app background/foreground behavior. V...

Hero animations without the glitches — hướng dẫn Flutter

Heroes are the cheapest way to make navigation feel spatial. Bài này chuyển quan sát đó thành một mô hình nhỏ để bạn có thể kiểm thử, đo lường và giữ cho code dễ bảo trì khi app lớn lên. Vấn đề cốt lõi FlightShuttleBuilder, tags that do not collide, and photo galleries. Câu hỏi hữu ích không phải API hay pattern có đẹp riêng lẻ hay không, mà là state nằm ở đâu, boundary nào chịu trách nhiệm khi lỗi xảy ra, và người dùng phục hồi thế nào khi happy path biến mất. Mô hình thực tế Unique tags per item are mandatory in lists. Hãy bắt đầu bằng một owner rõ ràng cho behavior. Widget chỉ nên render và phát intent; IO, persistence, permission và retry nên nằm sau một interface nhỏ. Nhờ vậy bạn có seam để fake trong test và một chỗ ghi lại các dữ kiện cần theo dõi ở production. Trong app Flutter, boundary thường có dạng: Widget phát intent như load, submit, refresh hoặc retry. Controller hoặc use case validate intent rồi gọi boundary. Boundary trả về data có kiểu hoặc failure có kiểu,...

Scroll physics tự viết: khiến danh sách dừng đúng chỗ bạn muốn

Cuộn là thao tác người dùng cảm nhận nhiều nhất nhưng mô tả được ít nhất. “Nó rề rà”, “nó không dừng ở chỗ tôi tưởng”, “trên Android nó nảy sai”. Tất cả những lời phàn nàn đó đều trỏ về một lớp nhỏ: ScrollPhysics . Phần lớn lập trình viên Flutter chỉ gặp nó qua ba lớp con có tên sẵn — BouncingScrollPhysics , ClampingScrollPhysics , NeverScrollableScrollPhysics . Bên dưới, đó là một interface gọn với bốn điểm quyết định, và hiểu chúng biến “danh sách dừng ở chỗ kỳ quặc” từ một bí ẩn thành bản sửa hai dòng. Lớp này thật sự quyết định điều gì Phương thức Quyết định applyPhysicsToUserOffset Chuyển động của ngón tay ánh xạ sang offset cuộn ra sao — độ kháng khi overscroll applyBoundaryConditions Từ chối bao nhiêu phần của offset được yêu cầu khi ở mép createBallisticSimulation Chuyện gì xảy ra sau khi nhấc tay: fling, ổn định, snap, hay không gì cả tolerance Khi nào một simulation được coi là kết thúc Cộng thêm hai thuộc tính đáng biết: shouldAcceptUserOffset (...

prefers-reduced-motion and Flutter animations

Some users get sick from motion. Honor the platform setting. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence MediaQuery disableAnimations and designing calm alternatives. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model Swap parallax and large transitions for opacity fades. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an intent such as load, submit, refresh, or retry. A controller or use case validates the int...

Haptics and microinteractions that feel native

Small feedback loops make UIs feel expensive. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence HapticFeedback, spring curves, and when less is more. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model Match platform haptic patterns; do not invent new ones. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an intent such as load, submit, refresh, or retry. A controller or use case validates the intent and calls the boun...

Hero animations without the glitches

Heroes are the cheapest way to make navigation feel spatial. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence FlightShuttleBuilder, tags that do not collide, and photo galleries. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model Unique tags per item are mandatory in lists. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an intent such as load, submit, refresh, or retry. A controller or use case validates the intent...

Scroll physics tự viết: khiến danh sách dừng đúng chỗ bạn muốn

Cuộn là thao tác người dùng cảm nhận nhiều nhất nhưng mô tả được ít nhất. “Nó rề rà”, “nó không dừng ở chỗ tôi tưởng”, “trên Android nó nảy sai”. Tất cả những lời phàn nàn đó đều trỏ về một lớp nhỏ: ScrollPhysics . Phần lớn lập trình viên Flutter chỉ gặp nó qua ba lớp con có tên sẵn — BouncingScrollPhysics , ClampingScrollPhysics , NeverScrollableScrollPhysics . Bên dưới, đó là một interface gọn với bốn điểm quyết định, và hiểu chúng biến “danh sách dừng ở chỗ kỳ quặc” từ một bí ẩn thành bản sửa hai dòng. Lớp này thật sự quyết định điều gì Phương thức Quyết định applyPhysicsToUserOffset Chuyển động của ngón tay ánh xạ sang offset cuộn ra sao — độ kháng khi overscroll applyBoundaryConditions Từ chối bao nhiêu phần của offset được yêu cầu khi ở mép createBallisticSimulation Chuyện gì xảy ra sau khi nhấc tay: fling, ổn định, snap, hay không gì cả tolerance Khi nào một simulation được coi là kết thúc Cộng thêm hai thuộc tính đáng biết: shouldAcceptUserOffset (...

Custom scroll physics: making a list stop where you want it to

Scrolling is the interaction users feel most and describe least. “It feels sluggish”, “it doesn’t stop where I expect”, “it bounces wrong on Android”. Those complaints all point at one small class: ScrollPhysics . Most Flutter developers only ever meet it through the three named subclasses — BouncingScrollPhysics , ClampingScrollPhysics , NeverScrollableScrollPhysics . Underneath, it is a compact interface with four decision points, and understanding those turns “the list stops in a weird place” from a mystery into a two-line fix. What the class actually decides Method Decides applyPhysicsToUserOffset How a finger’s movement maps to scroll offset — resistance when overscrolling applyBoundaryConditions How much of a requested offset to refuse at the edges createBallisticSimulation What happens after the finger lifts: fling, settle, snap, or nothing tolerance When a simulation is considered finished Plus two properties worth knowing: shouldAcceptUserOffset (...