Xamarin Forms TranslateTo relative to parent - xamarin

I'm using TranslateTo to move an object vertically on the screen, but I only see how to use numbers for the x/y arguments. How can I do something like when adding an object on a view where you say, "Constraint.RelativeToParent(..."?
CAN I translate relative to something else?

Sounds like you want to use a RelativeLayout perhaps?
There is a discussion here, and a demo here that may get you started?
Yes - you can perform a Translate operation on a View that is relative to some other View.
The following example demonstrates that:-
StackLayout objStackLayout = new StackLayout()
{
Orientation = StackOrientation.Vertical,
};
RelativeLayout objRelativeLayout = new RelativeLayout();
objStackLayout.Children.Add(objRelativeLayout);
Label objLabel1 = new Label();
objLabel1.BackgroundColor = Color.Red;
objLabel1.Text = "This is a label";
objLabel1.SizeChanged += ((o2, e2) =>
{
objRelativeLayout.ForceLayout();
});
objRelativeLayout.Children.Add(objLabel1,
xConstraint: Constraint.RelativeToParent((parent) =>
{
return ((parent.Width - objLabel1.Width) / 2);
}));
Button objButton = new Button();
objButton.BackgroundColor = Color.Blue;
objButton.Text = "Hi";
objRelativeLayout.Children.Add(objButton,
xConstraint: Constraint.RelativeToView(objLabel1,
new Func<RelativeLayout, View, double>((pobjRelativeLayout, pobjView) =>
{
return pobjView.X + pobjView.Width;
})));
Button objButton1 = new Button();
objButton1.Text = "Translate the button that is relative to the text";
objButton1.Clicked += ((o2, e2) =>
{
objButton.TranslateTo(100,100,2000);
});
objStackLayout.Children.Add(objButton1);
Button objButton2 = new Button();
objButton2.Text = "Change label text";
objButton2.Clicked += ((o2, e2) =>
{
objLabel1.Text = "text";
});
objStackLayout.Children.Add(objButton2);
Clicking on the button with text "Translate the button that is relative to the text" will translate the blue button by 100 width and 100 height.
The rule is still enforced when you click the button with text "Change label text". Note that the translation previously applied is still at an offset of 100 width and 100 height from the end of the Label that we are doing our relative layout against.

Related

how to apply max height and enable scroll to Xamarin.Forms.Editor

I wanted chat application type user interface in my app & i am targeting android and iOS.
I am using Xamarin.Forms.Editor for reply
Editor _replyEntry = new Editor
{
HorizontalOptions = LayoutOptions.FillAndExpand,
TextColor = Color.Black
}
in this case the editor height remains constant and allows scrolling and editor does not expands
Then i used InvalidateMeasure()
_replyEntry .TextChanged += (sender, e) => { this.InvalidateMeasure(); };
in this case editor expands as when the text requires more space but does not allow scroll inside editor and if user types long message then editor does not allows scroll and text goes behind the keyboard and not visible to user
Is there any way to enable scroll and give max height to edit either in xamarin.forms of by writing custom renderer
Thanks
Here is my code
public class abc : ContentPage
{
public abc()
{
Image attchment = new Image
{
Source = "attachment.png",
HorizontalOptions = LayoutOptions.Start
};
Editor _replyEntry = new Editor
{
HorizontalOptions = LayoutOptions.FillAndExpand,
TextColor = Color.Black,
};
Button _sendButton = new Button
{
Text = "Send",
TextColor = Color.Black,
BackgroundColor = Color.Transparent,
HorizontalOptions = LayoutOptions.End
};
StackLayout replyStack = new StackLayout
{
Orientation = StackOrientation.Horizontal,
Padding = new Thickness(10),
Spacing = 10,
VerticalOptions = LayoutOptions.End,
Children = { attchment, _replyEntry, _sendButton }
};
Content = replyStack;
}
}
It looks like you will have to use a custom renderer to achieve what you are wanting.
There is a post here that has pretty much the same thing with what you are trying to achieve for Android.
In that demo it has an expanding multi-line EditText control (android:singleLine="false"), with only vertical scrollbars (android:scrollbars="vertical"), whilst disabling the horizontal scrollbars (android:scrollHorizontally="false").
You need to ensure the Editor' parent is expanding, then the editor will automatically expand too. If you make an empty contentpage and add an Editor, the is will just expand. If you place it inside a stacklayout, the you need to ensure that the stacklayout is expanding.

How to center a view horizontally in a Xamarin.Forms RelativeLayout?

