示例#1
0
        private void SnapToClosestBar(double position, GroupChartItem selectedItem)
        {
            var selectedValues = new SelectedChartValueItemArgs
            {
                ChartValueItems = new List <ChartValueItemParam>(),
                TouchedPoint    = TouchedPoint
            };

            foreach (var chartEntry in ChartEntries.Where(x => x.IsVisible))
            {
                var chartEntryItem = chartEntry.Items.FirstOrDefault(i => i.Tag.ToString() == selectedItem.Tag.ToString());

                if (chartEntryItem == null)
                {
                    continue;
                }

                selectedValues.ChartValueItems.Add(new ChartValueItemParam(chartEntryItem, null, chartEntry));
            }

            // Invoke command with selected items
            SelectedValuesCommand?.Execute(selectedValues);

            Device.BeginInvokeOnMainThread(async() =>
            {
                isSnapping = true;

                ScrollComponent.Scrolled -= ScrollComponent_Scrolled;

                SelectedLabel = selectedItem.Label;

                lastScrollPosition = position;

                await ScrollComponent.ScrollToAsync(lastScrollPosition, 0, false);

                ShowSwipeNotifications(lastScrollPosition);

                ScrollComponent.Scrolled += ScrollComponent_Scrolled;

                isSnapping = false;
            });
        }
示例#2
0
        private void DrawSlider(SKCanvas canvas, SKRect frame, SKRect chart)
        {
            if (!IsSliderVisible)
            {
                return;
            }

            if (!IsInitialized)
            {
                FindClosestItem(TouchedPoint.X);
            }

            float x = chart.GetInsideXValue(TouchedPoint.X);

            using (var paint = new SKPaint
            {
                Style = SKPaintStyle.Stroke,
                StrokeCap = UseItemWidthSlider ? SKStrokeCap.Butt : SKStrokeCap.Round,
                Color = this.SliderColor.ToSKColor().AsTransparency(),
                StrokeWidth = UseItemWidthSlider ? frame.GetItemWidth(MaxItems) : this.SliderWidth
            })
            {
                // Straight slider line
                canvas.DrawLine(x, chart.Top, x, DisplayHorizontalValuesBySlider && !UseItemWidthSlider ? frame.Bottom + HorizontalTextSize : chart.Bottom, paint);

                DrawSliderHint(canvas, x);
            }

            // Get items on x axis
            var valueItems = ChartEntries.GetChartValueItemFromX(x, frame, frame.GetItemWidth(MaxItems));

            // Send selected items with command
            SelectedValuesCommand?.Execute(new SelectedChartValueItemArgs
            {
                ChartValueItems = valueItems,
                TouchedPoint    = new SKPoint(x, TouchedPoint.Y)
            });
        }
示例#3
0
        private void LineChart_PaintSurface(object sender, SKPaintSurfaceEventArgs e)
        {
            if (ChartEntries?.Any() != true)
            {
                return;
            }

            var info   = e.Info;
            var canvas = e.Surface.Canvas;

            canvas.Clear();

            var frame = CreateFrame(info);
            var chart = CreateChart(frame);

            if (!IsInitialized)
            {
                // Makes slider first init in middle of frame
                TouchedPoint = new SKPoint(frame.MidX, 0);
            }

            DrawVerticalLabels(canvas, frame, chart);

            if (ChartEntries.Any(x => x.IsVisible))
            {
                CalculateChartValuesXPoints(chart);

                DrawBackground(canvas, frame);
                DrawInnerFrame(canvas, frame);

                if (!string.IsNullOrEmpty(SelectedTag) && !isTouching)
                {
                    var selectedTagPosition = ChartValueItemsXPoints.FirstOrDefault(x => x.Item1.ToString() == SelectedTag)?.Item2 ?? 0f;

                    TouchedPoint = new SKPoint(selectedTagPosition, 0f);
                }

                DrawSlider(canvas, frame, chart);

                foreach (var entry in ChartEntries.Where(x => x.IsVisible).OrderByDescending(x => x.Items.Count()))
                {
                    DrawLines(entry, canvas, CalculatePoints(entry.Items, frame, chart));
                }

                DrawHorizontalLabels(canvas, frame, chart);

                // Get items on x axis
                var valueItems = ChartEntries.GetChartValueItemFromX(chart.GetInsideXValue(TouchedPoint.X), frame, frame.GetItemWidth(MaxItems));

                // Send selected items with command
                SelectedValuesCommand?.Execute(new SelectedChartValueItemArgs
                {
                    ChartValueItems = valueItems,
                    TouchedPoint    = new SKPoint(chart.GetInsideXValue(TouchedPoint.X), TouchedPoint.Y)
                });

                DrawHorizontalLabel(valueItems?.FirstOrDefault()?.ChartValueItem, canvas, frame, chart);

                DrawFrame(canvas, frame);

                DrawSliderPoints(valueItems, canvas, chart);
            }
            else
            {
                DrawInnerFrame(canvas, frame);
                DrawFrame(canvas, frame);
            }

            IsInitialized = true;
        }
