bitsdojo / bitsdojo_window

A Flutter package that makes it easy to customize and work with your Flutter desktop app window.
http://www.youtube.com/watch?v=bee2AHQpGK4
MIT License
815 stars 229 forks source link

Support build for mobile platforms. #78

Open UNIcodeX opened 3 years ago

UNIcodeX commented 3 years ago

I may be missing something, but I don't know of a way to get a project that uses this plugin to build without the custom window portions for a mobile target. Please advise. Thank you.

EDIT: See reply for a working solution. 😄

UNIcodeX commented 3 years ago

Investigating this a bit, I have found success in overriding the WindowTitleBarBox class with the following:

import 'package:universal_io/io.dart' show Platform; // Make use of `Platform` while also supporting web targets

import 'package:flutter/material.dart';

import 'package:bitsdojo_window/bitsdojo_window.dart';

get isDesktop {
  return Platform.isMacOS || Platform.isLinux || Platform.isWindows;
}

class MobileAwareWindowTitleBarBox extends WindowTitleBarBox {
  final Widget? child;
  MyWindowTitleBarBox({Key? key, this.child}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    if (kIsWeb || !isDesktop) { // adds check for desktop platform
      return Container();
    }
    final titlebarHeight = appWindow.titleBarHeight;
    return SizedBox(height: titlebarHeight, child: this.child ?? Container());
  }
}

The example in your Readme.md, modified to use the overridden class:

import 'package:universal_io/io.dart' show Platform;  // Make use of `Platform` while also supporting web targets

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

get isDesktop {
  return Platform.isMacOS || Platform.isLinux || Platform.isWindows;
}

const bool kIsWeb = identical(0, 0.0);  // Taken from Dart libs

void main() {
  runApp(MyApp());
  // Only setup the appWindow if we're on a desktop.
  if (isDesktop) {
    doWhenWindowReady(() {
      final win = appWindow;
      final initialSize = Size(600, 450);
      win.minSize = initialSize;
      win.size = initialSize;
      win.alignment = Alignment.center;
      win.title = "Custom window with Flutter";
      win.show();
    });
  }
}

const borderColor = Color(0xFF805306);

class MobileAwareWindowTitleBarBox extends WindowTitleBarBox {
  final Widget? child;
  MobileAwareWindowTitleBarBox({Key? key, this.child}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    if (kIsWeb || !isDesktop) {
      return Container();
    }
    final titlebarHeight = appWindow.titleBarHeight;
    return SizedBox(height: titlebarHeight, child: this.child ?? Container());
  }
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        debugShowCheckedModeBanner: false,
        home: Scaffold(
            body: WindowBorder(
                color: borderColor,
                width: 1,
                child: Row(children: [LeftSide(), RightSide()]))));
  }
}

const sidebarColor = Color(0xFFF6A00C);

class LeftSide extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return SizedBox(
        width: 200,
        child: Container(
            color: sidebarColor,
            child: Column(
              children: [
                MobileAwareWindowTitleBarBox(child: MoveWindow()),
                Expanded(child: Container())
              ],
            )));
  }
}

const backgroundStartColor = Color(0xFFFFD500);
const backgroundEndColor = Color(0xFFF6A00C);

class RightSide extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Expanded(
        child: Container(
            decoration: BoxDecoration(
              gradient: LinearGradient(
                  begin: Alignment.topCenter,
                  end: Alignment.bottomCenter,
                  colors: [backgroundStartColor, backgroundEndColor],
                  stops: [0.0, 1.0]),
            ),
            child: Column(children: [
              // 
              MobileAwareWindowTitleBarBox(
                  child: Row(children: [
                Expanded(child: MoveWindow()),
                WindowButtons()
              ])),
            ])));
  }
}

final buttonColors = WindowButtonColors(
    iconNormal: Color(0xFF805306),
    mouseOver: Color(0xFFF6A00C),
    mouseDown: Color(0xFF805306),
    iconMouseOver: Color(0xFF805306),
    iconMouseDown: Color(0xFFFFD500));

final closeButtonColors = WindowButtonColors(
    mouseOver: Color(0xFFD32F2F),
    mouseDown: Color(0xFFB71C1C),
    iconNormal: Color(0xFF805306),
    iconMouseOver: Colors.white);

class WindowButtons extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        MinimizeWindowButton(colors: buttonColors),
        MaximizeWindowButton(colors: buttonColors),
        CloseWindowButton(colors: closeButtonColors),
      ],
    );
  }
}

Modified example running in Android emulator. image

Modified example running on Linux desktop: image

bitsdojo commented 3 years ago

Thank you for taking the time to write a solution. Will add it to the repo.

prateekmedia commented 3 years ago

@bitsdojo But it is only for Android and IOS detection, but in issue #90 I was talking about ARM linux devices or ARM windows devices, which is windows / linux but on mobile.

In mobile linux the titlebar (which is managed by window manager) is hidden or so to speak the close/minimize/maximize buttons are hidden for smoother mobile experience.

So this is not related to #90