Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .github/workflows/pr_validation.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,27 @@ jobs:

# Run all tests
- run: flutter test

test_goldens:
runs-on: ubuntu-latest
steps:
# Checkout the PR branch
- uses: actions/checkout@v3

# Setup Flutter environment
- uses: subosito/flutter-action@v2
with:
channel: "stable"

# Download all the packages that the app uses
- run: flutter pub get

# Run all tests
- run: flutter test test_goldens

# Archive golden failures
- uses: actions/upload-artifact@v4
if: failure()
with:
name: golden-failures
path: "**/failures/**/*.png"
19 changes: 7 additions & 12 deletions example/android/app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
plugins {
id "com.android.application"
id "kotlin-android"
id "dev.flutter.flutter-gradle-plugin"
}

def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
Expand All @@ -6,11 +12,6 @@ if (localPropertiesFile.exists()) {
}
}

def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}

def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
Expand All @@ -21,13 +22,11 @@ if (flutterVersionName == null) {
flutterVersionName = '1.0'
}

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"

android {
compileSdkVersion flutter.compileSdkVersion
ndkVersion flutter.ndkVersion
namespace "com.example.example"

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
Expand Down Expand Up @@ -65,7 +64,3 @@ android {
flutter {
source '../..'
}

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
13 changes: 0 additions & 13 deletions example/android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,16 +1,3 @@
buildscript {
ext.kotlin_version = '1.7.10'
repositories {
google()
mavenCentral()
}

dependencies {
classpath 'com.android.tools.build:gradle:7.2.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}

allprojects {
repositories {
google()
Expand Down
2 changes: 1 addition & 1 deletion example/android/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-all.zip
30 changes: 22 additions & 8 deletions example/android/settings.gradle
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
include ':app'
pluginManagement {
def flutterSdkPath = {
def properties = new Properties()
file("local.properties").withInputStream { properties.load(it) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
return flutterSdkPath
}()

def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
def properties = new Properties()
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")

assert localPropertiesFile.exists()
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}

def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0" // apply true
id "com.android.application" version "8.3.0" apply false
id "org.jetbrains.kotlin.android" version "1.8.10" apply false
}

include ":app"
2 changes: 1 addition & 1 deletion example/lib/main_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
PageListViewportGestures(
controller: _controller,
lockPanAxis: true,
child: PageListViewport(
child: PageListViewport.sameSizePages(
controller: _controller,
pageCount: _pageCount,
naturalPageSize: _naturalPageSizeInInches * 72 * MediaQuery.of(context).devicePixelRatio,
Expand Down
2 changes: 1 addition & 1 deletion example/lib/main_long_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
PageListViewportGestures(
controller: _controller,
lockPanAxis: true,
child: PageListViewport(
child: PageListViewport.sameSizePages(
controller: _controller,
pageCount: _pageCount,
naturalPageSize: _naturalPageSizeInInches * 72 * MediaQuery.of(context).devicePixelRatio,
Expand Down
2 changes: 1 addition & 1 deletion example/lib/main_minimal_viewport.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class _MinimalViewportDemoState extends State<_MinimalViewportDemo> with TickerP
return Scaffold(
body: PageListViewportGestures(
controller: _controller,
child: PageListViewport(
child: PageListViewport.sameSizePages(
controller: _controller,
pageCount: 10,
naturalPageSize: const Size(8.5, 11) * 72,
Expand Down
2 changes: 1 addition & 1 deletion example/lib/main_single_page_orientation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
children: [
PageListViewportGestures(
controller: _controller,
child: PageListViewport(
child: PageListViewport.sameSizePages(
controller: _controller,
pageCount: 1,
naturalPageSize: const Size(8.5, 11) * 72 * MediaQuery.of(context).devicePixelRatio,
Expand Down
177 changes: 177 additions & 0 deletions example/lib/main_variable_page_size.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
import 'package:flutter/material.dart';
import 'package:logging/logging.dart';
import 'package:page_list_viewport/page_list_viewport.dart';

void main() {
PageListViewportLogs.initLoggers(Level.ALL, {});

runApp(const MyApp());
}

class MyApp extends StatelessWidget {
const MyApp({super.key});

@override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Page List Viewport Variable Size Demo',
home: MyHomePage(),
);
}
}

/// A widget that displays a [PageListViewportWithVariablePageSize], intercalating
/// between vertical and horizontal aspect ratios for each page.
///
/// Each page has a centered circle, which scales its size based on the incoming constraints,
/// and the natural size of the page.
class MyHomePage extends StatefulWidget {
const MyHomePage({
super.key,
});

@override
State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
static const _pageCount = 200;

static const _pageSizes = [
Size(8.5, 11), // Letter
Size(11, 8.5), // Letter (inverse)
];

late final PageListViewportWithVariableSizeController _controller;

@override
void initState() {
super.initState();
_controller = PageListViewportWithVariableSizeController.startAtPage(pageIndex: 5, vsync: this);
}

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

@override
Widget build(BuildContext context) {
return Scaffold(
body: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
SizedBox(
width: 125,
child: _buildThumbnailList(),
),
Expanded(
child: Center(
child: SizedBox(
height: _pageSizes[0].height * 72 * MediaQuery.of(context).devicePixelRatio,
width: _pageSizes[0].width * 72 * MediaQuery.of(context).devicePixelRatio,
child: _buildViewport(),
),
),
),
],
),
);
}

Widget _buildViewport() {
return Stack(
children: [
PageListViewportGestures(
controller: _controller,
lockPanAxis: true,
child: PageListViewport.variedPages(
controller: _controller,
pageCount: _pageCount,
onGetNaturalPageSize: (pageIndex) =>
_pageSizes[pageIndex % _pageSizes.length] * 72 * MediaQuery.of(context).devicePixelRatio,
pageLayoutCacheCount: 3,
pagePaintCacheCount: 3,
builder: (BuildContext context, int pageIndex) {
return Stack(
children: [
Positioned.fill(
child: GestureDetector(
onTap: () => print('tapped at pageIndex: $pageIndex'),
child: _buildPage(pageIndex),
),
),
],
);
},
),
),
],
);
}

Widget _buildThumbnailList() {
return RepaintBoundary(
child: ColoredBox(
color: Colors.grey.shade800,
child: ListView.builder(
padding: const EdgeInsets.all(16),
itemCount: _pageCount,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8),
child: GestureDetector(
onTap: () {
_controller.animateToPage(index, const Duration(milliseconds: 250));
},
child: AspectRatio(
aspectRatio: _pageSizes[index % _pageSizes.length].aspectRatio,
child: _buildPage(index),
),
),
);
},
),
),
);
}

Widget _buildPage(int pageIndex) {
final pageSize = Size(
_pageSizes[pageIndex % _pageSizes.length].width * 72,
_pageSizes[pageIndex % _pageSizes.length].height * 72,
);

return Container(
color: Colors.white,
child: Container(
color: Colors.primaries[pageIndex % Colors.primaries.length],
width: pageSize.width,
height: pageSize.height,
child: Center(
child: LayoutBuilder(builder: (context, constraints) {
return Container(
width: 300 * (constraints.maxWidth / pageSize.width),
height: 300 * (constraints.maxHeight / pageSize.height),
decoration: const BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
),
alignment: Alignment.center,
child: Padding(
padding: const EdgeInsets.all(4.0),
child: FittedBox(
child: Text(
'Page $pageIndex',
style: const TextStyle(fontSize: 24),
),
),
),
);
}),
),
),
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ class _PageListImagesInspectorDemoState extends State<PageListImagesInspectorDem
controller: _viewportController,
child: PageListViewportGestures(
controller: _viewportController,
child: PageListViewport(
child: PageListViewport.sameSizePages(
key: _pageViewportKey,
controller: _viewportController,
pageCount: 20,
Expand Down
23 changes: 23 additions & 0 deletions golden_tester.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
FROM ubuntu:latest

ENV FLUTTER_HOME=${HOME}/sdks/flutter
ENV PATH ${PATH}:${FLUTTER_HOME}/bin:${FLUTTER_HOME}/bin/cache/dart-sdk/bin

USER root

RUN apt update

RUN apt install -y git curl unzip

# Print the Ubuntu version. Useful when there are failing tests.
RUN cat /etc/lsb-release

# Invalidate the cache when flutter pushes a new commit.
ADD https://api.github.com/repos/flutter/flutter/git/refs/heads/stable ./flutter-latest-stable

RUN git clone https://github.com/flutter/flutter.git ${FLUTTER_HOME}

RUN flutter doctor

# Copy the whole repo.
COPY ./ /golden_tester
1 change: 1 addition & 0 deletions lib/page_list_viewport.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
library page_list_viewport;

export 'src/page_list_viewport.dart';
export 'src/page_list_viewport_variable_size.dart';
export 'src/page_list_performance_optimizer.dart';
export 'src/logging.dart';

Expand Down
Loading