2

这里解决了有关设计此布局的问题。

在此处输入图像描述

我在使用它时遇到了问题,因为屏幕右侧的这条曲线不是小部件,当我想在绿色一侧有一些其他小部件时,我不能,因为设计的曲线不是从绿色布局中剪裁的小部件。

假设我想在屏幕右侧有这条曲线,下面有一些小部件。

源代码

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.

4

1 回答 1

6

您似乎需要下图中给出的类似内容。

更新:添加了拖动控件

在此处输入图像描述

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;
}
于 2019-08-22T19:58:25.430 回答