From 94fbf371e775a60bdb0ed925bac9c6e24dd3c602 Mon Sep 17 00:00:00 2001
From: Kevin <468561207@qq.com>
Date: Sun, 12 Jul 2020 02:48:37 +0800
Subject: [PATCH] =?UTF-8?q?CupertinoPopoverDirection=E6=B7=BB=E5=8A=A0?=
 =?UTF-8?q?=E4=BA=86left=E5=92=8Cright?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 CHANGELOG.md                               |   3 +
 README.md                                  |   2 +-
 example/lib/main.dart                      |   8 +
 example/lib/pages/table_demo.dart          |  29 +
 lib/cool_ui.dart                           |   6 +-
 lib/utils/scroll_utils.dart                |  14 +
 lib/widgets/popover/cupertino_popover.dart | 633 +++++++++++++--------
 lib/widgets/tables/table.dart              |  48 +-
 pubspec.yaml                               |   2 +-
 9 files changed, 508 insertions(+), 237 deletions(-)
 create mode 100644 example/lib/pages/table_demo.dart
 create mode 100644 lib/utils/scroll_utils.dart

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4e3b14d..82bfacb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,6 @@
+## [0.6.1]
+* TODO: CupertinoPopoverDirection娣诲姞浜唋eft鍜宺ight
+
 ## [0.6.0]
 * TODO: 閲嶆瀯浜嗛敭鐩樺脊鍑虹殑鏂瑰紡,淇闀挎寜杈撳叆妗嗘姤閿欓棶棰�
 
diff --git a/README.md b/README.md
index 715cf8e..9ead822 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@ Usage Add this to your package's pubspec.yaml file:
 Flutter >=1.17
 ``` yaml
 dependencies:
-  cool_ui: "^0.6.0"
+  cool_ui: "^0.6.1"
 ```
 
 Flutter >=1.7
diff --git a/example/lib/main.dart b/example/lib/main.dart
index 0bdfd58..1d80e12 100644
--- a/example/lib/main.dart
+++ b/example/lib/main.dart
@@ -2,6 +2,7 @@ import 'package:cool_ui_example/cool_u_i_example_icons.dart';
 import 'package:cool_ui_example/pages/custom_keyboard.dart';
 import 'package:cool_ui_example/pages/paint_event_demo.dart';
 import 'package:cool_ui_example/pages/popover_demo.dart';
+import 'package:cool_ui_example/pages/table_demo.dart';
 import 'package:cool_ui_example/pages/weui_toast_demo.dart';
 import 'package:cool_ui/cool_ui.dart';
 import 'package:flutter/material.dart';
@@ -113,6 +114,13 @@ class _MyHomePageState extends State<MyHomePage> {
                 Navigator.of(context).push(MaterialPageRoute(
                     builder: (context) => CustomKeyboardDemo()));
               },
+            ),
+            ListTile(
+              title: Text("TableEvent"),
+              onTap: () {
+                Navigator.of(context).push(MaterialPageRoute(
+                    builder: (context) => TableDemo()));
+              },
             )
           ],
         ));
diff --git a/example/lib/pages/table_demo.dart b/example/lib/pages/table_demo.dart
new file mode 100644
index 0000000..839a0c8
--- /dev/null
+++ b/example/lib/pages/table_demo.dart
@@ -0,0 +1,29 @@
+import 'package:flutter/material.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:cool_ui/cool_ui.dart';
+
+
+class TableDemo extends StatefulWidget{
+  @override
+  State<StatefulWidget> createState() {
+    // TODO: implement createState
+    return TableDemoState();
+  }
+
+}
+
+class TableDemoState extends State<TableDemo>{
+
+
+  @override
+  Widget build(BuildContext context) {
+    // TODO: implement build
+    return Scaffold(
+        appBar: AppBar(
+          title: Text("Table Demo"),
+        ),
+        body: CoolTable()
+    );
+  }
+
+}
\ No newline at end of file
diff --git a/lib/cool_ui.dart b/lib/cool_ui.dart
index 477734c..90435ae 100644
--- a/lib/cool_ui.dart
+++ b/lib/cool_ui.dart
@@ -12,6 +12,7 @@ import 'package:flutter/rendering.dart';
 
 part 'utils/widget_util.dart';
 part 'utils/screen_util.dart';
+part 'utils/scroll_utils.dart';
 
 part 'icons/cool_ui_icons.dart';
 
@@ -26,4 +27,7 @@ part 'keyboards/keyboard_manager.dart';
 part 'keyboards/number_keyboard.dart';
 part 'keyboards/keyboard_controller.dart';
 part 'keyboards/keyboard_media_query.dart';
-part 'keyboards/keyboard_root.dart';
\ No newline at end of file
+part 'keyboards/keyboard_root.dart';
+
+
+part 'widgets/tables/table.dart';
\ No newline at end of file
diff --git a/lib/utils/scroll_utils.dart b/lib/utils/scroll_utils.dart
new file mode 100644
index 0000000..37e9adc
--- /dev/null
+++ b/lib/utils/scroll_utils.dart
@@ -0,0 +1,14 @@
+part of cool_ui;
+
+connectScroll(ScrollController scroll1, ScrollController scroll2){
+  scroll1.addListener(() {
+    if(scroll2.offset != scroll1.offset){
+      scroll2.jumpTo(scroll1.offset);
+    }
+  });  
+  scroll2.addListener(() {
+    if(scroll1.offset != scroll2.offset){
+      scroll1.jumpTo(scroll2.offset);
+    }
+  });  
+}
diff --git a/lib/widgets/popover/cupertino_popover.dart b/lib/widgets/popover/cupertino_popover.dart
index cdd951a..0b18af3 100644
--- a/lib/widgets/popover/cupertino_popover.dart
+++ b/lib/widgets/popover/cupertino_popover.dart
@@ -1,12 +1,10 @@
 part of cool_ui;
 
