Zoom-able CarouselView in Xamarin.form - c#

I'm using carousel view to display a number of images, changeable upon sliding. The problem I'm having is that these images are not zoom-able. Is there any way to enable zooming within carousel view? Thanks.

Ok so the First Thing first Carousel View is not a gud thing which you want to make zoom (for Practical Case)
and as client demands out of the Galaxy things so you can make things work out with some logic
1st Way:
Create a Class Name ZoomImage in Your Shared Xamarin.forms Solution and Add this code in it
public class ZoomImage : Image {
private const double MIN_SCALE = 1;
private const double MAX_SCALE = 4;
private const double OVERSHOOT = 0.15;
private double StartScale;
private double LastX, LastY;
public ZoomImage() {
var pinch = new PinchGestureRecognizer();
pinch.PinchUpdated += OnPinchUpdated;
GestureRecognizers.Add(pinch);
var pan = new PanGestureRecognizer();
pan.PanUpdated += OnPanUpdated;
GestureRecognizers.Add(pan);
var tap = new TapGestureRecognizer { NumberOfTapsRequired = 2 };
tap.Tapped += OnTapped;
GestureRecognizers.Add(tap);
Scale = MIN_SCALE;
TranslationX = TranslationY = 0;
AnchorX = AnchorY = 0;
}
protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint) {
Scale = MIN_SCALE;
TranslationX = TranslationY = 0;
AnchorX = AnchorY = 0;
return base.OnMeasure(widthConstraint, heightConstraint);
}
private void OnTapped(object sender, EventArgs e) {
if (Scale > MIN_SCALE) {
this.ScaleTo(MIN_SCALE, 250, Easing.CubicInOut);
this.TranslateTo(0, 0, 250, Easing.CubicInOut);
}
else {
AnchorX = AnchorY = 0.5; //TODO tapped position
this.ScaleTo(MAX_SCALE, 250, Easing.CubicInOut);
}
}
private void OnPanUpdated(object sender, PanUpdatedEventArgs e) {
if (Scale > MIN_SCALE)
switch (e.StatusType) {
case GestureStatus.Started:
LastX = TranslationX;
LastY = TranslationY;
break;
case GestureStatus.Running:
TranslationX = Clamp(LastX + e.TotalX * Scale, -Width / 2, Width / 2);
TranslationY = Clamp(LastY + e.TotalY * Scale, -Height / 2, Height / 2);
break;
}
}
private void OnPinchUpdated(object sender, PinchGestureUpdatedEventArgs e) {
switch (e.Status) {
case GestureStatus.Started:
StartScale = Scale;
AnchorX = e.ScaleOrigin.X;
AnchorY = e.ScaleOrigin.Y;
break;
case GestureStatus.Running:
double current = Scale + (e.Scale - 1) * StartScale;
Scale = Clamp(current, MIN_SCALE * (1 - OVERSHOOT), MAX_SCALE * (1 + OVERSHOOT));
break;
case GestureStatus.Completed:
if (Scale > MAX_SCALE)
this.ScaleTo(MAX_SCALE, 250, Easing.SpringOut);
else if (Scale < MIN_SCALE)
this.ScaleTo(MIN_SCALE, 250, Easing.SpringOut);
break;
}
}
private T Clamp<T>(T value, T minimum, T maximum) where T : IComparable {
if (value.CompareTo(minimum) < 0)
return minimum;
else if (value.CompareTo(maximum) > 0)
return maximum;
else
return value;
}
}
and now In Xaml within carousel view Use Image Like This
<cv:CarouselView x:Name="itemPictureGallery" Grid.Column="0" Grid.Row="0">
<cv:CarouselView.ItemTemplate>
<DataTemplate>
<local:image source="YOUR_PIC_SOURCE" />
</DataTemplate>
</cv:CarouselView.ItemTemplate>
</cv:CarouselView>
Dont Forget to add nameSpace in Xamal
xmlns:local="clr-namespace:YOUR_APP_NAME"
so this is how the image can zoom etiher
Or Second Way is
add an Item Tapped on carousel view and pass the picture source in command parameter and open a new page with that picture in it and apply zoom with in it
i use that logic for figure out my problem
Hope this Helps :)

This can be achieved by using
alexrainman/CarouselView for the carousal view.
https://github.com/alexrainman/CarouselView
and add Xamarin forms pinch gesture recognizer according to the forms sample to the image used in carousal view
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/gestures/pinch

Related

Why child control ignores the size set with Arrange in parent container?