示例#4
0
        private void DrawBars(SKCanvas canvas, SKRect frame, SKRect chart)
        {
            // Selected bar width
            var selectedValueItems = ChartEntries.GetChartValueItemFromX(chart.GetInsideXValue(TouchedPoint.X), chart, chart.GetItemWidth(MaxItems));
            var selectedTags       = selectedValueItems?.Select(x => x.ChartValueItem.Tag);

            // Invoke command with selected items
            SelectedValuesCommand?.Execute(new SelectedChartValueItemArgs
            {
                ChartValueItems = selectedValueItems,
                TouchedPoint    = new SKPoint(chart.GetInsideXValue(TouchedPoint.X), TouchedPoint.Y)
            });

            using (var paint = new SKPaint
            {
                IsAntialias = true,
                Style = SKPaintStyle.StrokeAndFill,
                StrokeCap = SKStrokeCap.Butt,
            })
            {
                var groupedItems = ChartEntries.Where(x => x.IsVisible).SelectMany(x => x.Items).GroupBy(x => x.Tag.ToString()).OrderBy(x => x.Key);

                // Calc max items in one group
                var maxItemsInGroups = groupedItems.Max(x => x.Count());

                // Calc how many groups there is
                var groupCount = groupedItems.Count();

                // Calc how many bars there will be
                var totalBars = groupCount * maxItemsInGroups;

                var internalGroupMargin = maxItemsInGroups == 1 ? BarMargin : GroupMargin;
                var internalBarMargin   = maxItemsInGroups == 1 ? 0 : BarMargin;
                var internalBarWidth    = MinimumBarWidth;

                float itemWidth;

                if (AllowScroll)
                {
                    // Calc total item width
                    itemWidth = internalBarWidth * maxItemsInGroups + ((maxItemsInGroups - 1) * barMargin);
                }
                else
                {
                    itemWidth = chart.Width / groupCount;

                    itemWidth -= internalGroupMargin;

                    internalBarWidth = (itemWidth / maxItemsInGroups) - ((maxItemsInGroups - 1) * barMargin);
                }

                int groupIndex = 0;

                float scrollLeftPadding = 0;
                float left      = 0;
                float groupLeft = 0;
                float right     = 0;

                groupCenters = new List <GroupChartItem>();

                foreach (var groupedItem in groupedItems)
                {
                    int itemIndex = 0;

                    groupLeft = left;

                    if (!AllowScroll && IsSliderVisible && selectedTags?.Contains(groupedItem.Key) == true)
                    {
                        var item = groupedItem.OrderByDescending(x => x.Value).First();

                        paint.Color      = SliderColor.ToSKColor();
                        paint.PathEffect = SKPathEffect.CreateCorner(SliderCornerRadius);

                        var bounds = new SKRect(
                            item.Point.X - (itemWidth * .5f) - (groupMargin * .5f),
                            item.Point.Y - (itemWidth * .5f),
                            item.Point.X + (itemWidth * .5f) + (groupMargin * .5f),
                            chart.Bottom + HorizontalTextSize);

                        paint.StrokeWidth = 0;

                        canvas.DrawRect(bounds, paint);
                    }

                    foreach (var item in groupedItem)
                    {
                        var parent = ChartEntries.FirstOrDefault(x => x.Items.Contains(item));

                        SKRect bounds = new SKRect();

                        if (AllowScroll)
                        {
                            if (left == 0)
                            {
                                left = itemWidth.FromDpiAdjusted();

                                groupLeft = left;

                                scrollLeftPadding = left;
                            }
                            else if (itemIndex != 0)
                            {
                                left += internalBarMargin;
                            }

                            right = left + internalBarWidth;

                            bounds = new SKRect(
                                left,
                                item.Point.Y,
                                right,
                                chart.Bottom);

                            left = right;
                        }
                        else
                        {
                            left  = (item.Point.X - (itemWidth * .5f)) + (internalBarWidth * itemIndex) + (internalBarMargin * itemIndex);
                            right = left + internalBarWidth;

                            bounds = new SKRect(
                                left,
                                item.Point.Y,
                                right,
                                chart.Bottom);
                        }

                        paint.StrokeWidth = 0;

                        if (parent.UseDashedEffect)
                        {
                            paint.Color      = parent.Color.ToSKColor().AsTransparency();
                            paint.PathEffect = SKPathEffect.CreateCorner(BarCornerRadius);

                            canvas.DrawRect(bounds, paint);

                            paint.Color      = parent.Color.ToSKColor();
                            paint.PathEffect = SKPathEffect.CreateDash(new float[] { StrokeDashFirst, StrokeDashSecond }, StrokeDashPhase);

                            paint.StrokeWidth = bounds.Width;

                            canvas.DrawLine(bounds.MidX, bounds.Bottom, bounds.MidX, bounds.Top, paint);
                        }
                        else
                        {
                            paint.Color      = parent.Color.ToSKColor();
                            paint.PathEffect = SKPathEffect.CreateCorner(BarCornerRadius);
                            canvas.DrawRect(bounds, paint);
                        }

                        itemIndex++;
                    }

                    left += internalGroupMargin;

                    groupIndex++;

                    var groupCenterPosition = groupLeft + (itemWidth / 2);

                    groupCenters.Add(new GroupChartItem
                    {
                        Label    = groupedItem.FirstOrDefault().Label,
                        Position = groupCenterPosition.FromDpiAdjusted(),
                        Tag      = groupedItem.Key
                    });
                }

                if (AllowScroll)
                {
                    var requestedWidth = right.FromDpiAdjusted() + frame.Left.FromDpiAdjusted();

                    if (requestedWidth != this.WidthRequest)
                    {
                        this.WidthRequest = requestedWidth;
                    }
                    else
                    {
                        SetStartPosition(groupCenters);
                        IsInitialized = true;
                    }

                    if (ScrollComponent != null)
                    {
                        var deviceWidth = Xamarin.Essentials.DeviceDisplay.MainDisplayInfo.Width;

                        var halfDeviceWidth = ((float)(deviceWidth / 2)).FromDpiAdjusted();

                        var frameLeftVal       = frame.Left.FromDpiAdjusted();
                        var rectRightMarginVal = ChartRectMargin.Right.FromDpiAdjusted();

                        var leftPadding = halfDeviceWidth - frameLeftVal - scrollLeftPadding.FromDpiAdjusted();

                        var rightPadding = halfDeviceWidth - frameLeftVal - rectRightMarginVal - itemWidth.FromDpiAdjusted();

                        ScrollComponent.Padding = new Thickness(leftPadding, 0, rightPadding, 0);
                        ScrollComponent.Margin  = new Thickness(frame.Left.FromDpiAdjusted(), 0, ChartRectMargin.Right.FromDpiAdjusted(), 0);

                        if (Selector != null)
                        {
                            Selector.WidthRequest = itemWidth.FromDpiAdjusted();
                            Selector.Margin       = new Thickness(halfDeviceWidth, 0, 0, this.Height - frame.Bottom.FromDpiAdjusted());
                        }

                        if (!isScrollEventActive)
                        {
                            ScrollComponent.Scrolled += ScrollComponent_Scrolled;
                            isScrollEventActive       = true;
                        }
                    }

                    if (SwipeNotificationLeft != null)
                    {
                        SwipeNotificationLeft.Margin       = new Thickness(frame.Left.FromDpiAdjusted(), 0, 0, this.Height - frame.Bottom.FromDpiAdjusted());
                        SwipeNotificationLeft.WidthRequest = ScrollComponent.Padding.Left;
                    }

                    if (SwipeNotificationRight != null)
                    {
                        SwipeNotificationRight.Margin       = new Thickness(0, 0, ChartRectMargin.Right.FromDpiAdjusted(), this.Height - frame.Bottom.FromDpiAdjusted());
                        SwipeNotificationRight.WidthRequest = ScrollComponent.Padding.Left;
                    }
                }
            }

            DrawHorizontalLabel(selectedValueItems?.FirstOrDefault()?.ChartValueItem, canvas, frame, chart);
        }