private void DrawLegends(SKCanvas canvas) { int x = _chartData.Padding.Left; float legendsTop = _chartData.Height * 0.8f; var height = _chartData.Height - legendsTop - _chartData.Padding.Bottom; var y = legendsTop + (height + _chartData.TextFont.TextSize) / 2; int index = 0; var legendRect = new SKRect(0, 0, _chartData.TextFont.TextSize, _chartData.TextFont.TextSize); var textLocation = new SKPoint(x + _chartData.TextFont.TextSize * 2, y + _chartData.TextFont.TextSize); foreach (var item in _chartData.SeriesCollection) { LegendBoxPaint.Color = _chartData.Colors[index++].ToSKColor(); legendRect = new SKRect(x, textLocation.Y - _chartData.TextFont.TextSize, x + _chartData.TextFont.TextSize, textLocation.Y); canvas.DrawRect(legendRect, LegendBoxPaint); canvas.DrawRect(legendRect, LegendBoxBorderPaint); canvas.DrawText(item.Title, textLocation.X, textLocation.Y, TextPaint); var offset = TextPaint.MeasureText(item.Title) + 3 * _chartData.TextFont.TextSize; x += (int)offset; textLocation.X += offset; } }
private void DrawColumns(SKCanvas canvas, SKRect chartRect, float unitHeight) { float chartAreaLeft = chartRect.Left + _chartData.TextFont.TextSize * 4; float chartAreaRight = chartRect.Right - _chartData.TextFont.TextSize; float availableWidth = chartAreaRight - chartAreaLeft; int numberOfSeries = _chartData.SeriesCollection.Count(); int numberOfItems = _chartData.SeriesCollection[0].DataPoints.Count(); int totalWidthOfBars = numberOfSeries * numberOfItems * _chartData.ColumnWidth + (numberOfItems - 1) * _chartData.ColumnSpacing; float left = chartAreaLeft + ((chartAreaRight - chartAreaLeft) - totalWidthOfBars) / 2; var index = 0; foreach (var series in _chartData.SeriesCollection) { ChartItemFillPaint.Color = _chartData.Colors[index].ToSKColor(); var item = 0; var barLeft = left + index * _chartData.ColumnWidth; TextPaint.TextAlign = SKTextAlign.Center; foreach (var dataPoint in series.DataPoints) { float height = dataPoint.Value * unitHeight; var bottom = chartRect.Bottom; var top = bottom - height; var r = barLeft + _chartData.ColumnWidth; var rect = new SKRect(barLeft, top, r, bottom); canvas.DrawRect(rect, ChartItemFillPaint); canvas.DrawRect(rect, ChartItemOutlinePaint); if (index == 0) { float textWidth = TextPaint.MeasureText(dataPoint.Title); var textLeft = barLeft + (_chartData.ColumnWidth * numberOfSeries) / 2; var textBottom = bottom + TextPaint.TextSize * 2; canvas.DrawText(dataPoint.Title, textLeft, textBottom, TextPaint); } barLeft += _chartData.ColumnWidth * numberOfSeries + _chartData.ColumnSpacing; item++; } index++; } }
private float BuildAxesLabels(int highest, int markerValue, List <string> texts) { float maxWidth = 0; for (int i = 0; i < 5; i++) { string text = string.Format(_chartData.SeriesCollection[0].ValueDisplayFormat, highest); maxWidth = Math.Max(TextPaint.MeasureText(text), maxWidth); highest = highest - markerValue; texts.Add(text); } return(maxWidth); }
public MainRecyclerViewTouchCallback(Context context, MainRecyclerView recyclerView) : base(0, ItemTouchHelper.Left | ItemTouchHelper.Right) { this.recyclerView = recyclerView; backgrounds = new[] { Resource.Color.playButtonRed, Resource.Color.playButtonGreen } .Select(res => new Color(ContextCompat.GetColor(context, res))) .Select(color => new ColorDrawable(color)) .ToArray(); textMargin = 16.DpToPixels(context); textPaint.Color = Color.White; textPaint.TextAlign = Paint.Align.Left; textPaint.TextSize = 15.SpToPixels(context); textPaint.SetTypeface(Typeface.Create("sans-serif-medium", TypefaceStyle.Normal)); deleteTextWidth = (int)textPaint.MeasureText(Delete); }
private int MeasureWidth(int measureSpec) { int result; int specMode = Convert.ToInt32(MeasureSpec.GetMode(measureSpec)); int specSize = MeasureSpec.GetSize(measureSpec); if (specMode == (int)MeasureSpecMode.Exactly) { result = specSize; } else { result = (int)mTextPaintOutline.MeasureText(mText) + PaddingLeft + PaddingRight; if (specMode == (int)MeasureSpecMode.AtMost) { result = Math.Min(result, specSize); } } return(result); }
public override void Draw(Canvas canvas) { // Grab canvas dimensions. int canvasWidth = canvas.Width; int canvasHeight = canvas.Height; // Calculate horizontal center. float centerX = canvasWidth * 0.5f; // Draw the background. float centerY = (float)Math.Round(canvasHeight * 0.5f); Paint circlePaint = new Paint(); circlePaint.Flags = PaintFlags.AntiAlias; circlePaint.Color = Color.LightSkyBlue; int h = this.MeasuredHeight; int w = this.MeasuredWidth; int r = Math.Max(w, h); canvas.DrawCircle(centerX, centerY, r / 2, circlePaint); // Draw text. TextPaint textPaint = new TextPaint(); textPaint.Flags = PaintFlags.AntiAlias; textPaint.Color = Color.Black; textPaint.TextSize = this.TextSize; float baselineY = (float)Math.Round(canvasHeight * 0.5f + this.TextSize / 3); // Measure the width of text to display. float textWidth = textPaint.MeasureText(this.Text); // Figure out an x-coordinate that will center the text in the canvas. float textX = (float)Math.Round(centerX - textWidth * 0.5f); // Draw. canvas.DrawText(this.Text, textX, baselineY, textPaint); }
public override Carto.Graphics.Bitmap OnDrawPopup(PopupDrawInfo popupDrawInfo) { PopupStyle style = popupDrawInfo.Popup.Style; // Calculate scaled dimensions float DPToPX = popupDrawInfo.DPToPX; float PXTODP = 1 / DPToPX; if (style.ScaleWithDPI) { DPToPX = 1; } else { PXTODP = 1; } float screenWidth = popupDrawInfo.ScreenBounds.GetWidth() * PXTODP; float screenHeight = popupDrawInfo.ScreenBounds.GetHeight() * PXTODP; // Update sizes based on scale (uses extension method, cf. Shared/Extensions int fontSize = FontSize.Update(DPToPX); int triangleWidth = TriangleSize.Update(DPToPX); int triangleHeight = TriangleSize.Update(DPToPX); int strokeWidth = StrokeWidth.Update(DPToPX); int screenPadding = ScreenPadding.Update(DPToPX); // Set font var font = Android.Graphics.Typeface.Create("HelveticaNeue-Light", Android.Graphics.TypefaceStyle.Normal); // Calculate the maximum popup size, adjust with dpi int maxPopupWidth = (int)(Math.Min(screenWidth, screenHeight)); float halfStrokeWidth = strokeWidth * 0.5f; int maxTextWidth = maxPopupWidth - (2 * screenPadding + strokeWidth); // Measure text TextPaint textPaint = new TextPaint { Color = TextColor, TextSize = fontSize }; textPaint.SetTypeface(font); var textLayout = new StaticLayout(text, textPaint, maxTextWidth, Layout.Alignment.AlignNormal, 1, 0, false); int textX = (int)Math.Min(textPaint.MeasureText(text), textLayout.Width); int textY = textLayout.Height; int popupWidth = textX + (2 * PopupPadding + strokeWidth + triangleWidth); int popupHeight = textY + (2 * PopupPadding + strokeWidth); var bitmap = Android.Graphics.Bitmap.CreateBitmap(popupWidth, popupHeight, Android.Graphics.Bitmap.Config.Argb8888); var canvas = new Android.Graphics.Canvas(bitmap); var trianglePath = new Android.Graphics.Path(); trianglePath.MoveTo(triangleWidth, 0); trianglePath.LineTo(halfStrokeWidth, triangleHeight * 0.5f); trianglePath.LineTo(triangleWidth, triangleHeight); trianglePath.Close(); int triangleOffsetX = 0; int triangleOffsetY = (popupHeight - triangleHeight) / 2; // Create paint object var paint = new Android.Graphics.Paint(); paint.AntiAlias = true; paint.SetStyle(Android.Graphics.Paint.Style.Stroke); paint.StrokeWidth = strokeWidth; paint.Color = StrokeColor; // Stroke background var background = new Android.Graphics.RectF(); background.Left = triangleWidth; background.Top = halfStrokeWidth; background.Right = popupWidth - strokeWidth; background.Bottom = popupHeight - strokeWidth; canvas.DrawRect(background, paint); // Stroke triangle canvas.Save(); canvas.Translate(triangleOffsetX, triangleOffsetY); canvas.DrawPath(trianglePath, paint); canvas.Restore(); // Fill background paint.SetStyle(Android.Graphics.Paint.Style.Fill); paint.Color = BackgroundColor; canvas.DrawRect(background, paint); // Fill triangle canvas.Save(); canvas.Translate(triangleOffsetX, triangleOffsetY); canvas.DrawPath(trianglePath, paint); canvas.Restore(); if (textLayout != null) { // Draw text canvas.Save(); canvas.Translate(halfStrokeWidth + triangleWidth + PopupPadding, halfStrokeWidth + PopupPadding); textLayout.Draw(canvas); canvas.Restore(); } return BitmapUtils.CreateBitmapFromAndroidBitmap(bitmap); }
/** * Decorate the RecyclerView item with the chosen backgrounds and icons */ public void Decorate() { try { if (_actionState != ItemTouchHelper.ActionStateSwipe) { return; } if (_dX > 0) { // Swiping Right if (_swipeRightBackgroundColor != null) { var background = new ColorDrawable(_swipeRightBackgroundColor.Value); background.SetBounds(_viewHolder.ItemView.Left, _viewHolder.ItemView.Top, _viewHolder.ItemView.Left + (int)_dX, _viewHolder.ItemView.Bottom); background.Draw(_canvas); } var iconSize = 0; if (_swipeRightActionIconId != 0 && _dX > _iconHorizontalMargin) { var icon = ContextCompat.GetDrawable(_recyclerView.Context, _swipeRightActionIconId); if (icon != null) { iconSize = icon.IntrinsicHeight; var halfIcon = iconSize / 2; var top = _viewHolder.ItemView.Top + ((_viewHolder.ItemView.Bottom - _viewHolder.ItemView.Top) / 2 - halfIcon); icon.SetBounds(_viewHolder.ItemView.Left + _iconHorizontalMargin, top, _viewHolder.ItemView.Left + _iconHorizontalMargin + icon.IntrinsicWidth, top + icon.IntrinsicHeight); if (_swipeRightActionIconTint != null) { icon.SetColorFilter(_swipeRightActionIconTint.Value, PorterDuff.Mode.SrcIn); } icon.Draw(_canvas); } } if (!string.IsNullOrEmpty(_mSwipeRightText) && _dX > _iconHorizontalMargin + iconSize) { var textPaint = new TextPaint { AntiAlias = true, TextSize = TypedValue.ApplyDimension(_mSwipeRightTextUnit, _mSwipeRightTextSize, _recyclerView.Context.Resources.DisplayMetrics), Color = _mSwipeRightTextColor }; textPaint.SetTypeface(_mSwipeRightTypeface); var textTop = (int)(_viewHolder.ItemView.Top + (_viewHolder.ItemView.Bottom - _viewHolder.ItemView.Top) / 2.0 + textPaint.TextSize / 2); _canvas.DrawText(_mSwipeRightText, _viewHolder.ItemView.Left + _iconHorizontalMargin + iconSize + (iconSize > 0 ? _iconHorizontalMargin / 2 : 0), textTop, textPaint); } } else if (_dX < 0) { // Swiping Left if (_swipeLeftBackgroundColor != null) { var background = new ColorDrawable(_swipeLeftBackgroundColor.Value); background.SetBounds(_viewHolder.ItemView.Right + (int)_dX, _viewHolder.ItemView.Top, _viewHolder.ItemView.Right, _viewHolder.ItemView.Bottom); background.Draw(_canvas); } var iconSize = 0; var imgLeft = _viewHolder.ItemView.Right; if (_swipeLeftActionIconId != 0 && _dX < -_iconHorizontalMargin) { var icon = ContextCompat.GetDrawable(_recyclerView.Context, _swipeLeftActionIconId); if (icon != null) { iconSize = icon.IntrinsicHeight; var halfIcon = iconSize / 2; var top = _viewHolder.ItemView.Top + ((_viewHolder.ItemView.Bottom - _viewHolder.ItemView.Top) / 2 - halfIcon); imgLeft = _viewHolder.ItemView.Right - _iconHorizontalMargin - halfIcon * 2; icon.SetBounds(imgLeft, top, _viewHolder.ItemView.Right - _iconHorizontalMargin, top + icon.IntrinsicHeight); if (_swipeLeftActionIconTint != null) { icon.SetColorFilter(_swipeLeftActionIconTint.Value, PorterDuff.Mode.SrcIn); } icon.Draw(_canvas); } } if (!string.IsNullOrEmpty(_mSwipeLeftText) && _dX < -_iconHorizontalMargin - iconSize) { var textPaint = new TextPaint { AntiAlias = true, TextSize = TypedValue.ApplyDimension(_mSwipeLeftTextUnit, _mSwipeLeftTextSize, _recyclerView.Context.Resources.DisplayMetrics), Color = _mSwipeLeftTextColor }; textPaint.SetTypeface(_mSwipeLeftTypeface); var width = textPaint.MeasureText(_mSwipeLeftText); var textTop = (int)(_viewHolder.ItemView.Top + (_viewHolder.ItemView.Bottom - _viewHolder.ItemView.Top) / 2.0 + textPaint.TextSize / 2); _canvas.DrawText(_mSwipeLeftText, imgLeft - width - (imgLeft == _viewHolder.ItemView.Right ? _iconHorizontalMargin : _iconHorizontalMargin / 2), textTop, textPaint); } } } catch (Exception e) { } }
protected override void OnPaintSurface(SKPaintSurfaceEventArgs args) { base.OnPaintSurface(args); var info = args.Info; var canvas = args.Surface.Canvas; canvas.Clear(); var lineSize = info.Height * 0.12f; //25% var segmentCircleSize = lineSize * 4; BackgroundPaint.StrokeWidth = lineSize; ForegroundPaint.StrokeWidth = lineSize; ProgressCirclePaint.StrokeWidth = lineSize; var rect = new SKRect(segmentCircleSize / 2, 0, info.Width - segmentCircleSize / 2, info.Height); var progress = Math.Min(Math.Max(0, Progress - 1), (TotalProgress - 1)) / (TotalProgress - 1); var progressWidth = rect.Left + (rect.Width * progress); // Draw Background canvas.DrawLine(rect.Left, rect.MidY, rect.Right, rect.MidY, BackgroundPaint); // Draw Foreground ForegroundPaint.StrokeWidth = lineSize; canvas.DrawLine(rect.Left, rect.MidY, progressWidth, rect.MidY, ForegroundPaint); // Draw end and start circle if (progress > 0) { canvas.DrawLine(rect.Left, rect.MidY, rect.Left, rect.MidY, ProgressCirclePaint); } if (progress >= 1) { canvas.DrawLine(rect.Right, rect.MidY, rect.Right, rect.MidY, ProgressCirclePaint); } var width = rect.Width; var interval = width / (TotalProgress - 1); for (var i = 0; i < TotalProgress; i++) { var xPos = rect.Left + interval * i; // Draw Circles ProgressCirclePaint.StrokeWidth = segmentCircleSize; BackgroundPaint.StrokeWidth = segmentCircleSize * 0.9f; canvas.DrawLine(xPos, rect.MidY, xPos, rect.MidY, Progress > i ? ProgressCirclePaint : BackgroundPaint); // Draw Checkmark if (Progress > i) { canvas.Save(); CHECKMARK_PATH.GetTightBounds(out var bounds); canvas.Translate(xPos, rect.MidY); var size = lineSize * 1.5f; var scale = new SKPoint(size / (bounds.Width + CheckmarkPaint.StrokeWidth), size / (bounds.Height + CheckmarkPaint.StrokeWidth)); canvas.Scale(scale); canvas.Translate(-bounds.MidX, -bounds.MidY); canvas.DrawPath(CHECKMARK_PATH, CheckmarkPaint); canvas.Restore(); } // Draw Labels var text = (i + 1).ToString(CultureInfo.InvariantCulture); var textRect = new SKRect(); TextPaint.MeasureText(text, ref textRect); canvas.DrawText(text, XPosInsideBounds(xPos, textRect, info), rect.Bottom - 2, TextPaint); } }
// Test if the suggested size fits the control boundaries public int OnTestSize(int suggestedSize, RectF availableSpace) { RectF textRect = new RectF(); paint.TextSize = suggestedSize; ITransformationMethod transformationMethod = targetControl.TransformationMethod; string text = null; if (transformationMethod != null) { text = transformationMethod.GetTransformation(targetControl.Text, targetControl); } // If text is null, use the value from Text object if (text == null) { text = targetControl.Text; } bool singleLine = targetControl.MaxLines == 1; if (singleLine) { textRect.Bottom = paint.FontSpacing; textRect.Right = paint.MeasureText(text); } else { StaticLayout layout = new StaticLayout(text, paint, widthLimit, Alignment.AlignNormal, spacingMult, spacingAdd, true); if (targetControl.MaxLines != NO_LINE_LIMIT && layout.LineCount > targetControl.MaxLines) { return(1); } textRect.Bottom = layout.Height; int maxWidth = -1; int lineCount = layout.LineCount; for (int i = 0; i < lineCount; i++) { int end = layout.GetLineEnd(i); if (i < lineCount - 1 && end > 0 && !IsValidWordWrap(text[end - 1], text[end])) { return(1); } if (maxWidth < layout.GetLineRight(i) - layout.GetLineLeft(i)) { maxWidth = (int)layout.GetLineRight(i) - (int)layout.GetLineLeft(i); } } textRect.Right = maxWidth; } textRect.OffsetTo(0, 0); if (availableSpace.Contains(textRect)) { return(-1); } return(1); }
protected override void OnPaintSurface(SKPaintSurfaceEventArgs args) { var info = args.Info; var canvas = args.Surface.Canvas; canvas.Clear(); var lineSize = (info.Width / TotalProgress) * 0.75f; var lineSizeHalf = lineSize * 0.5f; BackgroundPaint.StrokeWidth = lineSize; ForegroundPaint.StrokeWidth = lineSize; ForegroundPaint.StrokeCap = SKStrokeCap.Round; var rect = new SKRect(lineSize, 0, info.Width - lineSize, info.Height); var textRect = new SKRect(); TextPaint.MeasureText("0", ref textRect); var verticalSpace = rect.Height * 0.1f; var bottom = rect.Bottom - lineSizeHalf - (textRect.Height + verticalSpace); var top = rect.Top + lineSizeHalf + (textRect.Height + verticalSpace); var regularHeight = (bottom - top) * 0.65f; var xPosInterval = rect.Width / (TotalProgress - 1); for (var i = 0; i < TotalProgress; i++) { var xPos = rect.Left + xPosInterval * i; // Draw Labels if (i == 0) { // Start Label const string progressText = "0"; canvas.DrawText(progressText, XPosInsideBounds(xPos, textRect, info), rect.Bottom - 2, TextPaint); } else if (i == TotalProgress - 1) { // End Label var progressText = TotalProgress.ToString(); TextPaint.MeasureText(progressText, ref textRect); canvas.DrawText(progressText, XPosInsideBounds(xPos, textRect, info), rect.Bottom - 2, TextPaint); } if (i + 1 < Progress) { // Draw Foreground canvas.DrawLine(xPos, bottom - regularHeight, xPos, bottom, ForegroundPaint); } else if (i + 1 == Progress) { // Draw Current Progress canvas.DrawLine(xPos, top, xPos, bottom, ForegroundPaint); TextPaint.Color = TextPaint.Color.WithAlpha(255); var progressText = Progress.ToString(); TextPaint.MeasureText(progressText, ref textRect); canvas.DrawText(progressText, XPosInsideBounds(xPos, textRect, info), rect.Top + textRect.Height, ActiveTextPaint); } else { // Draw Background canvas.DrawLine(xPos, bottom - regularHeight, xPos, bottom, BackgroundPaint); } } }
protected override void OnDraw(Canvas canvas) { base.OnDraw(canvas); var left = _strokeWidth * 0.5f; var top = _strokeWidth * 0.5f; var right = _width - _strokeWidth * 0.5f; var bottom = _height - _strokeWidth * 0.5f; // Draw rounded rectangle canvas.DrawRoundRect( new RectF(left, top, right, bottom), _strokeRadius, _strokeRadius, _strokePaint ); // Draw line for (var i = 0; i < (_tabNum - 1); i++) { canvas.DrawLine( _perWidth * (i + 1), top, _perWidth * (i + 1), bottom, _strokePaint ); } // Draw tab and line for (var i = 0; i < _tabNum; i++) { var tabText = _tabTexts[i]; var tabTextWidth = _selectedTextPaint.MeasureText(tabText); if (i == _selectedTab) { // Draw selected tab if (i == 0) { DrawLeftPath(canvas, left, top, bottom); } else if (i == (_tabNum - 1)) { DrawRightPath(canvas, top, right, bottom); } else { canvas.DrawRect(new RectF(_perWidth * i, top, _perWidth * (i + 1), bottom), _fillPaint); } // Draw selected text canvas.DrawText( tabText, 0.5f * _perWidth * (2 * i + 1) - 0.5f * tabTextWidth, _height * 0.5f + _textHeightOffset, _selectedTextPaint ); } else { // Draw unselected text canvas.DrawText( tabText, 0.5f * _perWidth * (2 * i + 1) - 0.5f * tabTextWidth, _height * 0.5f + _textHeightOffset, _unselectedTextPaint ); } } }
protected int MeasureTextWidth(TextPaint textPaint, string line) { return Java.Lang.Math.Round (textPaint.MeasureText (line)); }
protected override void OnPaintSurface(SKPaintSurfaceEventArgs args) { base.OnPaintSurface(args); var info = args.Info; var canvas = args.Surface.Canvas; canvas.Clear(); var lineSize = info.Height * 0.25f; //25% var lineSizeHalf = lineSize * 0.5f; BackgroundPaint.StrokeWidth = lineSize; ForegroundPaint.StrokeWidth = lineSize; ProgressCirclePaint.StrokeWidth = lineSize; FinishCirclePaint.StrokeWidth = lineSize * 2; var rect = new SKRect(lineSizeHalf, 0, info.Width - lineSize, info.Height); var progress = Math.Min(Math.Max(0, Progress), TotalProgress) / TotalProgress; var progressWidth = rect.Left + (rect.Width * progress); // Draw Background canvas.DrawLine(rect.Left, rect.MidY, rect.Right, rect.MidY, BackgroundPaint); // Draw Foreground ForegroundPaint.StrokeWidth = lineSize; canvas.DrawLine(rect.Left, rect.MidY, progressWidth, rect.MidY, ForegroundPaint); // Draw current progress line if (progress > 0 && progress < 1) { // Draw Top Progress Text var progressText = Progress.ToString(CultureInfo.InvariantCulture); var textRect = new SKRect(); TextPaint.MeasureText(progressText, ref textRect); canvas.DrawText(progressText, progressWidth - 1 - textRect.MidX, rect.Top + textRect.Height, ActiveTextPaint); // Draw Progress Line ForegroundPaint.StrokeWidth = 1; canvas.DrawLine(progressWidth - 1, rect.Top + textRect.Height + lineSize * 0.3f, progressWidth - 1, rect.MidY + lineSizeHalf, ForegroundPaint); } // Draw end and start circle if (progress > 0) { canvas.DrawLine(rect.Left, rect.MidY, rect.Left, rect.MidY, ProgressCirclePaint); } if (progress >= 1) { canvas.DrawLine(rect.Right, rect.MidY, rect.Right, rect.MidY, ProgressCirclePaint); } // Draw Finish Circle FinishCirclePaint.Color = progress >= 1 ? ProgressColor.ToSKColor() : ProgressBackgroundColor.ToSKColor(); var end = rect.Right; canvas.DrawLine(end, rect.MidY, end, rect.MidY, FinishCirclePaint); // Draw Labels if (LabelCount > 1) { var width = rect.Width; var interval = width / (LabelCount - 1); for (var i = 0; i < LabelCount; i++) { var xPos = rect.Left + interval * i; var text = (i * (TotalProgress / (LabelCount - 1))).ToString(CultureInfo.InvariantCulture); var textRect = new SKRect(); TextPaint.MeasureText(text, ref textRect); canvas.DrawText(text, XPosInsideBounds(xPos, textRect, info), rect.Bottom - 2, TextPaint); } } // Draw Finish Flag canvas.Save(); FlagPaint.Color = TextPaint.Color.WithAlpha(150); FLAG_PATH.GetTightBounds(out var bounds); canvas.Translate(end, rect.MidY); var size = lineSize * 0.75f; var scale = new SKPoint(size / (bounds.Width + FlagPaint.StrokeWidth), size / (bounds.Height + FlagPaint.StrokeWidth)); canvas.Scale(scale); canvas.Translate(-bounds.MidX, -bounds.MidY); canvas.DrawPath(FLAG_PATH, FlagPaint); canvas.Restore(); }
public override Carto.Graphics.Bitmap OnDrawPopup(PopupDrawInfo popupDrawInfo) { PopupStyle style = popupDrawInfo.Popup.Style; // Calculate scaled dimensions float DPToPX = popupDrawInfo.DPToPX; float PXTODP = 1 / DPToPX; if (style.ScaleWithDPI) { DPToPX = 1; } else { PXTODP = 1; } float screenWidth = popupDrawInfo.ScreenBounds.GetWidth() * PXTODP; float screenHeight = popupDrawInfo.ScreenBounds.GetHeight() * PXTODP; // Update sizes based on scale (uses extension method, cf. Shared/Extensions int fontSize = FontSize.Update(DPToPX); int triangleWidth = TriangleSize.Update(DPToPX); int triangleHeight = TriangleSize.Update(DPToPX); int strokeWidth = StrokeWidth.Update(DPToPX); int screenPadding = ScreenPadding.Update(DPToPX); // Set font var font = Android.Graphics.Typeface.Create("HelveticaNeue-Light", Android.Graphics.TypefaceStyle.Normal); // Calculate the maximum popup size, adjust with dpi int maxPopupWidth = (int)(Math.Min(screenWidth, screenHeight)); float halfStrokeWidth = strokeWidth * 0.5f; int maxTextWidth = maxPopupWidth - (2 * screenPadding + strokeWidth); // Measure text TextPaint textPaint = new TextPaint { Color = TextColor, TextSize = fontSize }; textPaint.SetTypeface(font); var textLayout = new StaticLayout(text, textPaint, maxTextWidth, Layout.Alignment.AlignNormal, 1, 0, false); int textX = (int)Math.Min(textPaint.MeasureText(text), textLayout.Width); int textY = textLayout.Height; int popupWidth = textX + (2 * PopupPadding + strokeWidth + triangleWidth); int popupHeight = textY + (2 * PopupPadding + strokeWidth); var bitmap = Android.Graphics.Bitmap.CreateBitmap(popupWidth, popupHeight, Android.Graphics.Bitmap.Config.Argb8888); var canvas = new Android.Graphics.Canvas(bitmap); var trianglePath = new Android.Graphics.Path(); trianglePath.MoveTo(triangleWidth, 0); trianglePath.LineTo(halfStrokeWidth, triangleHeight * 0.5f); trianglePath.LineTo(triangleWidth, triangleHeight); trianglePath.Close(); int triangleOffsetX = 0; int triangleOffsetY = (popupHeight - triangleHeight) / 2; // Create paint object var paint = new Android.Graphics.Paint(); paint.AntiAlias = true; paint.SetStyle(Android.Graphics.Paint.Style.Stroke); paint.StrokeWidth = strokeWidth; paint.Color = StrokeColor; // Stroke background var background = new Android.Graphics.RectF(); background.Left = triangleWidth; background.Top = halfStrokeWidth; background.Right = popupWidth - strokeWidth; background.Bottom = popupHeight - strokeWidth; canvas.DrawRect(background, paint); // Stroke triangle canvas.Save(); canvas.Translate(triangleOffsetX, triangleOffsetY); canvas.DrawPath(trianglePath, paint); canvas.Restore(); // Fill background paint.SetStyle(Android.Graphics.Paint.Style.Fill); paint.Color = BackgroundColor; canvas.DrawRect(background, paint); // Fill triangle canvas.Save(); canvas.Translate(triangleOffsetX, triangleOffsetY); canvas.DrawPath(trianglePath, paint); canvas.Restore(); if (textLayout != null) { // Draw text canvas.Save(); canvas.Translate(halfStrokeWidth + triangleWidth + PopupPadding, halfStrokeWidth + PopupPadding); textLayout.Draw(canvas); canvas.Restore(); } return(BitmapUtils.CreateBitmapFromAndroidBitmap(bitmap)); }
public void ResizeText(int width, int height) { var text = TextFormatted; if (text == null || text.Length() == 0 || height <= 0 || width <= 0 || mTextSize == 0) { return; } if (TransformationMethod != null) { text = TransformationMethod.GetTransformationFormatted(TextFormatted, this); } TextPaint textPaint = Paint; float oldTextSize = textPaint.TextSize; float targetTextSize = mMaxTextSize > 0 ? System.Math.Min(mTextSize, mMaxTextSize) : mTextSize; int textHeight = GetTextHeight(text, textPaint, width, targetTextSize); while (textHeight > height && targetTextSize > mMinTextSize) { targetTextSize = System.Math.Max(targetTextSize - 2, mMinTextSize); textHeight = GetTextHeight(text, textPaint, width, targetTextSize); } if (AddEllipsis && targetTextSize == mMinTextSize && textHeight > height) { TextPaint paint = new TextPaint(textPaint); StaticLayout layout = new StaticLayout(text, paint, width, Layout.Alignment.AlignNormal, mSpacingMult, mSpacingAdd, false); if (layout.LineCount > 0) { int lastLine = layout.GetLineForVertical(height) - 1; if (lastLine < 0) { SetText("", BufferType.Normal); } else { int start = layout.GetLineStart(lastLine); int end = layout.GetLineEnd(lastLine); float lineWidth = layout.GetLineWidth(lastLine); float ellipseWidth = textPaint.MeasureText(mEllipsis); while (width < lineWidth + ellipseWidth) { lineWidth = textPaint.MeasureText(text.SubSequence(start, --end + 1).ToString()); } SetText(text.SubSequence(0, end) + mEllipsis, BufferType.Normal); } } } SetTextSize(ComplexUnitType.Px, targetTextSize); SetLineSpacing(mSpacingAdd, mSpacingMult); mTextResizeListener?.OnTextResize(this, oldTextSize, targetTextSize); mNeedsResize = false; }
// Resize the text size with specified width and height public void ResizeText(int width, int height) { ICharSequence text = new Java.Lang.String(Text); // Do not resize if the view does not have dimensions or there is no text if (text == null || text.Length() == 0 || height <= 0 || width <= 0 || mTextSize == 0) { return; } if (TransformationMethod != null) { text = TransformationMethod.GetTransformationFormatted(text, this); } // Get the text view's paint object TextPaint textPaint = Paint; // Store the current text size float oldTextSize = textPaint.TextSize; // If there is a max text size set, use the lesser of that and the default text size float targetTextSize = mMaxTextSize > 0 ? Math.Min(mTextSize, mMaxTextSize) : mTextSize; // Get the required text height int textHeight = GetTextHeight(text, textPaint, width, targetTextSize); // Until we either fit within our text view or we had reached our min text size, incrementally try smaller sizes while (textHeight > height && targetTextSize > mMinTextSize) { targetTextSize = Math.Max(targetTextSize - 2, mMinTextSize); textHeight = GetTextHeight(text, textPaint, width, targetTextSize); } // If we had reached our minimum text size and still don't fit, append an ellipsis if (mAddEllipsis && targetTextSize == mMinTextSize && textHeight > height) { TextPaint paint = new TextPaint(textPaint); // Draw using a static layout StaticLayout layout = new StaticLayout(text, paint, width, Layout.Alignment.AlignNormal, mSpacingMult, mSpacingAdd, false); // Check that we have a least one line of rendered text if (layout.LineCount > 0) { // Since the line at the specific vertical position would be cut off, // we must trim up to the previous line int lastLine = layout.GetLineForVertical(height) - 1; // If the text would not even fit on a single line, clear it if (lastLine < 0) { Text = ""; } // Otherwise, trim to the previous line and add an ellipsis else { int start = layout.GetLineStart(lastLine); int end = layout.GetLineEnd(lastLine); float lineWidth = layout.GetLineWidth(lastLine); float ellipseWidth = textPaint.MeasureText(mEllipsis); // Trim characters off until we have enough room to draw the ellipsis while (width < lineWidth + ellipseWidth) { lineWidth = textPaint.MeasureText(text.SubSequence(start, --end + 1).ToString()); } Text = (text.SubSequence(0, end) + mEllipsis); } } } // Some devices try to auto adjust line spacing, so force default line spacing // and invalidate the layout as a side effect SetTextSize(ComplexUnitType.Px, targetTextSize); SetLineSpacing(mSpacingAdd, mSpacingMult); // Notify the listener if registered if (mTextResizeListener != null) { mTextResizeListener.OnTextResize(this, oldTextSize, targetTextSize); } // Reset force resize flag mNeedsResize = false; }
// Set the text size of the text paint object and use a static layout to render text off screen before measuring private int GetTextWidth(string source, TextPaint paint, float textSize) { // Update the text paint object paint.TextSize = textSize; //Measure width of text using the Paint object's MeasureText method. //NOTE: the StaticLayout Width property does not return the correct width, so we use this method instead. return Convert.ToInt32( paint.MeasureText(source, 0, source.Length) ); }