I wrote an EditorPanel container, which orders controls in a label/editor order. The complete source of the control follows:
public class EditorPanel : Panel
{
private enum GeneralAlignment
{
Begin,
Center,
End,
Stretch
}
private static GeneralAlignment ToGeneralAlignment(VerticalAlignment verticalAlignment)
{
switch (verticalAlignment)
{
case VerticalAlignment.Top:
return GeneralAlignment.Begin;
case VerticalAlignment.Center:
return GeneralAlignment.Center;
case VerticalAlignment.Bottom:
return GeneralAlignment.End;
case VerticalAlignment.Stretch:
return GeneralAlignment.Stretch;
default:
throw new InvalidEnumArgumentException("Unsupported vertical alignment!");
}
}
private static GeneralAlignment ToGeneralAlignment(HorizontalAlignment horizontalAlignment)
{
switch (horizontalAlignment)
{
case HorizontalAlignment.Left:
return GeneralAlignment.Begin;
case HorizontalAlignment.Center:
return GeneralAlignment.Center;
case HorizontalAlignment.Right:
return GeneralAlignment.End;
case HorizontalAlignment.Stretch:
return GeneralAlignment.Stretch;
default:
throw new InvalidEnumArgumentException("Unsupported horizontal alignment!");
}
}
private Size DesiredSizeWithMargin(UIElement element)
{
if (element == null)
return Size.Empty;
if (element is FrameworkElement frameworkElement)
return new Size(frameworkElement.DesiredSize.Width + frameworkElement.Margin.Left + frameworkElement.Margin.Right,
frameworkElement.DesiredSize.Height + frameworkElement.Margin.Top + frameworkElement.Margin.Bottom);
else
return element.DesiredSize;
}
private static (double elementStart, double elementSize) EvalPlacement(UIElement element,
double placementRectStart,
double placementRectSize,
double elementMarginBegin,
double elementMarginEnd,
double elementDesiredSize,
GeneralAlignment elementAlignment)
{
double resultSize;
double resultStart;
switch (elementAlignment)
{
case GeneralAlignment.Begin:
resultSize = Math.Max(0, Math.Min(elementDesiredSize, placementRectSize - (elementMarginBegin + elementMarginEnd)));
resultStart = placementRectStart + elementMarginBegin;
break;
case GeneralAlignment.Center:
resultSize = Math.Max(0, Math.Min(elementDesiredSize, placementRectSize - (elementMarginBegin + elementMarginEnd)));
resultStart = placementRectStart + (placementRectSize - (resultSize + elementMarginBegin + elementMarginEnd)) / 2 + elementMarginBegin;
break;
case GeneralAlignment.End:
resultSize = Math.Max(0, Math.Min(elementDesiredSize, placementRectSize - (elementMarginBegin + elementMarginEnd)));
resultStart = placementRectStart + placementRectSize - elementMarginEnd - resultSize;
break;
case GeneralAlignment.Stretch:
resultSize = Math.Max(0, placementRectSize - (elementMarginBegin + elementMarginEnd));
resultStart = placementRectStart + elementMarginBegin;
break;
default:
throw new InvalidEnumArgumentException("Unsupported alignment!");
}
return (resultStart, resultSize);
}
private void ArrangeWithAlignment(UIElement element, Rect placementRect, Size cachedDesiredSize)
{
if (cachedDesiredSize == Size.Empty)
cachedDesiredSize = DesiredSizeWithMargin(element);
Thickness elementMargin = new Thickness();
HorizontalAlignment elementHorizontalAlignment = HorizontalAlignment.Stretch;
VerticalAlignment elementVerticalAlignment = VerticalAlignment.Top;
if (element is FrameworkElement frameworkElement)
{
elementMargin = frameworkElement.Margin;
elementHorizontalAlignment = frameworkElement.HorizontalAlignment;
elementVerticalAlignment = frameworkElement.VerticalAlignment;
}
(double elementTop, double elementHeight) = EvalPlacement(element,
placementRect.Top,
placementRect.Height,
elementMargin.Top,
elementMargin.Bottom,
cachedDesiredSize.Height,
ToGeneralAlignment(elementVerticalAlignment));
(double elementLeft, double elementWidth) = EvalPlacement(element,
placementRect.Left,
placementRect.Width,
elementMargin.Left,
elementMargin.Right,
cachedDesiredSize.Width,
ToGeneralAlignment(elementHorizontalAlignment));
element.Arrange(new Rect(elementLeft, elementTop, elementWidth, elementHeight));
}
protected override Size MeasureOverride(Size availableSize)
{
double maxLabelWidth = 0.0;
double maxEditorWidth = 0.0;
double totalLabelEditorPairHeight = 0.0;
for (int i = 0; i < InternalChildren.Count; i += 2)
{
// Measure label
InternalChildren[i].Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
Size labelDesiredSize = DesiredSizeWithMargin(InternalChildren[i]);
// Measure editor (if any)
Size editorDesiredSize = Size.Empty;
if (i + 1 < InternalChildren.Count)
{
InternalChildren[i + 1].Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
editorDesiredSize = DesiredSizeWithMargin(InternalChildren[i + 1]);
}
maxLabelWidth = Math.Max(maxLabelWidth, labelDesiredSize.Width);
maxEditorWidth = Math.Max(maxEditorWidth, editorDesiredSize.Width);
totalLabelEditorPairHeight += Math.Max(labelDesiredSize.Height, editorDesiredSize.Height);
}
// This is required height, regardless of how much space is available
double resultHeight = totalLabelEditorPairHeight;
// If space is not constrained, pick as much as labels & editors want. Else, use
// as much, as is given.
double resultWidth = double.IsInfinity(availableSize.Width) ? maxLabelWidth + maxEditorWidth : availableSize.Width;
return new Size(resultWidth, resultHeight);
}
protected override Size ArrangeOverride(Size finalSize)
{
// Label area width
double labelAreaWidth = 0;
for (int i = 0; i < InternalChildren.Count; i += 2)
labelAreaWidth = Math.Max(labelAreaWidth, DesiredSizeWithMargin(InternalChildren[i]).Width);
labelAreaWidth = Math.Min(labelAreaWidth, finalSize.Width);
// Editor area width
double editorAreaWidth = Math.Max(0, finalSize.Width - labelAreaWidth);
// Arranging controls
double y = 0;
int controlIndex = 0;
while (controlIndex < InternalChildren.Count)
{
// Retrieve label and editor
UIElement label = InternalChildren[controlIndex++];
Size labelDesiredSize = DesiredSizeWithMargin(label);
UIElement editor = (controlIndex < InternalChildren.Count) ? InternalChildren[controlIndex++] : null;
Size editorDesiredSize = DesiredSizeWithMargin(editor);
double rowHeight = Math.Max(labelDesiredSize.Height, editorDesiredSize.Height);
var labelArea = new Rect(0, y, labelAreaWidth, rowHeight);
ArrangeWithAlignment(label, labelArea, label.DesiredSize);
// Arrange editor
if (editor != null)
{
var editorArea = new Rect(labelAreaWidth, y, editorAreaWidth, rowHeight);
ArrangeWithAlignment(editor, editorArea, editor.DesiredSize);
}
y += Math.Max(labelDesiredSize.Height, editorDesiredSize.Height);
}
return finalSize;
}
}
Example of usage may look like following:
<Border BorderBrush="Black" BorderThickness="1"
Width="400" Height="100">
<controls:EditorPanel>
<Label>First label</Label>
<TextBox />
<Label>Second label</Label>
<TextBox />
</controls:EditorPanel>
</Border>
When I run the application, it looks like following:
However, if I write more text in the textbox, it starts to escape the boundaries set by the EditorPanel itself.
What is interesting is that the container seems to work properly and allocates proper amount of space for the control:
But the control seems to ignore it completely and ends up bigger than it actually should be:
That leads to my question: why the child control ignores the space it was given through the Arrange call?
It turns out, that I was too generous during the Measure stage. I put more effort into checking, how much space labels and editors can occupy and now everything works.
protected override Size MeasureOverride(Size availableSize)
{
// Measure labels
List<Size> labelSizes = new List<Size>();
for (int i = 0; i < InternalChildren.Count; i += 2)
{
// Measure label
Thickness labelMargin = new Thickness(0);
if (InternalChildren[i] is FrameworkElement frameworkElement)
labelMargin = frameworkElement.Margin;
InternalChildren[i].Measure(new Size(availableSize.Width - (labelMargin.Left + labelMargin.Right), availableSize.Height - (labelMargin.Top + labelMargin.Bottom)));
labelSizes.Add(DesiredSizeWithMargin(InternalChildren[i]));
}
double maxLabelWidth = labelSizes.Max(ls => ls.Width);
// Measure editors
List<Size> editorSizes = new List<Size>();
for (int i = 1; i < InternalChildren.Count; i += 2)
{
Thickness editorMargin = new Thickness(0);
if (InternalChildren[i] is FrameworkElement frameworkElement)
editorMargin = frameworkElement.Margin;
InternalChildren[i].Measure(new Size(availableSize.Width - maxLabelWidth - (editorMargin.Left + editorMargin.Right), availableSize.Height - (editorMargin.Top + editorMargin.Bottom)));
editorSizes.Add(DesiredSizeWithMargin(InternalChildren[i]));
}
double maxEditorWidth = editorSizes.Max(es => es.Width);
// Equalize count
while (editorSizes.Count < labelSizes.Count)
editorSizes.Add(Size.Empty);
// Evaluate total height
double totalLabelEditorPairHeight = labelSizes.Zip(editorSizes)
.Select(sizes => Math.Max(sizes.First.Height, sizes.Second.Height))
.Sum();
// This is required height, regardless of how much space is available
double resultHeight = totalLabelEditorPairHeight;
// If space is not constrained, pick as much as labels & editors want. Else, use
// as much, as is given.
double resultWidth = double.IsInfinity(availableSize.Width) ? maxLabelWidth + maxEditorWidth : availableSize.Width;
return new Size(resultWidth, resultHeight);
}