I want to center a label horizontally in a RelativeLayout in Xamarin.Forms. I tried something like this, but it doesn't work:
var label = new Label {HorizontalOptions = LayoutOptions.Center};
var rl = new RelativeLayout();
rl.Children.Add(label, Constraint.RelativeToParent((parent) => parent.Width / 2 - label.Width / 2));
I want to place a second label on the right of my label while the first label is centered horizontally. How can I achieve that?
When you are doing RelativeLayouts you have Constraints that you can specify.
To achieve what you are aiming to do, you need to use a RelativeToParent Constraint first, and then a RelativeToView Constraint for the 2nd label that is attached to the right of the first view.
The first view will then be centered horizontally across the whole page, with the 2nd label attached relative to the first view afterwards.
The following example shows this:-
RelativeLayout objRelativeLayout = new RelativeLayout();
Label objLabel1 = new Label();
objLabel1.BackgroundColor = Color.Red;
objLabel1.Text = "This is a label";
objLabel1.WidthRequest = 300;
objRelativeLayout.Children.Add(objLabel1,
xConstraint: Constraint.RelativeToParent((parent) =>
{
return ((parent.Width - objLabel1.Width) / 2);
}));
Label objLabel2 = new Label();
objLabel2.BackgroundColor = Color.Blue;
objLabel2.Text = "Hi";
objLabel2.WidthRequest = 100;
objRelativeLayout.Children.Add(objLabel2,
xConstraint: Constraint.RelativeToView(objLabel1,
new Func<RelativeLayout, View, double>((pobjRelativeLayout, pobjView) =>
{
return pobjView.X + pobjView.Width;
})));
this.Content = objRelativeLayout;
Update 1:-
If you don't want to use a specified Width or the contents are of an unknown size then you will have to trigger a re-layout via calling ForceLayout on the RelativeLayout when the view(s) need to be repositioned according to the Constraints you have defined.
The updated example below illustrates this:-
StackLayout objStackLayout = new StackLayout()
{
Orientation = StackOrientation.Vertical,
};
RelativeLayout objRelativeLayout = new RelativeLayout();
objStackLayout.Children.Add(objRelativeLayout);
Label objLabel1 = new Label();
objLabel1.BackgroundColor = Color.Red;
objLabel1.Text = "This is a label";
objLabel1.SizeChanged += ((o2, e2) =>
{
objRelativeLayout.ForceLayout();
});
objRelativeLayout.Children.Add(objLabel1,
xConstraint: Constraint.RelativeToParent((parent) =>
{
return ((parent.Width - objLabel1.Width) / 2);
}));
Label objLabel2 = new Label();
objLabel2.BackgroundColor = Color.Blue;
objLabel2.Text = "Hi";
objRelativeLayout.Children.Add(objLabel2,
xConstraint: Constraint.RelativeToView(objLabel1,
new Func<RelativeLayout, View, double>((pobjRelativeLayout, pobjView) =>
{
return pobjView.X + pobjView.Width;
})));
Button objButton1 = new Button();
objButton1.Text = "Test1";
objButton1.Clicked += ((o2, e2) =>
{
objLabel1.Text = "This is some other label text";
});
objStackLayout.Children.Add(objButton1);
this.Content = objStackLayout;

How to add a click handler to content page in xamarin forms

I am new at Xamarin.Forms and are trying to add a click event to my content page. I want an event to start when the user clicks on the page, no matter where.
I've created similar functionality in a WinPhone app, where I could solve my problem with OnLeftMouseButtonDown which was available on PhoneApplicationPage, but I could not find a suitable counterpart in the ContentPage. Any suggestions?
In order to get this working you have to add a Layout to the ContentPage, as you will want to specify some content, and set the HorizontalOptions and VerticalOptions to LayoutOptions.FillAndExpand.
This is not enough though to handle the taps correctly though.
You also need to specify a BackgroundColor for the Layout. I set mine to Color.Transparent. If you try without specifying a Color it does not work.
You then have to attach a TapGestureRecognizer to the ContentPage in order to catch the clicks that are made.
Although this works well with Labels and Buttons in my test below, still receiving the TapGestures for WindowsPhone on both types, along with the Button click event firing - this does not fully work with Android - as the Button click will prevent the TapGesture event from firing.
The other alternative is to try putting an 'invisible' Grid over the top of everything. However the issue with this approach is that you will loose the Click event handler from firing with WindowsPhone and also loose the Click event handler from firing with Android. The good part though - is that you can detect a click anywhere, although not pass this on. It just depends what your trying to achieve at the end of the day.
StackLayout objStackLayout = new StackLayout()
{
Orientation = StackOrientation.Horizontal,
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand,
BackgroundColor = Color.Transparent
};
//
Label objLabel1 = new Label();
objLabel1.BackgroundColor = Color.Red;
objLabel1.Text = "label1";
objLabel1.HorizontalOptions = LayoutOptions.Start;
objLabel1.VerticalOptions = LayoutOptions.Start;
objLabel1.WidthRequest = 100;
objLabel1.HeightRequest = 300;
objStackLayout.Children.Add(objLabel1);
//
Label objLabel2 = new Label();
objLabel2.BackgroundColor = Color.Green;
objLabel2.Text = "label2";
objLabel2.Font = Font.OfSize("Arial", 48);
objLabel2.WidthRequest = 100;
objLabel2.HeightRequest = 300;
objStackLayout.Children.Add(objLabel2);
//
Button objButton1 = new Button();
objButton1.Text = "Click Me";
objButton1.WidthRequest = 300;
objButton1.HeightRequest = 300;
objStackLayout.Children.Add(objButton1);
//
this.Content = objStackLayout;
TapGestureRecognizer objTapGestureRecognizer1 = new TapGestureRecognizer();
objTapGestureRecognizer1.Tapped += ((o2, e2) =>
{
System.Diagnostics.Debug.WriteLine("Clicked!");
});
this.Content.GestureRecognizers.Add(objTapGestureRecognizer1);

