Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
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"
172 changes: 172 additions & 0 deletions example/lib/main_variable_page_size.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
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(),
);
}
}

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.variedPageSized(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dodgog I'm reviewing this PR with @angelosilvestre - what do you think about this widget API? Do you see anything missing in terms of what you need for varied page sizes?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks fine, yes. I can see the alternative being: passing a list of page sizes and also a function onGetNaturalSizeForPage() [doesn't have arguments]. Or is there a design constraint requiring onGetNaturalPageSize to be a different function for each page?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dodgog

A list of page sizes sounds good to me, but I didn't understand why we would have an onGetNaturalSizeForPage() without arguments if the list of page sizes is provided.

Could you clarify that?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The api looks good. It's either a list of sizes, or a PageSizeResolver with a cache.
It may not always be cheap to obtain a list of sizes in advance, that's why onGetSize can be helpful to dynamically build the viewport.

Just to confirm my understanding: does the total length of the viewport need to be known in advance in order to render the widget?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The api looks good. It's either a list of sizes, or a PageSizeResolver with a cache.
It may not always be cheap to obtain a list of sizes in advance, that's why onGetSize can be helpful to dynamically build the viewport.

Currently, only a PageSizeResolver is allowed. Do you want another option to give a list of sizes instead?

Just to confirm my understanding: does the total length of the viewport need to be known in advance in order to render the widget?

The pageCount is required in order to render the widget.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's no need for a list of sizes. The consumer of the api could probably implement a convenience resolver which would have cached values, for example a getSize(i) function which would map to sizesList[i] as you do in the example app roughly. This is good for now. Can proceed with final reviews and merging probably.

Let's not act on this now, but I'm wondering if it will be easy/worth it to make the calculation and per-page layout lazy? Would have to involve some complex scrolling approximations, but how hard is it?

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),
),
),
),
);
}),
),
),
);
}
}
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