Increase Animation Speed Win2d line UWP

I would like to increase the animation speed of the line by keeping the step 1.
Xaml:
<canvas:CanvasAnimatedControl x:Name="canvas"
Margin="0,30,0,0"
Height="500"
Draw="OnDraw"/>
cs:
private bool _adding = true;
private int _Offset = 0;
private void OnDraw(Microsoft.Graphics.Canvas.UI.Xaml.ICanvasAnimatedControl sender, Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedDrawEventArgs args)
{
CanvasDrawingSession ds = args.DrawingSession;
double height = sender.Size.Height;
double width = sender.Size.Width;
var point1 = new Vector2((float)(width / 2), (float)height);
var point2 = new Vector2((float)(width / 2), (float)height - (float)_Offset);
CanvasSolidColorBrush brush = new CanvasSolidColorBrush(sender, Colors.Green);
ds.DrawLine(point1, point2, brush, (float)10);
if (_adding)
{
_Offset++;
}
else
{
_Offset--;
}
if (_Offset == 0 || _Offset == 300)
{
_adding = !_adding;
}
}
Is it possible to keep the _offset step at 1 but increase the line animation speed and to keep TargetElapsedTime at 16?

How to create a movable and clickable button in android

I'm new to Xamarin Android and currently working on a floating action button, I implemented View.IOnTouchListener and normal button click event (faButton.Click += floatButtonPressed;) to carry out my actions. But for the case MotionEventActions.Move, it doesn't work as I wanted. Moving left and right it works fine but for top and bottom it will move downwards a little bit whenever I start moving it. Besides, when I move the button to screen border it will be able to exceed the screen. Hence, I tried detect screen size and restrict it but it still not good enough, is there any other available solution or settings?
public bool OnTouch(View v, MotionEvent e)
{
switch (e.Action)
{
case MotionEventActions.Down:
oldXvalue = e.GetX();
oldYvalue = e.GetY();
if (oldXvalue == e.GetX() && oldYvalue == e.GetY())
{
return false;
}
break;
case MotionEventActions.Up:
if (oldXvalue == e.GetX() && oldYvalue == e.GetY())
{
return false;
}
break;
case MotionEventActions.Move:
var xleft = (int)(e.RawX - oldXvalue);
var xright = xleft + v.Width;
var ytop = (int)(e.RawY - oldYvalue);
var ybtm = (ytop + v.Height);
if (xleft + v.Width >= intWidth)
{
break;
}
if (xleft <= 0)
{
break;
}
if (ytop + v.Height >= intHeight)
{
break;
}
if (ytop <= 0)
{
break;
}
v.Layout(xleft, ytop, xright, ybtm);
break;
}
return true;
}
You can get the screen height and screen width first. And when the button exceed the screen you need to reset the button position.
Try the following code:
public class MainActivity : Activity, IOnTouchListener
{
Button dragAbleBt;
int screenWidth = 0;
int screenHeight = 0;
int lastX = 0, lastY = 0;
public bool OnTouch(View v, MotionEvent e)
{
MotionEventActions ea = e.Action;
switch (ea) {
case MotionEventActions.Down:
lastX = (int)e.RawX;
lastY = (int)e.RawY;
break;
case MotionEventActions.Move:
int dx = (int)e.RawX - lastX;
int dy = (int)e.RawY - lastY;
int left = v.Left + dx;
int right = v.Right + dx;
int top = v.Top + dy;
int bottom = v.Bottom + dy;
if (left < 0)
{
left = 0;
right = left + v.Width;
}
if (right > screenWidth)
{
right = screenWidth;
left = right - v.Width;
}
if (top < 0)
{
top = 0;
bottom = top + v.Height;
}
if (bottom > screenHeight)
{
bottom = screenHeight;
top = bottom - v.Height;
}
v.Layout(left, top, right, bottom);
lastX = (int) e.RawX;
lastY = (int) e.RawY;
v.PostInvalidate();
break;
case MotionEventActions.Up:
break;
}
return false;
}
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView (Resource.Layout.Main);
//DisplayMetrics dm = Resources.DisplayMetrics;
//screenWidth = dm.WidthPixels;
//screenHeight = dm.HeightPixels;
dragAbleBt = FindViewById<Button>(Resource.Id.button1);
dragAbleBt.SetOnTouchListener(this);
}
public override void OnWindowFocusChanged(bool hasFocus)
{
base.OnWindowFocusChanged(hasFocus);
if (hasFocus)
{
Rect outRect = new Rect();
this.Window.FindViewById(Window.IdAndroidContent).GetDrawingRect(outRect);
screenWidth = outRect.Width();
screenHeight = outRect.Height();
}
}
}
I tried detect screen size and restrict it but it still not good enough, is there any other available solution or settings?
You may got the whole screen width and height, the button will exceed the screen height, In this kind of situation you need get the view drawing area by this.Window.FindViewById(Window.IdAndroidContent).GetDrawingRect(outRect)
Screen Shot:
Note: I am using the emulator that is slow, If you are using the real device it will be faster.

