颤振设计曲线布局作为单个小部件 [英] flutter design Curves layout as single widget

查看:71
本文介绍了颤振设计曲线布局作为单个小部件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此处解决了有关设计此布局的问题.

Here solved question about design this layout.

我有一个问题,因为屏幕右边的曲线不是小部件,而当我想在绿色的一面有其他小部件时,我不能,因为设计的曲线不是小部件,而是从绿色中剪下的布局.

I have a problem to using that, because of this curve on right of screen is not widget and when I want to have some other widgets in green side, I can't, because designed curve is not widget its clipped from green layout.

假设我要在屏幕的右侧显示此曲线,并在其下方显示一些小部件.

Suppose I want to have this curve on right of screen and some widget in below of that.

源代码

import 'package:flutter/material.dart';

void main() {
    runApp(MaterialApp(home: Scaffold(body: Test())));
}

class Test extends StatefulWidget {
    @override
    _TestState createState() => _TestState();
}

class _TestState extends State<Test> {
    double _height = 0.0;
    double _width = 0.0;
    double _rightPadding = 2.0;
    double _btnSize = 25.0;
    double _btnY = 0.0;

    @override
    Widget build(BuildContext context) {
    if (_height == 0.0)
        setState(() {
        _height = MediaQuery.of(context).size.height;
        _width = MediaQuery.of(context).size.width;
        _btnY = _height / 3 * 2;
        });
    return _height == 0.0
        ? Container()
        : Stack(
            children: <Widget>[
                Container(
                color: Colors.white,
                ),
                CustomPaint(
                size: Size(_width - _rightPadding, _height),
                painter: CurvedPainter(_btnSize, _btnY),
                ),
            ],
            );
    }
}

class CurvedPainter extends CustomPainter {
    CurvedPainter(this.btnSize, this.btnY);

    final double btnSize;
    final double btnY;

    @override
    void paint(Canvas canvas, Size size) {
    Path path = Path();
    path.moveTo(0.0, 0.0);
    path.lineTo(size.width, 0.0);
    path.lineTo(size.width, btnY - btnSize * 2);

    path.cubicTo(size.width, btnY - btnSize * 0.3, size.width - btnSize * 0.95, btnY - btnSize * 0.9, size.width - btnSize, btnY);
    path.cubicTo(size.width - btnSize * 0.95, btnY + btnSize * 0.9, size.width, btnY + btnSize * 0.3, size.width, btnY + btnSize * 2);

    path.lineTo(size.width, size.height);
    path.lineTo(0.0, size.height);
    path.lineTo(0.0, 0.0);
    canvas.drawPath(
        path,
        Paint()
            ..color = Colors.transparent
            ..style = PaintingStyle.fill);
    }

    @override
    bool shouldRepaint(CurvedPainter oldDelegate) => oldDelegate.btnY != btnY;
}

我想在所有小部件的顶部使用右曲线作为小部件,而没有绿色的一面,您认为绿色的一面是ListView.

I want to use right curve as an widget on top of all widgets, without having green side, you suppose green side is as ListView.

推荐答案

似乎您需要以下图片中给出的类似信息.

It seems that you need something like this given in the image below.

更新:已添加拖动控件

import 'dart:math' as math;
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        body: Test(),
      ),
    );
  }
}

class Test extends StatefulWidget {
  @override
  _TestState createState() => _TestState();
}

enum dragType { vertical, horizontal }

class _TestState extends State<Test> {
  final double _btnSize = 48.0;
  final double _rightPadding = 0;

  double _extraOffcet = 0;
  double _btnY;
  double _currentX;
  double _currentY;
  double _height;
  double _width;

  bool _isHorizontalActive = true;
  bool _isVerticalActive = true;

  @override
  void initState() {
    WidgetsBinding.instance.addPostFrameCallback(_afterLayout);

    super.initState();
  }

  _afterLayout(_) {
    _height = MediaQuery.of(context).size.height;
    _width = MediaQuery.of(context).size.width;
    _btnY = _height / 2;
    setState(() {});
  }

  _onDrag(details) {
    _updateCoordinates(
      details.globalPosition.dx,
      details.globalPosition.dy,
    );
  }

  _updateCoordinates(double x, double y) {
    setState(() {
      if (_isHorizontalActive) {
        _updateX(x);
      }
      if (_isVerticalActive) {
        _updateY(y);
      }
    });
  }