-enum CupertinoPopoverDirection{
-  top,
-  bottom,
-}
+enum CupertinoPopoverDirection { top, bottom, left, right }
 
 typedef BoolCallback = bool Function();
-class CupertinoPopoverButton extends StatelessWidget{
+
+class CupertinoPopoverButton extends StatelessWidget {
   final Widget child;
   final WidgetBuilder popoverBuild;
   final double popoverWidth;
@@ -20,34 +18,35 @@ class CupertinoPopoverButton extends StatelessWidget{
   final Color barrierColor;
   final CupertinoPopoverDirection direction;
 
-  CupertinoPopoverButton({
-    @required this.child,
-    this.popoverBuild,
-    this.popoverColor=Colors.white,
-    this.popoverBoxShadow,
-    this.popoverWidth,
-    this.popoverHeight,
-    BoxConstraints popoverConstraints,
-    this.direction = CupertinoPopoverDirection.bottom,
-    this.onTap,
-    this.transitionDuration=const Duration(milliseconds: 200),
-    this.barrierColor = Colors.black54,
-    this.radius=8.0}):
-        assert(popoverBuild != null),
+  CupertinoPopoverButton(
+      {@required this.child,
+      this.popoverBuild,
+      this.popoverColor = Colors.white,
+      this.popoverBoxShadow,
+      this.popoverWidth,
+      this.popoverHeight,
+      BoxConstraints popoverConstraints,
+      this.direction = CupertinoPopoverDirection.bottom,
+      this.onTap,
+      this.transitionDuration = const Duration(milliseconds: 200),
+      this.barrierColor = Colors.black54,
+      this.radius = 8.0})
+      : assert(popoverBuild != null),
         this.popoverConstraints =
-        (popoverWidth != null || popoverHeight != null)
-
-            ? popoverConstraints?.tighten(width: popoverWidth, height: popoverHeight)
-            ?? BoxConstraints.tightFor(width: popoverWidth, height: popoverHeight)
-            : popoverConstraints;
+            (popoverWidth != null || popoverHeight != null)
+                ? popoverConstraints?.tighten(
+                        width: popoverWidth, height: popoverHeight) ??
+                    BoxConstraints.tightFor(
+                        width: popoverWidth, height: popoverHeight)
+                : popoverConstraints;
 
   @override
   Widget build(BuildContext context) {
     // TODO: implement build
     return GestureDetector(
       behavior: HitTestBehavior.translucent,
-      onTap: (){
-        if(onTap != null && onTap()){
+      onTap: () {
+        if (onTap != null && onTap()) {
           return;
         }
         var offset = _WidgetUtil.getWidgetLocalToGlobal(context);
@@ -55,20 +54,20 @@ class CupertinoPopoverButton extends StatelessWidget{
         var body;
         showGeneralDialog(
           context: context,
-          pageBuilder: (BuildContext buildContext, Animation<double> animation, Animation<double> secondaryAnimation) {
-            return Builder(
-                builder: (BuildContext context) {
-                  return Container();
-                }
-            );
-
+          pageBuilder: (BuildContext buildContext, Animation<double> animation,
+              Animation<double> secondaryAnimation) {
+            return Builder(builder: (BuildContext context) {
+              return Container();
+            });
           },
           barrierDismissible: true,
-          barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel,
+          barrierLabel:
+              MaterialLocalizations.of(context).modalBarrierDismissLabel,
           barrierColor: this.barrierColor,
           transitionDuration: transitionDuration,
-          transitionBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
-            if(body == null){
+          transitionBuilder: (BuildContext context, Animation<double> animation,
+              Animation<double> secondaryAnimation, Widget child) {
+            if (body == null) {
               body = popoverBuild(context);
             }
             return FadeTransition(
@@ -77,9 +76,10 @@ class CupertinoPopoverButton extends StatelessWidget{
                 curve: Curves.easeOut,
               ),
               child: CupertinoPopover(
-                attachRect:Rect.fromLTWH(offset.dx, offset.dy, bounds.width, bounds.height),
+                attachRect: Rect.fromLTWH(
+                    offset.dx, offset.dy, bounds.width, bounds.height),
                 child: body,
-                constraints:popoverConstraints,
+                constraints: popoverConstraints,
                 color: popoverColor,
                 boxShadow: popoverBoxShadow,
                 context: context,
@@ -88,7 +88,8 @@ class CupertinoPopoverButton extends StatelessWidget{
                 direction: direction,
               ),
             );
-          },);
+          },
+        );
       },
       child: child,
     );
@@ -106,44 +107,51 @@ class CupertinoPopover extends StatefulWidget {
   final Animation<double> doubleAnimation;
   BoxConstraints constraints;
 
-  CupertinoPopover({
-    @required this.attachRect,
-    @required this.child,
-    BoxConstraints constraints,
-    this.color=Colors.white,
-    this.boxShadow,
-    @required BuildContext context,
-    this.direction = CupertinoPopoverDirection.bottom,
-    this.doubleAnimation,
-    this.radius=8.0}):super(){
+  CupertinoPopover(
+      {@required this.attachRect,
+      @required this.child,
+      BoxConstraints constraints,
+      this.color = Colors.white,
+      this.boxShadow,
+      @required BuildContext context,
+      this.direction = CupertinoPopoverDirection.bottom,
+      this.doubleAnimation,
+      this.radius = 8.0})
+      : super() {
     BoxConstraints temp;
-    if(constraints != null){
-      temp = BoxConstraints(maxHeight:123.0,maxWidth:150.0).copyWith(
-        minWidth: constraints.minWidth.isFinite?constraints.minWidth:null,
-        minHeight: constraints.minHeight.isFinite?constraints.minHeight:null,
-        maxWidth: constraints.maxWidth.isFinite?constraints.maxWidth:null,
-        maxHeight: constraints.maxHeight.isFinite?constraints.maxHeight:null,
+    if (constraints != null) {
+      temp = BoxConstraints(maxHeight: 123.0, maxWidth: 150.0).copyWith(
+        minWidth: constraints.minWidth.isFinite ? constraints.minWidth : null,
+        minHeight:
+            constraints.minHeight.isFinite ? constraints.minHeight : null,
+        maxWidth: constraints.maxWidth.isFinite ? constraints.maxWidth : null,
+        maxHeight:
+            constraints.maxHeight.isFinite ? constraints.maxHeight : null,
       );
-    }else{
-      temp=BoxConstraints(maxHeight:123.0,maxWidth:150.0);
+    } else {
+      temp = BoxConstraints(maxHeight: 123.0, maxWidth: 150.0);
     }
-    this.constraints = temp.copyWith(maxHeight: temp.maxHeight + CupertinoPopoverState._arrowHeight);
+    this.constraints = temp.copyWith(
+        maxHeight: temp.maxHeight + CupertinoPopoverState._arrowHeight);
   }
 
   @override
   CupertinoPopoverState createState() => new CupertinoPopoverState();
 
-
   @override
   void debugFillProperties(DiagnosticPropertiesBuilder properties) {
     super.debugFillProperties(properties);
-    properties.add(DiagnosticsProperty<BoxConstraints>('constraints', constraints, showName: false));
+    properties.add(DiagnosticsProperty<BoxConstraints>(
+        'constraints', constraints,
+        showName: false));
     properties.add(DiagnosticsProperty<Color>('color', color, showName: false));
-    properties.add(DiagnosticsProperty<double>('double', radius, showName: false));
+    properties
+        .add(DiagnosticsProperty<double>('double', radius, showName: false));
   }
 }
 
-class CupertinoPopoverState extends State<CupertinoPopover>  with TickerProviderStateMixin{
+class CupertinoPopoverState extends State<CupertinoPopover>
+    with TickerProviderStateMixin {
   static const double _arrowWidth = 12.0;
   static const double _arrowHeight = 8.0;
 
@@ -173,33 +181,39 @@ class CupertinoPopoverState extends State<CupertinoPopover>  with TickerProvider
             color: widget.color,
             boxShadow: widget.boxShadow,
             direction: widget.direction,
-            child: Material(type: MaterialType.transparency, child: widget.child),
+            child:
+                Material(type: MaterialType.transparency, child: widget.child),
           ),
         )
       ],
     );
   }
-
 }
 
-
-class _CupertionPopoverPosition extends SingleChildRenderObjectWidget{
+class _CupertionPopoverPosition extends SingleChildRenderObjectWidget {
   final Rect attachRect;
   final Animation<double> scale;
   final BoxConstraints constraints;
   final CupertinoPopoverDirection direction;
 
-  _CupertionPopoverPosition({Widget child,this.attachRect,this.constraints,this.scale, this.direction}):super(child:child);
+  _CupertionPopoverPosition(
+      {Widget child,
+      this.attachRect,
+      this.constraints,
+      this.scale,
+      this.direction})
+      : super(child: child);
 
   @override
-  RenderObject createRenderObject(BuildContext context) =>_CupertionPopoverPositionRenderObject(
-      attachRect:attachRect,
-      direction: direction,
-      constraints:constraints);
-
+  RenderObject createRenderObject(BuildContext context) =>
+      _CupertionPopoverPositionRenderObject(
+          attachRect: attachRect,
+          direction: direction,
+          constraints: constraints);
 
   @override
-  void updateRenderObject(BuildContext context, _CupertionPopoverPositionRenderObject renderObject) {
+  void updateRenderObject(BuildContext context,
+      _CupertionPopoverPositionRenderObject renderObject) {
     renderObject
       ..attachRect = attachRect
       ..direction = direction
@@ -209,18 +223,17 @@ class _CupertionPopoverPosition extends SingleChildRenderObjectWidget{
   @override
   void debugFillProperties(DiagnosticPropertiesBuilder properties) {
     super.debugFillProperties(properties);
-    properties.add(DiagnosticsProperty<BoxConstraints>('constraints', constraints, showName: false));
+    properties.add(DiagnosticsProperty<BoxConstraints>(
+        'constraints', constraints,
+        showName: false));
   }
-
 }
 
-class _CupertionPopoverPositionRenderObject extends RenderShiftedBox{
-
+class _CupertionPopoverPositionRenderObject extends RenderShiftedBox {
   CupertinoPopoverDirection get direction => _direction;
   CupertinoPopoverDirection _direction;
   set direction(CupertinoPopoverDirection value) {
-    if (_direction == value)
-      return;
+    if (_direction == value) return;
     _direction = value;
     markNeedsLayout();
   }
@@ -228,92 +241,133 @@ class _CupertionPopoverPositionRenderObject extends RenderShiftedBox{
   Rect get attachRect => _attachRect;
   Rect _attachRect;
   set attachRect(Rect value) {
-    if (_attachRect == value)
-      return;
+    if (_attachRect == value) return;
     _attachRect = value;
     markNeedsLayout();
   }
 
-
-
   BoxConstraints get additionalConstraints => _additionalConstraints;
   BoxConstraints _additionalConstraints;
   set additionalConstraints(BoxConstraints value) {
-    if (_additionalConstraints == value)
-      return;
+    if (_additionalConstraints == value) return;
     _additionalConstraints = value;
     markNeedsLayout();
   }
 
-
-  _CupertionPopoverPositionRenderObject({RenderBox child,Rect attachRect,Color color,BoxConstraints constraints,Animation<double> scale, CupertinoPopoverDirection direction}) : super(child){
+  _CupertionPopoverPositionRenderObject(
+      {RenderBox child,
+      Rect attachRect,
+      Color color,
+      BoxConstraints constraints,
+      Animation<double> scale,
+      CupertinoPopoverDirection direction})
+      : super(child) {
     this._attachRect = attachRect;
     this._additionalConstraints = constraints;
     this._direction = direction;
   }
 
-
   @override
   void performLayout() {
-    child.layout(_additionalConstraints.enforce(constraints), parentUsesSize: true);
-    size = Size(constraints.maxWidth,constraints.maxHeight);
+    child.layout(_additionalConstraints.enforce(constraints),
+        parentUsesSize: true);
+    size = Size(constraints.maxWidth, constraints.maxHeight);
 
     final BoxParentData childParentData = child.parentData;
 
     childParentData.offset = calcOffset(child.size);
   }
 
-  Offset calcOffset(Size size){
-    double bodyLeft = 0.0;
-    CupertinoPopoverDirection calcDirection = _calcDirection(attachRect,size, direction); 
-    
-
-    if(attachRect.left > size.width / 2 &&
-        _ScreenUtil.getInstance().screenWidth - attachRect.right > size.width / 2){ //鍒ゆ柇鏄惁鍙互鍦ㄤ腑闂�
-      bodyLeft = attachRect.left +  attachRect.width / 2 - size.width / 2;
-    }else if(attachRect.left < size.width / 2){ //闈犲乏
-      bodyLeft = 10.0;
-    }else{ //闈犲彸
-      bodyLeft = _ScreenUtil.getInstance().screenWidth - 10.0 - size.width;
-    }
-
-    if(calcDirection == CupertinoPopoverDirection.bottom){
-      return Offset(bodyLeft,attachRect.bottom);
-    }else{
-      return Offset(bodyLeft,attachRect.top - size.height - CupertinoPopoverState._arrowHeight);
+  Offset calcOffset(Size size) {
+    CupertinoPopoverDirection calcDirection =
+        _calcDirection(attachRect, size, direction);
+
+    if (calcDirection == CupertinoPopoverDirection.top ||
+        calcDirection == CupertinoPopoverDirection.bottom) {
+      double bodyLeft = 0.0;
+      // 涓婁笅
+      if (attachRect.left > size.width / 2 &&
+          _ScreenUtil.getInstance().screenWidth - attachRect.right >
+              size.width / 2) {
+        //鍒ゆ柇鏄惁鍙互鍦ㄤ腑闂�
+        bodyLeft = attachRect.left + attachRect.width / 2 - size.width / 2;
+      } else if (attachRect.left < size.width / 2) {
+        //闈犲乏
+        bodyLeft = 10.0;
+      } else {
+        //闈犲彸
+        bodyLeft = _ScreenUtil.getInstance().screenWidth - 10.0 - size.width;
+      }
+
+      if (calcDirection == CupertinoPopoverDirection.bottom) {
+        return Offset(bodyLeft, attachRect.bottom);
+      } else {
+        return Offset(bodyLeft,
+            attachRect.top - size.height);
+      }
+    } else {
+      double bodyTop = 0.0;
+      if (attachRect.top > size.height / 2 &&
+          _ScreenUtil.getInstance().screenHeight - attachRect.bottom >
+              size.height / 2) {
+        //鍒ゆ柇鏄惁鍙互鍦ㄤ腑闂�
+        bodyTop = attachRect.top + attachRect.height / 2 - size.height / 2;
+      } else if (attachRect.top < size.height / 2) {
+        //闈犲乏
+        bodyTop = 10.0;
+      } else {
+        //闈犲彸
+        bodyTop = _ScreenUtil.getInstance().screenHeight - 10.0 - size.height;
+      }
+
+      if (calcDirection == CupertinoPopoverDirection.right) {
+        return Offset(attachRect.right, bodyTop);
+      } else {
+        return Offset(
+            attachRect.left - size.width,
+            bodyTop);
+      }
     }
   }
 
-
   @override
   void debugFillProperties(DiagnosticPropertiesBuilder properties) {
     super.debugFillProperties(properties);
-    properties.add(DiagnosticsProperty<BoxConstraints>('additionalConstraints', additionalConstraints));
+    properties.add(DiagnosticsProperty<BoxConstraints>(
+        'additionalConstraints', additionalConstraints));
   }
 }
 
-class _CupertionPopoverContext extends SingleChildRenderObjectWidget{
+class _CupertionPopoverContext extends SingleChildRenderObjectWidget {
   final Rect attachRect;
   final Color color;
   final List<BoxShadow> boxShadow;
   final Animation<double> scale;
   final double radius;
   final CupertinoPopoverDirection direction;
-  _CupertionPopoverContext({Widget child,this.attachRect,this.color, this.boxShadow,this.scale,this.radius, this.direction}):super(child:child);
+  _CupertionPopoverContext(
+      {Widget child,
+      this.attachRect,
+      this.color,
+      this.boxShadow,
+      this.scale,
+      this.radius,
+      this.direction})
+      : super(child: child);
 
   @override
-  RenderObject createRenderObject(BuildContext context) => _CupertionPopoverContextRenderObject(
-      attachRect: attachRect,
-      color: color,
-      boxShadow: boxShadow,
-      scale: scale.value,
-      direction: direction,
-      radius: radius
-  );
-
+  RenderObject createRenderObject(BuildContext context) =>
+      _CupertionPopoverContextRenderObject(
+          attachRect: attachRect,
+          color: color,
+          boxShadow: boxShadow,
+          scale: scale.value,
+          direction: direction,
+          radius: radius);
 
   @override
-  void updateRenderObject(BuildContext context, _CupertionPopoverContextRenderObject renderObject) {
+  void updateRenderObject(
+      BuildContext context, _CupertionPopoverContextRenderObject renderObject) {
     renderObject
       ..attachRect = attachRect
       ..color = color
@@ -322,35 +376,29 @@ class _CupertionPopoverContext extends SingleChildRenderObjectWidget{
       ..direction = direction
       ..radius = radius;
   }
-
 }
 
-class _CupertionPopoverContextRenderObject extends RenderShiftedBox{
+class _CupertionPopoverContextRenderObject extends RenderShiftedBox {
   CupertinoPopoverDirection get direction => _direction;
   CupertinoPopoverDirection _direction;
   set direction(CupertinoPopoverDirection value) {
-    if (_direction == value)
-      return;
+    if (_direction == value) return;
     _direction = value;
     markNeedsLayout();
   }
 
-
   Rect get attachRect => _attachRect;
   Rect _attachRect;
   set attachRect(Rect value) {
-    if (_attachRect == value)
-      return;
+    if (_attachRect == value) return;
     _attachRect = value;
     markNeedsLayout();
   }
 
-
   Color get color => _color;
   Color _color;
   set color(Color value) {
-    if (_color == value)
-      return;
+    if (_color == value) return;
     _color = value;
     markNeedsLayout();
   }
@@ -358,13 +406,11 @@ class _CupertionPopoverContextRenderObject extends RenderShiftedBox{
   List<BoxShadow> get boxShadow => _boxShadow;
   List<BoxShadow> _boxShadow;
   set boxShadow(List<BoxShadow> value) {
-    if (_boxShadow == value)
-      return;
+    if (_boxShadow == value) return;
     _boxShadow = value;
     markNeedsLayout();
   }
 
-
   double get scale => _scale;
   double _scale;
   set scale(double value) {
@@ -375,18 +421,23 @@ class _CupertionPopoverContextRenderObject extends RenderShiftedBox{
     markNeedsLayout();
   }
 
-
   double get radius => _radius;
   double _radius;
   set radius(double value) {
-    if (_radius == value)
-      return;
+    if (_radius == value) return;
     _radius = value;
     markNeedsLayout();
   }
 
-
-  _CupertionPopoverContextRenderObject({RenderBox child,Rect attachRect,Color color, List<BoxShadow> boxShadow,double scale,double radius, CupertinoPopoverDirection direction}) : super(child){
+  _CupertionPopoverContextRenderObject(
+      {RenderBox child,
+      Rect attachRect,
+      Color color,
+      List<BoxShadow> boxShadow,
+      double scale,
+      double radius,
+      CupertinoPopoverDirection direction})
+      : super(child) {
     this._attachRect = attachRect;
     this._color = color;
     this._boxShadow = boxShadow;
@@ -395,19 +446,42 @@ class _CupertionPopoverContextRenderObject extends RenderShiftedBox{
     this._direction = direction;
   }
 
-
   @override
   void performLayout() {
     assert(constraints.maxHeight.isFinite);
-    BoxConstraints childConstraints = BoxConstraints(maxHeight: constraints.maxHeight - CupertinoPopoverState._arrowHeight).enforce(constraints);
+    BoxConstraints childConstraints;
+
+    if (direction == CupertinoPopoverDirection.top ||
+        direction == CupertinoPopoverDirection.bottom) {
+      childConstraints = BoxConstraints(
+              maxHeight:
+                  constraints.maxHeight - CupertinoPopoverState._arrowHeight)
+          .enforce(constraints);
+    } else {
+      childConstraints = BoxConstraints(
+              maxWidth:
+                  constraints.maxWidth - CupertinoPopoverState._arrowHeight)
+          .enforce(constraints);
+    }
 
     child.layout(childConstraints, parentUsesSize: true);
-    size = Size(child.size.width,child.size.height + CupertinoPopoverState._arrowHeight);
+
+    if (direction == CupertinoPopoverDirection.top ||
+        direction == CupertinoPopoverDirection.bottom) {
+      size = Size(child.size.width,
+          child.size.height + CupertinoPopoverState._arrowHeight);
+    } else {
+      size = Size(child.size.width + CupertinoPopoverState._arrowHeight,
+          child.size.height);
+    }
+    CupertinoPopoverDirection calcDirection =
+        _calcDirection(attachRect, size, direction);
+
     final BoxParentData childParentData = child.parentData;
-    CupertinoPopoverDirection calcDirection = _calcDirection(attachRect,size, direction); 
-    if(calcDirection == CupertinoPopoverDirection.bottom)
-    {
+    if (calcDirection == CupertinoPopoverDirection.bottom) {
       childParentData.offset = Offset(0.0, CupertinoPopoverState._arrowHeight);
+    } else if (calcDirection == CupertinoPopoverDirection.right) {
+      childParentData.offset = Offset(CupertinoPopoverState._arrowHeight, 0.0);
     }
   }
 
@@ -417,120 +491,223 @@ class _CupertionPopoverContextRenderObject extends RenderShiftedBox{
     Matrix4 transform = Matrix4.identity();
 //
 
-    CupertinoPopoverDirection calcDirection = _calcDirection(attachRect,size, direction); 
-    var isArrowUp = calcDirection == CupertinoPopoverDirection.bottom;
+    CupertinoPopoverDirection calcDirection =
+        _calcDirection(attachRect, size, direction);
+    // var isArrowUp = calcDirection == CupertinoPopoverDirection.bottom;
+    Rect arrowRect;
+    Offset translation;
+    Rect bodyRect;
+
+    final BoxParentData childParentData = child.parentData;
+    bodyRect = childParentData.offset & child.size;
+
+    var arrowLeft = attachRect.left + // 鐢ㄤ簬 Top鍜孊ottom
+        attachRect.width / 2 -
+        CupertinoPopoverState._arrowWidth / 2 -
+        offset.dx;
+
+    var arrowTop = attachRect.top + // 鐢ㄤ簬 Left鍜孯ight
+        attachRect.height / 2 -
+        CupertinoPopoverState._arrowWidth / 2 -
+        offset.dy;
+
+    switch (calcDirection) {
+      case CupertinoPopoverDirection.top:
+        arrowRect = Rect.fromLTWH(
+            arrowLeft,
+            child.size.height,
+            CupertinoPopoverState._arrowWidth,
+            CupertinoPopoverState._arrowHeight);
+        translation = Offset(
+            arrowLeft + CupertinoPopoverState._arrowWidth / 2, size.height);
+
+        break;
+      case CupertinoPopoverDirection.left:
+        arrowRect = Rect.fromLTWH(
+            child.size.width,
+            arrowTop,
+            CupertinoPopoverState._arrowHeight,
+            CupertinoPopoverState._arrowWidth);
+        translation = Offset(
+            size.width, arrowTop + CupertinoPopoverState._arrowWidth / 2);
+        break;
+      case CupertinoPopoverDirection.bottom:
+        arrowRect = Rect.fromLTWH(
+            arrowLeft,
+            0,
+            CupertinoPopoverState._arrowWidth,
+            CupertinoPopoverState._arrowHeight);
+        translation =
+            Offset(arrowLeft + CupertinoPopoverState._arrowWidth / 2, 0);
+        break;
+      case CupertinoPopoverDirection.right:
+        arrowRect = Rect.fromLTWH(
+            0,
+            arrowTop,
+            CupertinoPopoverState._arrowHeight,
+            CupertinoPopoverState._arrowWidth);
+        translation = Offset(
+            0, arrowTop + CupertinoPopoverState._arrowWidth / 2);
+        break;
+      default:
+    }
 
-    var arrowLeft =attachRect.left + attachRect.width / 2 - CupertinoPopoverState._arrowWidth / 2 - offset.dx;
-    var translation = Offset(arrowLeft + CupertinoPopoverState._arrowWidth / 2,isArrowUp?0.0:size.height);
     transform.translate(translation.dx, translation.dy);
     transform.scale(scale, scale, 1.0);
     transform.translate(-translation.dx, -translation.dy);
-    Rect arrowRect = Rect.fromLTWH(
-        arrowLeft,
-        isArrowUp?0.0:child.size.height,
-        CupertinoPopoverState._arrowWidth,
-        CupertinoPopoverState._arrowHeight);
-    Rect bodyRect = Offset(0.0, isArrowUp?CupertinoPopoverState._arrowHeight:0.0) & child.size;
-
-    _paintShadows(context, transform, offset, isArrowUp,arrowRect,bodyRect);
-
-    Path clipPath = _getClip(isArrowUp,arrowRect,bodyRect);
-    context.pushClipPath(needsCompositing,
-        offset,offset & size,
-        clipPath,(context,offset){
-          context.pushTransform(needsCompositing, offset, transform,(context,offset){
-            final Paint backgroundPaint = Paint();
-            backgroundPaint.color = color;
-            context.canvas.drawRect(offset & size, backgroundPaint);
-            super.paint(context,offset);
-          });
-
-        });
-  }
 
+    _paintShadows(
+        context, transform, offset, calcDirection, arrowRect, bodyRect);
+
+    Path clipPath = _getClip(calcDirection, arrowRect, bodyRect);
+    context.pushClipPath(needsCompositing, offset, offset & size, clipPath,
+        (context, offset) {
+      context.pushTransform(needsCompositing, offset, transform,
+          (context, offset) {
+        final Paint backgroundPaint = Paint();
+        backgroundPaint.color = color;
+        context.canvas.drawRect(offset & size, backgroundPaint);
+        super.paint(context, offset);
+      });
+    });
+  }
 
-  
-  void _paintShadows(PaintingContext context, Matrix4 transform, Offset offset, bool isArrowUp,Rect arrowRect,Rect bodyRect) {
-    if (boxShadow == null)
-      return;
+  void _paintShadows(PaintingContext context, Matrix4 transform, Offset offset,
+      CupertinoPopoverDirection direction, Rect arrowRect, Rect bodyRect) {
+    if (boxShadow == null) return;
     for (final BoxShadow boxShadow in boxShadow) {
       final Paint paint = boxShadow.toPaint();
-      arrowRect = arrowRect.shift(offset).shift(boxShadow.offset).inflate(boxShadow.spreadRadius);
-      bodyRect = bodyRect.shift(offset).shift(boxShadow.offset).inflate(boxShadow.spreadRadius);
-      Path path = _getClip(isArrowUp, arrowRect, bodyRect);
-      
-      context.pushTransform(needsCompositing, offset, transform,(context,offset){
-        context.canvas.drawPath(path,paint);
+      arrowRect = arrowRect
+          .shift(offset)
+          .shift(boxShadow.offset)
+          .inflate(boxShadow.spreadRadius);
+      bodyRect = bodyRect
+          .shift(offset)
+          .shift(boxShadow.offset)
+          .inflate(boxShadow.spreadRadius);
+      Path path = _getClip(direction, arrowRect, bodyRect);
+
+      context.pushTransform(needsCompositing, offset, transform,
+          (context, offset) {
+        context.canvas.drawPath(path, paint);
       });
     }
   }
-  
-  Path _getClip(bool isArrowUp,Rect arrowRect,Rect bodyRect) {
-    Path path = new Path();
 
-    if(isArrowUp)
-    {
+  Path _getClip(
+      CupertinoPopoverDirection direction, Rect arrowRect, Rect bodyRect) {
+    Path path = new Path();
 
-      path.moveTo(arrowRect.left,arrowRect.bottom); //绠ご
-      path.lineTo(arrowRect.left + arrowRect.width / 2, arrowRect.top);
+    if (direction == CupertinoPopoverDirection.top) {
+      path.moveTo(arrowRect.left, arrowRect.top); //绠ご
+      path.lineTo(arrowRect.left + arrowRect.width / 2, arrowRect.bottom);
+      path.lineTo(arrowRect.right, arrowRect.top);
+
+      path.lineTo(bodyRect.right - radius, bodyRect.bottom); //鍙充笅瑙�
+      path.conicTo(bodyRect.right, bodyRect.bottom, bodyRect.right,
+          bodyRect.bottom - radius, 1.0);
+
+      path.lineTo(bodyRect.right, bodyRect.top + radius); //鍙充笂瑙�
+      path.conicTo(bodyRect.right, bodyRect.top, bodyRect.right - radius,
+          bodyRect.top, 1.0);
+
+      path.lineTo(bodyRect.left + radius, bodyRect.top); //宸︿笂瑙�
+      path.conicTo(bodyRect.left, bodyRect.top, bodyRect.left,
+          bodyRect.top + radius, 1.0);
+
+      path.lineTo(bodyRect.left, bodyRect.bottom - radius); //宸︿笅瑙�
+      path.conicTo(bodyRect.left, bodyRect.bottom, bodyRect.left + radius,
+          bodyRect.bottom, 1.0);
+    } else if (direction == CupertinoPopoverDirection.right) {
+      path.moveTo(arrowRect.right, arrowRect.top); //绠ご
+      path.lineTo(arrowRect.left, arrowRect.top + arrowRect.height / 2);
       path.lineTo(arrowRect.right, arrowRect.bottom);
 
-      path.lineTo(bodyRect.right - radius,bodyRect.top); //鍙充笂瑙�
-      path.conicTo(bodyRect.right,bodyRect.top
-          ,bodyRect.right,bodyRect.top + radius,1.0);
+      path.lineTo(bodyRect.left, bodyRect.bottom - radius); //宸︿笅瑙�
+      path.conicTo(bodyRect.left, bodyRect.bottom, bodyRect.left + radius,
+          bodyRect.bottom, 1.0);
+
+      path.lineTo(bodyRect.right - radius, bodyRect.bottom); //鍙充笅瑙�
+      path.conicTo(bodyRect.right, bodyRect.bottom, bodyRect.right,
+          bodyRect.bottom - radius, 1.0);
 
-      path.lineTo(bodyRect.right,bodyRect.bottom - radius);  //鍙充笅瑙�
-      path.conicTo(bodyRect.right,bodyRect.bottom
-          ,bodyRect.right -radius ,bodyRect.bottom,1.0);
+      path.lineTo(bodyRect.right, bodyRect.top + radius); //鍙充笂瑙�
+      path.conicTo(bodyRect.right, bodyRect.top, bodyRect.right - radius,
+          bodyRect.top, 1.0);
 
+      path.lineTo(bodyRect.left + radius, bodyRect.top); //宸︿笂瑙�
+      path.conicTo(bodyRect.left, bodyRect.top, bodyRect.left,
+          bodyRect.top + radius, 1.0);
+    } else if (direction == CupertinoPopoverDirection.left) {
+      path.moveTo(arrowRect.left, arrowRect.top); //绠ご
+      path.lineTo(arrowRect.right, arrowRect.top + arrowRect.height / 2);
+      path.lineTo(arrowRect.left, arrowRect.bottom);
+
+      path.lineTo(bodyRect.right, bodyRect.bottom - radius); //鍙充笅瑙�
+      path.conicTo(bodyRect.right, bodyRect.bottom, bodyRect.right - radius,
+          bodyRect.bottom, 1.0);
 
       path.lineTo(bodyRect.left + radius, bodyRect.bottom); //宸︿笅瑙�
-      path.conicTo(bodyRect.left,bodyRect.bottom
-          ,bodyRect.left ,bodyRect.bottom - radius,1.0);
+      path.conicTo(bodyRect.left, bodyRect.bottom, bodyRect.left,
+          bodyRect.bottom - radius, 1.0);
 
       path.lineTo(bodyRect.left, bodyRect.top + radius); //宸︿笂瑙�
-      path.conicTo(bodyRect.left,bodyRect.top
-          ,bodyRect.left + radius,bodyRect.top,1.0);
-    }else{
-
-      path.moveTo(bodyRect.left + radius,bodyRect.top);
+      path.conicTo(bodyRect.left, bodyRect.top, bodyRect.left + radius,
+          bodyRect.top, 1.0);
+
+      path.lineTo(bodyRect.right - radius, bodyRect.top); //鍙充笂瑙�
+      path.conicTo(bodyRect.right, bodyRect.top, bodyRect.right,
+          bodyRect.top + radius, 1.0);
+    } else {
+      path.moveTo(arrowRect.left, arrowRect.bottom); //绠ご
+      path.lineTo(arrowRect.left + arrowRect.width / 2, arrowRect.top);
+      path.lineTo(arrowRect.right, arrowRect.bottom);
 
-      path.lineTo(bodyRect.right - radius,bodyRect.top); //鍙充笂瑙�
-      path.conicTo(bodyRect.right,bodyRect.top
-          ,bodyRect.right,bodyRect.top + radius,1.0);
+      path.lineTo(bodyRect.right - radius, bodyRect.top); //鍙充笂瑙�
+      path.conicTo(bodyRect.right, bodyRect.top, bodyRect.right,
+          bodyRect.top + radius, 1.0);
 
-      path.lineTo(bodyRect.right,bodyRect.bottom - radius);  //鍙充笅瑙�
-      path.conicTo(bodyRect.right,bodyRect.bottom
-          ,bodyRect.right -radius ,bodyRect.bottom,1.0);
-
-      path.lineTo(arrowRect.right, arrowRect.top); //绠ご
-      path.lineTo(arrowRect.left + arrowRect.width / 2, arrowRect.bottom);
-      path.lineTo(arrowRect.left,arrowRect.top);
+      path.lineTo(bodyRect.right, bodyRect.bottom - radius); //鍙充笅瑙�
+      path.conicTo(bodyRect.right, bodyRect.bottom, bodyRect.right - radius,
+          bodyRect.bottom, 1.0);
 
       path.lineTo(bodyRect.left + radius, bodyRect.bottom); //宸︿笅瑙�
-      path.conicTo(bodyRect.left,bodyRect.bottom
-          ,bodyRect.left ,bodyRect.bottom - radius,1.0);
+      path.conicTo(bodyRect.left, bodyRect.bottom, bodyRect.left,
+          bodyRect.bottom - radius, 1.0);
 
       path.lineTo(bodyRect.left, bodyRect.top + radius); //宸︿笂瑙�
-      path.conicTo(bodyRect.left,bodyRect.top
-          ,bodyRect.left + radius,bodyRect.top,1.0);
-
+      path.conicTo(bodyRect.left, bodyRect.top, bodyRect.left + radius,
+          bodyRect.top, 1.0);
     }
     path.close();
     return path;
   }
-
 }
 
-CupertinoPopoverDirection _calcDirection(Rect attachRect,Size size, CupertinoPopoverDirection direction) {
-  bool isArrowUp;
-  switch(direction){
+CupertinoPopoverDirection _calcDirection(
+    Rect attachRect, Size size, CupertinoPopoverDirection direction) {
+  switch (direction) {
     case CupertinoPopoverDirection.top:
-      isArrowUp = attachRect.top < size.height + CupertinoPopoverState._arrowHeight; // 鍒ゆ柇椤堕儴浣嶇疆澶熶笉澶�
-      break;
+      return (attachRect.top < size.height + CupertinoPopoverState._arrowHeight)
+          ? CupertinoPopoverDirection.bottom
+          : CupertinoPopoverDirection.top; // 鍒ゆ柇椤堕儴浣嶇疆澶熶笉澶�
     case CupertinoPopoverDirection.bottom:
-      isArrowUp = _ScreenUtil.getInstance().screenHeight > attachRect.bottom + size.height + CupertinoPopoverState._arrowHeight;
-      break;
-  } 
-  return isArrowUp ? CupertinoPopoverDirection.bottom : CupertinoPopoverDirection.top;
-}
\ No newline at end of file
+      return _ScreenUtil.getInstance().screenHeight >
+              attachRect.bottom +
+                  size.height +
+                  CupertinoPopoverState._arrowHeight
+          ? CupertinoPopoverDirection.bottom
+          : CupertinoPopoverDirection.top;
+    case CupertinoPopoverDirection.left:
+      return (attachRect.left < size.width + CupertinoPopoverState._arrowHeight)
+          ? CupertinoPopoverDirection.right
+          : CupertinoPopoverDirection.left; // 鍒ゆ柇椤堕儴浣嶇疆澶熶笉澶�
+    case CupertinoPopoverDirection.right:
+      return _ScreenUtil.getInstance().screenWidth >
+              attachRect.right +
+                  size.width +
+                  CupertinoPopoverState._arrowHeight
+          ? CupertinoPopoverDirection.right
+          : CupertinoPopoverDirection.left;
+  }
+}
diff --git a/lib/widgets/tables/table.dart b/lib/widgets/tables/table.dart
index bc1acad..c0bb5d4 100644
--- a/lib/widgets/tables/table.dart
+++ b/lib/widgets/tables/table.dart
@@ -1,26 +1,62 @@
-import 'package:flutter/material.dart';
+part of cool_ui;
 
 class CoolTable extends StatefulWidget{
   @override
   State<StatefulWidget> createState() {
     // TODO: implement createState
-    return null;
+    return CoolTableState();
   }
 }
 
 class CoolTableState extends State<CoolTable>{
+  ScrollController hTitle = ScrollController();
+  ScrollController hBody = ScrollController();
+
+  @override
+  void initState() {
+    // TODO: implement initState
+    super.initState();
+    connectScroll(hTitle, hBody);
+  }
+
   @override
   Widget build(BuildContext context) {
     // TODO: implement build
-    return null;
+    return Column(
+      mainAxisSize: MainAxisSize.min,
+      children: <Widget>[
+        SizedBox(
+          height: 50,
+          child: ListView(
+          scrollDirection: Axis.horizontal,
+          shrinkWrap: true,
+          physics: BouncingScrollPhysics(),
+          controller: hTitle,
+          children: <Widget>[
+            Text('1111111111111111111111111111111111111111111111111111111111111111111111111111')
+          ],
+        ),
+        width: 375,),
+        SizedBox(
+          height: 50,
+          child: ListView(
+          physics: BouncingScrollPhysics(),
+          scrollDirection: Axis.horizontal,
+          controller: hBody,
+          shrinkWrap: true,
+          children: <Widget>[
+            Text('1111111111111111111111111111111111111111111111111111111111111111111111111111')
+          ],
+        )),
+      ],
+    );
   }
 }
 
 class CoolColumnInfo{
   final double flex;
   final double width;
-  final double minWidth;
-  final double maxWidth;
+  final Widget title;
 
-  const CoolColumnInfo({this.flex, this.width, this.minWidth, this.maxWidth});
+  const CoolColumnInfo({this.flex, this.width, this.title});
 }
\ No newline at end of file
diff --git a/pubspec.yaml b/pubspec.yaml
index 085eccd..eac5ee4 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,6 +1,6 @@
 name: cool_ui
 description: Some practical Widget for flutter,Popover,Weui,Custom Keyboard
-version: 0.6.0
+version: 0.6.1
 author: Kevin <liangkaikevin@gmail.com>
 homepage: https://github.com/Im-Kevin/cool_ui
 
-- 
2.17.1