How to use ScrollableControl with AutoScroll set to false

I have a custom control that zooms on a custom drawn document canvas.
I tried using AutoScroll but it was not giving satisfactory results. When I would set AutoScrollPosition and AutoScrollMinSize back to back (in any order) it would force a paint and cause jitter each time the zoom changes. I assume this was because it was calling an Update and not Invalidate when I modified both properties.
I am now manually setting the HorizontalScroll and VerticalScroll properties with AutoScroll set to false like so each time the Zoom level or the client size changes:
int canvasWidth = (int)Math.Ceiling(Image.Width * Zoom) + PageMargins.Horizontal;
int canvasHeight = (int)Math.Ceiling(Image.Height * Zoom) + PageMargins.Vertical;
HorizontalScroll.Maximum = canvasWidth;
HorizontalScroll.LargeChange = ClientSize.Width;
VerticalScroll.Maximum = canvasHeight;
VerticalScroll.LargeChange = ClientSize.Height;
if (canvasWidth > ClientSize.Width)
{
HorizontalScroll.Visible = true;
}
else
{
HorizontalScroll.Visible = false;
HorizontalScroll.Value = 0;
}
if (canvasHeight > ClientSize.Height)
{
VerticalScroll.Visible = true;
}
else
{
VerticalScroll.Visible = false;
VerticalScroll.Value = 0;
}
int focusX = (int)Math.Floor((FocusPoint.X * Zoom) + PageMargins.Left);
int focusY = (int)Math.Floor((FocusPoint.Y * Zoom) + PageMargins.Top);
focusX = focusX - ClientSize.Width / 2;
focusY = focusY - ClientSize.Height / 2;
if (focusX < 0)
focusX = 0;
if (focusX > canvasWidth - ClientSize.Width)
focusX = canvasWidth - ClientSize.Width;
if (focusY < 0)
focusY = 0;
if (focusY > canvasHeight - ClientSize.Height)
focusY = canvasHeight - ClientSize.Height;
if (HorizontalScroll.Visible)
HorizontalScroll.Value = focusX;
if (VerticalScroll.Visible)
VerticalScroll.Value = focusY;
In this case, FocusPoint is a PointF structure that holds the coordinates in the bitmap which the user is focused on (for example, when they mouse wheel to zoom in they are focusing on the current mouse location at that time). This functionality works for the most part.
What does not work is the scroll bars. If the user tries to manually scroll by clicking on either scroll bar, they both keep returning to 0. I do not set them anywhere else in my code. I have tried writing the following in the OnScroll() method:
if (se.ScrollOrientation == ScrollOrientation.VerticalScroll)
{
VerticalScroll.Value = se.NewValue;
}
else
{
HorizontalScroll.Value = se.NewValue;
}
Invalidate();
But this causes some very erratic behavior including flicking and scrolling out of bounds.
How am I supposed to write the code for OnScroll? I've tried the base.OnScroll but it didn't do anything while AutoScroll is set to false.
I ended up implementing my own custom scrolling by creating 3 child controls: an HScrollBar, a VScrollBar, and a Panel.
I hide ClientSize and ClientRectangle like so:
public new Rectangle ClientRectangle
{
get
{
return new Rectangle(new Point(0, 0), ClientSize);
}
}
public new Size ClientSize
{
get
{
return new Size(
base.ClientSize.Width - VScrollBar.Width,
base.ClientSize.Height - HScrollBar.Height
);
}
}
The layout is done in OnClientSizeChanged:
protected override void OnClientSizeChanged(EventArgs e)
{
base.OnClientSizeChanged(e);
HScrollBar.Location = new Point(0, base.ClientSize.Height - HScrollBar.Height);
HScrollBar.Width = base.ClientSize.Width - VScrollBar.Width;
VScrollBar.Location = new Point(base.ClientSize.Width - VScrollBar.Width, 0);
VScrollBar.Height = base.ClientSize.Height - HScrollBar.Height;
cornerPanel.Size = new Size(VScrollBar.Width, HScrollBar.Height);
cornerPanel.Location = new Point(base.ClientSize.Width - cornerPanel.Width, base.ClientSize.Height - cornerPanel.Height);
}
Each ScrollBar has their Scroll event subscribed to the following:
private void ScrollBar_Scroll(object sender, ScrollEventArgs e)
{
OnScroll(e);
}
And finally we can allow MouseWheel events to scroll with the following:
protected override void OnMouseWheel(MouseEventArgs e)
{
int xOldValue = VScrollBar.Value;
if (e.Delta > 0)
{
VScrollBar.Value = (int)Math.Max(VScrollBar.Value - (VScrollBar.SmallChange * e.Delta), 0);
OnScroll(new ScrollEventArgs(ScrollEventType.ThumbPosition, xOldValue, VScrollBar.Value, ScrollOrientation.VerticalScroll));
}
else
{
VScrollBar.Value = (int)Math.Min(VScrollBar.Value - (VScrollBar.SmallChange * e.Delta), VScrollBar.Maximum - (VScrollBar.LargeChange - 1));
OnScroll(new ScrollEventArgs(ScrollEventType.ThumbPosition, xOldValue, VScrollBar.Value, ScrollOrientation.VerticalScroll));
}
}
For custom painting, you would use the following statement:
e.Graphics.TranslateTransform(-HScrollBar.Value, -VScrollBar.Value);
This worked perfectly without the glitches present when using AutoScroll.

