2

Is there any way to rotate the CupertinoPicker in Flutter by 90 degrees? So that you can pick horizontally and not vertically. Transform.rotate is not an option because then the width of the Picker is limited to the height of the parent widget. Or is there any good way to force the cupertino picker to be bigger than its parent widget?

Quasi
  • 576
  • 4
  • 13

2 Answers2

2

How about the RotatedBox widget?

RotatedBox(
  quarterTurns: 1,
  child: CupertinoPicker(...),
)

Unlike Transform, which applies a transform just prior to painting, this object applies its rotation prior to layout, which means the entire rotated box consumes only as much space as required by the rotated child.

josxha
  • 1,110
  • 8
  • 23
0

So I found 2 solutions. First you can use a RotatedBox. Thx to josxha for that idea. 2. solution: Make a complete custom picker. So if anyone has the same problem you can use my custom picker. The code is a total mess please dont judge lmao.

class CustomPicker extends StatefulWidget {
  CustomPicker(
      {@required double this.width,
      @required double this.height,
      @required double this.containerWidth,
      @required double this.containerHeight,
      @required double this.gapScaleFactor,
      @required List<Widget> this.childrenW,
      Function(int) this.onSnap});

  double width;
  double height;
  double containerWidth;
  double containerHeight;
  double gapScaleFactor;
  List<Widget> childrenW;
  Function(int) onSnap;

  _CustomPicker createState() => _CustomPicker(width, height, containerWidth,
      containerHeight, gapScaleFactor, childrenW, onSnap);
}

class _CustomPicker extends State<CustomPicker>
    with SingleTickerProviderStateMixin {
  AnimationController controller;
  double width;
  double height;
  double containerWidth;
  double containerHeight;
  double gapScaleFactor;
  double currentScrollX = 0;
  double oldAnimScrollX = 0;
  double animDistance = 0;
  int currentSnap = 0;
  List<Widget> childrenW;
  List<Positioned> scrollableContainer = [];
  final Function(int) onSnap;

  int currentPos;
  _CustomPicker(
      double this.width,
      double this.height,
      double this.containerWidth,
      double this.containerHeight,
      double this.gapScaleFactor,
      List<Widget> this.childrenW,
      Function(int) this.onSnap) {
    initController();
    init();
  }

  void initController() {
    controller = AnimationController(
      vsync: this,
      duration: Duration(milliseconds: 200),
      lowerBound: 0,
      upperBound: 1,
    )..addListener(() {
        setState(() {
          currentScrollX = oldAnimScrollX + controller.value * animDistance;
          init();
        });
      });
  }

  void init() {
    scrollableContainer.clear();
    if (currentScrollX < 0) {
      currentScrollX = 0;
    }
    double scrollableLength =
        (containerWidth + containerWidth * gapScaleFactor) *
                (childrenW.length) -
            containerWidth * gapScaleFactor;

    if (currentScrollX > scrollableLength - containerWidth) {
      currentScrollX = scrollableLength - containerWidth;
    }
    for (int i = 0; i < childrenW.length; i++) {
      double leftPos = width / 2 -
          containerWidth / 2 -
          currentScrollX +
          containerWidth * i +
          containerWidth * gapScaleFactor * i;
      double mid = width / 2 - containerWidth / 2;
      double topPos = containerHeight *
          0.9 *
          ((leftPos - mid).abs() / scrollableLength) /
          2;
      scrollableContainer.add(Positioned(
          //calculate X position
          left: leftPos,
          top: topPos,
          child: Container(
            height: containerHeight -
                containerHeight *
                    0.9 *
                    ((leftPos - mid).abs() / scrollableLength),
            width: containerWidth -
                containerWidth *
                    0.9 *
                    ((leftPos - mid).abs() / scrollableLength),
            child: childrenW[i],
          )));
    }
  }

  void lookForSnappoint() {
    double distance = 1000000;
    double animVal = 0;
    int index = -2032;
    for (int i = 0; i < scrollableContainer.length; i++) {
      double snappoint = width / 2 - containerWidth / 2;
      double currentLeftPos = width / 2 -
          containerWidth / 2 -
          currentScrollX +
          containerWidth * i +
          containerWidth * gapScaleFactor * i;
      if ((currentLeftPos - snappoint).abs() < distance) {
        distance = (currentLeftPos - snappoint).abs();
        animVal = currentLeftPos - snappoint;
        index = i;
      }
    }
    animDistance = animVal;
    oldAnimScrollX = currentScrollX;
    controller.reset();
    controller.forward();
    this.onSnap(index);
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      width: widget.width,
      height: widget.height,
      child: GestureDetector(
        onPanUpdate: (DragUpdateDetails dragUpdateDetails) {
          setState(() {
            this.currentScrollX -= dragUpdateDetails.delta.dx;
            init();
          });
        },
        onPanEnd: (DragEndDetails dragEndDetails) {
          lookForSnappoint();
        },
        behavior: HitTestBehavior.translucent,
        child: LayoutBuilder(builder: (context, constraint) {
          return Container(
            child: Stack(
              children: <Widget>[
                Stack(children: scrollableContainer),
              ],
            ),
          );
        }),
      ),
    );
  }
}
Quasi
  • 576
  • 4
  • 13