  _updateX(x) {
    var dx = _currentX - x;
    _currentX = x;
    _extraOffcet = _extraOffcet + dx;
    _extraOffcet = math.max(_extraOffcet, _rightPadding);
    _extraOffcet = math.min(_extraOffcet, _width - _btnSize);
  }

  _updateY(y) {
    var dy = _currentY - y;
    _currentY = y;
    _btnY = _btnY - dy;
    _btnY = math.max(_btnY, _btnSize);
    _btnY = math.min(_btnY, _height - _btnSize);
  }

  _listItem(String text, double height) {
    return Container(
      height: height,
      child: Text(text, style: TextStyle(fontSize: 20.0)),
    );
  }

  @override
  Widget build(BuildContext context) {
    return _height == null
        ? Container()
        : Stack(
            children: <Widget>[
              Container(
                padding: EdgeInsets.only(right: 30),
                color: Colors.blue,
                height: double.infinity,
                width: double.infinity,
                child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
                  _buildSwitch(type: dragType.vertical),
                  _buildSwitch(type: dragType.horizontal),
                  ...List.generate(
                    4,
                    (index) => _listItem('inside', 80),
                  ),
                ]),
              ),
              Positioned(
                right: _extraOffcet + _rightPadding,
                child: CustomPaint(
                  size: Size(_btnSize, _height),
                  painter: CurvedPainter(_btnSize, _btnY),
                ),
              ),
              Positioned(
                top: _btnY - _btnSize / 2 + 5,
                right: _extraOffcet + _rightPadding + 5,
                child: GestureDetector(
                  onPanDown: (details) {
                    _currentX = details.globalPosition.dx;
                    _currentY = details.globalPosition.dy;
                  },
                  onPanStart: _onDrag,
                  onPanUpdate: _onDrag,
                  child: Material(
                    type: MaterialType.circle,
                    color: Colors.white,
                    elevation: 8.0,
                    child: Container(
                      width: _btnSize - 10,
                      height: _btnSize - 10,
                      child: Icon(Icons.add),
                    ),
                  ),
                ),
              ),
              Positioned(
                top: 0,
                left: _width - _extraOffcet,
                child: Container(
                  color: Colors.white,
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: List.generate(8, (index) => _listItem('from right', 20)),
                  ),
                  height: _height,
                  width: _width,
                ),
              ),
            ],
          );
  }

  SwitchListTile _buildSwitch({dragType type}) {
    Function onChange;
    String titleText, sutitleText;
    bool value;

    if (type == dragType.horizontal) {
      value = _isHorizontalActive;
      titleText = 'Horizontal dragging';
      onChange = (newValue) => setState(() => _isHorizontalActive = newValue);
    } else {
      value = _isVerticalActive;
      titleText = 'Vertical dragging';
      onChange = (newValue) => setState(() => _isVerticalActive = newValue);
    }
    sutitleText = value ? 'active' : 'disabled';

    return SwitchListTile(
      value: value,
      onChanged: onChange,
      title: Text(titleText),
      subtitle: Text(sutitleText),
    );
  }
}

class CurvedPainter extends CustomPainter {
  CurvedPainter(this.btnSize, this.btnY);

  final double btnSize;
  final double btnY;

  @override
  void paint(Canvas canvas, Size size) {
    var halfBtnSize = btnSize / 2;
    var xMax = size.width;
    var yMax = size.height;

    var path = Path()
      ..moveTo(halfBtnSize, yMax)
      ..lineTo(halfBtnSize, btnY + halfBtnSize * 2)
      ..cubicTo(halfBtnSize, btnY + halfBtnSize, 0, btnY + halfBtnSize, 0, btnY)
      ..cubicTo(0, btnY - halfBtnSize, halfBtnSize, btnY - halfBtnSize, halfBtnSize,
          btnY - halfBtnSize * 2)
      ..lineTo(halfBtnSize, 0)
      ..lineTo(xMax, 0)
      ..lineTo(xMax, yMax);

    canvas.drawPath(
        path,
        Paint()
          ..color = Colors.white
          ..style = PaintingStyle.fill);
  }

  @override
  bool shouldRepaint(CurvedPainter oldDelegate) => oldDelegate.btnY != btnY;
}

这篇关于颤振设计曲线布局作为单个小部件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