How to set Location of another Control proportionally

My problem is : I have 2 Panels (panel1,panel2) where panel1.Size = new Size(200, 200); and Panel2.Size = new Size(600, 600); where both panel's have within a CustomControl which can get Dragged and change it Possition (szbControl1 ,szbControl2) .
My Question is ,how can i set szbControl2.Location properly (proportionally)based on szbControl1.Location where szbControl1 parent is panel1 and szbControl2 parent is panel2 ,like if i move the szbControl1 at bottom also szbControl2 should be at bottom.
So far i tried this :
private void sizeAbleCTR2_LocationChanged(object sender, EventArgs e)
{
int smallX = (sizeAbleCTR2.Location.X * panel1.Size.Width) / 100;
int smallY = (sizeAbleCTR2.Location.Y * panel1.Size.Height) / 100;
int largeX = (smallX * panel2.Width) / 100;
int largeY = (smallY * panel2.Height) / 100;
sizeAbleCTR1.Location = new Point(largeX,largeY);
}
like using the Percentage but it's not working .
The code you provided does not take into account the size of the szbControls. The ratio of the (location/the differences of the sizes) should be equal.
private void sizeAbleCTR2_LocationChanged(object sender, EventArgs e)
{
float srcHeightDiff = panel2.Height - sizeAbleCTR2.Height;
float dstHeightDiff = panel1.Height - sizeAbleCTR1.Height;
int locY = (int)(dstHeightDiff * (sizeAbleCTR2.Location.Y / srcHeightDiff));
float srcWidthDiff = panel2.Width - sizeAbleCTR2.Width;
float dstWidthDiff = panel1.Width - sizeAbleCTR1.Width;
int locX = (float)(dstWidthDiff * (sizeAbleCTR2.Location.X / srcWidthDiff));
sizeAbleCTR1.Location = new Point(locX, locY);
}

Categories

Resources