WearOS Scrollbar

pub package pub points code factor analysis codecov Star on Github License: MIT Buy Me A Coffee

A Flutter plugin that implements an elegant, expressive scroll indicator for Wear OS devices, following the Material 3 Expressive design guidelines for Wear OS 6.

This package provides a customizable circular scrollbar that automatically responds to physical rotary input (such as a rotating bezel or crown) and provides haptic feedback, making your Wear OS applications feel truly native and premium.

✨ Features

  • Material 3 Expressive Design: Modern, sleek circular scrollbar tailored specifically for round screens.
  • Native Rotary Input: Automatically listens to the physical rotary encoder (crown/bezel) of the watch and scrolls the content.
  • Haptic Feedback: Provides integrated configurable haptic feedback as you scroll.
  • Highly Customizable: Easily adjust colors, stroke width, margins, and the total angle covered by the indicator.
  • Hide Indicator: Option to hide the visual indicator while keeping rotary and haptic functionality.
  • Auto-hiding: Smoothly fades out when not actively scrolling.

📸 Example App

Initial View Scrolling Down Reaching Bottom

🛠 Installation

Add the dependency to your pubspec.yaml:

dependencies:
  wear_os_scrollbar: ^0.0.3

⚙️ Configuration

Ensure your android/app/build.gradle is configured correctly for Wear OS:

android {
    defaultConfig {
        minSdkVersion 26 // Or your current minSdk, ideally 26+ for modern Android/WearOS features
    }
}

To make the app assume the rounded canvas appearance on rounded screens, you can add this to your MainActivity.kt:

import android.os.Bundle
import io.flutter.embedding.android.FlutterActivity

class MainActivity : FlutterActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        intent.putExtra("background_mode", "transparent")
        super.onCreate(savedInstanceState)
    }
}

🚀 Usage

Wrap your scrollable content (like a ListView or SingleChildScrollView) with the WearOsScrollbar widget.

Important: You must provide the exact same ScrollController to both the WearOsScrollbar and your scrollable child.

import 'package:flutter/material.dart';
import 'package:wear_os_scrollbar/wear_os_scrollbar.dart';

class MyWearOsScreen extends StatefulWidget {
  const MyWearOsScreen({super.key});

  @override
  State<MyWearOsScreen> createState() => _MyWearOsScreenState();
}

class _MyWearOsScreenState extends State<MyWearOsScreen> {
  final ScrollController _controller = ScrollController();

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black,
      body: WearOsScrollbar(
        controller: _controller,
        // Optional customizations:
        hapticFeedback: WearOsHapticFeedback.lightImpact,
        indicatorColor: Colors.white,
        backgroundColor: Colors.white30,
        strokeWidth: 6.0,
        totalAngle: 30.0,
        child: ListView.builder(
          controller: _controller, // MUST be the same controller
          itemCount: 50,
          itemBuilder: (context, index) {
            return ListTile(
              title: Text('Item $index'),
            );
          },
        ),
      ),
    );
  }
}

📱 Using with PageView

WearOsScrollbar also works perfectly with PageView. If you want to use the rotary input to navigate between pages but prefer to show your own custom page indicator (like dots or a curved indicator), you can set hideIndicator: true.

WearOsScrollbar(
  controller: _pageController,
  hideIndicator: true, // Hides the default scrollbar but keeps rotary input working
  child: PageView(
    controller: _pageController,
    scrollDirection: Axis.vertical, // Works best for vertical PageView on Wear OS
    children: [
      PageOne(),
      PageTwo(),
      PageThree(),
    ],
  ),
)

Customization Options

Parameter Type Default Description
controller ScrollController Required The controller attached to the scrollable widget inside.
child Widget Required The scrollable content (e.g., ListView).
hapticScrollThreshold double 30.0 How much rotary scrolling must accumulate before triggering a haptic click.
hapticFeedback WearOsHapticFeedback .selectionClick The type of vibration to trigger (vibrate, lightImpact, mediumImpact, heavyImpact, selectionClick).
indicatorColor Color Colors.white Color of the active scroll indicator.
backgroundColor Color Colors.white30 Color of the background track arc.
strokeWidth double 6.0 Thickness of the scrollbar (must be between 1 and 10).
marginRight double 0.0 Distance from the physical edge of the screen (must be between 0 and 50).
totalAngle double 30.0 Total span angle of the scrollbar area (must be between 10 and 90 degrees).
hideIndicator bool false Whether to hide the visual scroll indicator while maintaining rotary and haptic support.

📄 License

Distributed under the MIT License. See LICENSE for more information.

Libraries

wear_os_scrollbar
A custom scrollbar tailored for Wear OS applications.
wear_os_scrollbar_method_channel
The method channel implementation for wear_os_scrollbar.
wear_os_scrollbar_platform_interface
The platform interface for wear_os_scrollbar.