Adding space in Xamarin.Forms layouts?

What's the proposed way to add space to layouts in Xamarin.Forms?
One way would be to add a Frame with no children like so:
new Frame {
BackgroundColor = Color.White,
HeightRequest = 1,
MinimumHeightRequest = 1,
HasShadow = false
}
Unfortunately, HeightRequest and MinimumHeightRequest get ignored.
Does a better way exist?
You could put your controls inside layouts (like frame, scroll view, stack panel) and use Padding property:
this.stackPanel = new StackLayout ()
{
Padding = new Thickness (8, 8)
};
var scrollView = new ScrollView ()
{
Content = stackPanel,
Padding = new Thickness (1, 2, 3, 4)
};
var frame = new Frame ()
{
Padding = new Thickness (8)
};
If you want space between two buttons for example, I believe this would do the trick. The first one adds 10 to bottom padding, the second adds 10 to top padding for total of 20.
var frame1 = new Frame ()
{
Padding = new Thickness (0,0,0,10),
Content = new Button()
};
var frame2 = new Frame ()
{
Padding = new Thickness (0,10,0,0),
Content = new Button()
};
Most Xamarin.Forms Layouts supports adding space between elements:
StackLayout has a Spacing property,
Grid has RowSpacing and ColumnSpacing properties,
...
Now, if you want to add spacing at a particular place, the way to to it is to include a BoxView:
myStackLayout.Children.Add (new BoxView {Color = Color.Transparent, HeightRequest = 5});
You can also wrap your content in a Frame or ContentView, but it adds padding to the content instead of adding space (although the effect will be the same).
What I do worked perfectly for me:
Suppose you want to distribute 2 Labels evenly on a horizontal StackLayout:
new StackLayout
{
Orientation = StackOrientation.Horizontal,
HorizontalOptions=LayoutOptions.CenterAndExpand,
Spacing = 0, // <- Very important!!
Children = {
new Label { Text = "Label 1" },
new BoxView { HorizontalOptions = LayoutOptions.FillAndExpand }, // <- the clever part
new Label { Text = "Label 2" }
}
};
Summary
By inserting BoxViews that fill the remaining space ("FillAndExpand") between your views, your views appear evenly distributed.
By setting Spacing = 0, you don't get extra space between your views.
Try:
myFrame.TranslateX=10;
myFrame.TranslateY=10;
I wanted to share a screenshot in conjunction with Lay González's answer but the edit queue was full->
To get dynamic spacing similar to CSS "Space-Between" in Xamarin you can insert filler views between your views that actually have content.
Here is an example:
Omit the filler view after the last "actual" view so that the view you want is at the end (the "-50" label at the bottom in the example).

KineticJS change color of text onclick

I am working on KineticJS(Latest version) and i have issue regarding change text color which drawn by drawFunc() shape object.
1)Here is the code of Shpae Object.
var sampleText = new Kinetic.Shape({
x:380,
y:700,
drawFunc: function(context) {
context.beginPath();
var x = 0;
var y = 0;
var text = 'Sample Text';
context.setAttr("font", '15pt Calibri');
context.setAttr('fillStyle','black');
context.fillText(text, x, y)
context.closePath();
// KineticJS specific context method
context.fillStrokeShape(this);
},
id:"sampleText"
});
2)I want to change color of "sample text" on click event which is written using core html5 code (context object).
colorTabViews.on('click', function (e) {
sampleText.sceneFunc(function(context) {
context.beginPath();
//how can i get text which already displayed in shape object("Sample text")?
//or to change color of "sample text"
context.setAttr('fillStyle','green');
context.closePath();
context.fillStrokeShape(this);
});
verticalText.draw();
});
But issue is ,it removes whole text nothing displayed instead of just changing "sample text" color.
Please advice either get text filled by context.fillText() function or alternate way that i can change text color on particular event.
Thanks for your time and consideration in advance.
-Naitik
To programatically change fillStyle inside a Kinetic.Shape
Attach a fill property to your shape object and reference your fill property inside the Kinetic.Shape:
var sampleText = new Kinetic.Shape({
x:10,
y:15,
sceneFunc: function(context) {
context.beginPath();
var x = 0;
var y = 0;
var text = 'Sample Text';
context.setAttr("font", '15pt Calibri');
context.setAttr('fillStyle',this.myFillStyle);
context.fillText(text, x, y)
context.closePath();
// KineticJS specific context method
context.fillStrokeShape(this);
},
id:"sampleText",
fill:"blue"
});
// add a property to sampleText that's used in its sceneFunc
sampleText.myFillStyle="black";
Then you can change that fill property in your click handler:
colorTabViews.on('click', function (e) {
sampleText.myFillStyle="red";
verticalText.draw();
});

Resources