Sliding in and out using xamarin - xaml

I am trying to implement this kind of design as shown in fig on my page, how can I achieve this in Xamarin.forms mainly in shared project. As I am trying to reduce the complexity by doing in platform specific.
I tried using this even https://github.com/XAM-Consulting/SlideOverKit .
But the issue is I can't slide in the menu when its open (i.e after touching on page I want the menu to hide) but it doesn't happen. We need to manually drag that out to close it.
So please let me know how to achieve this.
Thanks

Based on your description, I modifed my code,there is a GIF
When you click the ImageButton, you should call this method this.HideMenu();
code of QuickInnerMenuPage
public QuickInnerMenuPage()
{
Content = new StackLayout
{
VerticalOptions = LayoutOptions.Center,
HorizontalOptions = LayoutOptions.Center,
Children = {
new Label(){Text="1222"}
}
};
this.SlideMenu = new QuickInnerMenuView(MenuOrientation.RightToLeft);
QuickInnerMenuView.ib.Clicked += (o, e) =>
{
this.HideMenu();
};
}
}
There is code of QuickInnerMenuView
public class QuickInnerMenuView : SlideMenuView
{
public static ImageButton ib;
public QuickInnerMenuView (MenuOrientation orientation)
{
ib = new ImageButton
{
Source = "Happy.png",
WidthRequest = 25,
HeightRequest = 25,
};
var mainLayout = new StackLayout {
Spacing = 15,
Children = {
ib,
new ImageButton {
Source = "Home.png",
WidthRequest = 25,
HeightRequest = 25,
},
new ImageButton {
Source = "MessageFilled.png",
WidthRequest = 25,
HeightRequest = 25,
},
new ImageButton {
Source = "Settings.png",
WidthRequest = 25,
HeightRequest = 25,
},
}
};
// In this case the IsFullScreen must set false
this.IsFullScreen = false;
this.BackgroundViewColor = Color.Transparent;
// You must set BackgroundColor,
// and you cannot put another layout with background color cover the whole View
// otherwise, it cannot be dragged on Android
this.BackgroundColor = Color.FromHex ("#C82630");
this.MenuOrientations = orientation;
if (orientation == MenuOrientation.BottomToTop) {
mainLayout.Orientation = StackOrientation.Vertical;
mainLayout.Children.Insert (0, new Image {
Source = "DoubleUp.png",
WidthRequest = 25,
HeightRequest = 25,
});
mainLayout.Padding = new Thickness (0, 5);
// In this case, you must set both WidthRequest and HeightRequest.
this.WidthRequest = 50;
this.HeightRequest = 200;
// A little bigger then DoubleUp.png image size, used for user drag it.
this.DraggerButtonHeight = 30;
// In this menu direction you must set LeftMargin.
this.LeftMargin = 100;
}

Do you add want to achieve it like following GIF.
If so,when you used SlideMenu, you should Create a new view that inherit's from MenuContainerPage like following code.Note:MenuContainerPage comes from SlideOverKit
public class QuickInnerMenuPage: MenuContainerPage
{
public QuickInnerMenuPage()
{
Content = new StackLayout
{
VerticalOptions = LayoutOptions.Center,
HorizontalOptions = LayoutOptions.Center,
Children = {
new Label(){Text="1222"}
}
};
this.SlideMenu = new QuickInnerMenuView(MenuOrientation.RightToLeft);
}
}
Here is my demo.you could refer to it.
https://github.com/851265601/SlideOverKitDemo

Related

Is there any way to force execute the OnSizeAllocated method?

I have created a view using Xaml code behind. I did it using the code behind because I wanted to change the layout of the view based on the device orientation. So, the problem which I am facing is that the OnSizeAllocated method is being called after the view is loaded. So, it is unable to change the layout as per the device orientation. I just want to know if there is any way to invoke the OnSizeAllocated method before the view is loaded. Please click on the below link to view the code:
Please click Here to view the Code
1.Rearrange the Page
you could check if width is greater than height to determine if the device is now in landscape or portrait:
public partial class Page13 : ContentPage
{
private double _width ;
private double _height ;
private Grid grid;
private Label label;
private Entry entry;
private Button button;
public Page13 ()
{
_width = this.Width;
_height = this.Height;
label = new Label(){Text = "i am a laber"};
entry = new Entry(){WidthRequest = 200};
button = new Button(){Text = "Submit"};
grid = new Grid();
UpdateLayout();
StackLayout stackLayout = new StackLayout();
stackLayout.Children.Add(grid);
Content = stackLayout;
}
protected override void OnSizeAllocated(double width, double height)
{
base.OnSizeAllocated(width, height);
if (_width != width || _height != height)
{
_width = width;
_height = height;
UpdateLayout();
}
}
void UpdateLayout()
{
grid.RowDefinitions.Clear();
grid.ColumnDefinitions.Clear();
grid.Children.Clear();
if (_width > _height)
{
ScreenRotatedToLandscape();
}
else
{
ScreenRotatedToPortrait();
}
}
private void ScreenRotatedToLandscape()
{
grid.RowDefinitions.Add(new RowDefinition(){Height = new GridLength(1,GridUnitType.Auto)});
grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) });
grid.ColumnDefinitions.Add(new ColumnDefinition(){Width = new GridLength(1,GridUnitType.Auto)});
grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Auto) });
grid.Children.Add(label,0,0);
grid.Children.Add(entry, 1, 0);
grid.Children.Add(button, 0, 1);
Grid.SetColumnSpan(button,2);
}
private void ScreenRotatedToPortrait()
{
grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) });
grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) });
grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) });
grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Auto) });
grid.Children.Add(label, 0, 0);
grid.Children.Add(entry, 0, 1);
grid.Children.Add(button, 0, 2);
}
}
This is the recommended implementation pulled right from the Xamarin.Forms documentation.
2.Using Xamarin.Essentials
It adds additional functionality to cross-platform applications built in Xamarin. One of these new features is the ability to ping the device for the current orientation by accessing the DeviceDisplay.ScreenMetrics.Orientation property. This returns the current device orientation, which can be used to determine which layout to render.
it's similar to the one above
private bool IsPortrait;
public Page13 ()
{
...
IsPortrait = DeviceDisplay.ScreenMetrics.Orientation == ScreenOrientation.Portrait;
UpdateLayout();
...
}
void UpdateLayout()
{
grid.RowDefinitions.Clear();
grid.ColumnDefinitions.Clear();
grid.Children.Clear();
if (IsPortrait)
{
ScreenRotatedToPortrait();
}
else
{
ScreenRotatedToLandscape();
}
}
You can't force run that since the SizeAllocation hasn't changed, but you could do this to get orientation on initial load:
If you add the Xamarin.Essentials nuget package, as you can see here, you can get the orientation using this line of code DeviceDisplay.MainDisplayInfo.Orientation and you will get Landscape, Portrait, Square, or Unknown.
If you don't want to add the package, you can just use Application.Current.MainPage.Width and Application.Current.MainPage.Height to figure out orientation.

Cannot display two scrollview together in stacklayout in Xamarin Forms

I try to add two horizontal scrollviews together in one stacklayout. But displayed only last scrollview(scrollView1). Why first scrollView doesn't display?
var avatarLayout = new StackLayout()
{
HeightRequest = 500,
};
StackLayout st = new StackLayout()
{
Orientation = StackOrientation.Horizontal
};
st.Children.Add(postImage1);
st.Children.Add(postImage2);
st.Children.Add(postImage3);
StackLayout st1 = new StackLayout()
{
Orientation = StackOrientation.Horizontal
};
st1.Children.Add(postImage4);
st1.Children.Add(postImage5);
st1.Children.Add(postImage6);
ScrollView scrollView = new ScrollView()
{
HorizontalOptions = LayoutOptions.Fill,
Orientation = ScrollOrientation.Horizontal,
Content = new StackLayout{
Orientation = StackOrientation.Horizontal,
Children = {st}
}
};
ScrollView scrollView1 = new ScrollView()
{
HorizontalOptions = LayoutOptions.Fill,
Orientation = ScrollOrientation.Horizontal,
Content = new StackLayout
{
Orientation = StackOrientation.Horizontal,
Children = {st1}
}
};
avatarLayout.Children.Add(avatarImage);
avatarLayout.Children.Add(friends);
avatarLayout.Children.Add(scrollView);
avatarLayout.Children.Add(cars);
avatarLayout.Children.Add(scrollView1);
avatarLayout.Children.Add(posts1);
Solved.
The code above isn't adding any children to st1, so scrollView1 don't have anything to display. It looks like the code ought to be displaying scrollView (not scrollView1), but with the content that was intended for both ScrollView containers. I suspect the calls after the creation of st1 should be st1.Children.Add(...) not st.Children.Add(...).

Xamarin Forms Switch XAML

I'm new in Xamarin and i'm trying to create a simple page with some components.
One of these component is a Switch it works fine by itself but i would like to change the basic text "inactive/active" by "male/female"
I've seen that in Xaml for windows phone there is a ToggleSwitch Component with a On/OffContent property but i can't seems to find an equivalent in XAML for Xamarin Forms
any idea ?
Thank you!
The lack of built in switch options, or at least the lack of being able to rename the switch options, has been asked a few times.
You could go with custom renders, modify the text at the OS level or do like I chose to do, just build your own switch.
This switch is two buttons laid out horizontally with the text Yes and No. The selected button gets a red border, and the unselected a transparent border.
class CustomSwitch : Grid
{
public event EventHandler<SelectedItemChangedEventArgs> ItemSelected;
private Button negative;
private Button positive;
public static readonly BindableProperty SelectedItemProperty = BindableProperty.Create<CustomSwitch, Object>(t => t.SelectedItem, null, BindingMode.TwoWay, propertyChanged: OnSelectedItemChanged);
public CustomSwitch()
{
try
{
this.HorizontalOptions = LayoutOptions.Center;
this.VerticalOptions = LayoutOptions.Center;
negative = new Button();
negative.Text = "No";
negative.Style = <YourNameSpace>.AppStyling.Style_Button_Switch;
negative.Clicked += (o,s) => OnSelectedItemChanged(this, ItemSelected, (int)Classes.Collections.Enums.SelectionStatus.False);
positive = new Button();
positive.Text = "Yes";
positive.Style = <YourNameSpace>.AppStyling.Style_Button_Switch;
positive.Clicked += (o, s) => OnSelectedItemChanged(this, ItemSelected, (int)Classes.Collections.Enums.SelectionStatus.True);
this.Children.Add(negative, 0,0);
this.Children.Add(positive, 1,0);
}
catch(System.Exception ex)
{
<YourNameSpace>.Classes.Helpers.Helper_ErrorHandling.SendErrorToServer(ex, this.GetType().Name, System.Reflection.MethodBase.GetCurrentMethod().Name);
}
}
public Object SelectedItem
{
get
{
return base.GetValue(SelectedItemProperty);
}
set
{
if (SelectedItem != value)
{
base.SetValue(SelectedItemProperty, value);
InternalUpdateSelected();
}
}
}
private void InternalUpdateSelected()
{
if((int)SelectedItem == (int)Classes.Collections.Enums.SelectionStatus.False)
{
negative.BorderColor = <YourNameSpace>.AppStyling.Color_Selected;
positive.BorderColor = <YourNameSpace>.AppStyling.Color_UnSelected;
positive.Opacity = <YourNameSpace>.AppStyling.Opaque_High;
}
else if ((int)SelectedItem == (int)Classes.Collections.Enums.SelectionStatus.True)
{
negative.BorderColor = <YourNameSpace>.AppStyling.Color_UnSelected;
negative.Opacity = <YourNameSpace>.AppStyling.Opaque_High;
positive.BorderColor = <YourNameSpace>.AppStyling.Color_Selected;
}
else
{
negative.BorderColor = <YourNameSpace>.AppStyling.Color_UnSelected;
negative.Opacity = <YourNameSpace>.AppStyling.Opaque_High;
positive.BorderColor = <YourNameSpace>.AppStyling.Color_UnSelected;
positive.Opacity = <YourNameSpace>.AppStyling.Opaque_High;
}
}
private static void OnSelectedItemChanged(BindableObject bindable, object oldValue, object newValue)
{
CustomSwitch boundSwitch = (CustomSwitch)bindable;
if((int)newValue != (int)Classes.Collections.Enums.SelectionStatus.Unselected)
{
boundSwitch.SelectedItem = (int)newValue == (int)Classes.Collections.Enums.SelectionStatus.False ? (int)Classes.Collections.Enums.SelectionStatus.False : (int)Classes.Collections.Enums.SelectionStatus.True;
}
if (boundSwitch.ItemSelected != null)
{
boundSwitch.ItemSelected(boundSwitch, new SelectedItemChangedEventArgs(newValue));
}
boundSwitch.InternalUpdateSelected();
}
}

Windows Store Apps: animate control when visibility changes?

In my app I have A grid with visibility bound to a property in the view model.
What I want to do is when the visibility property changes at the view model, the grid fades in or out according to the visibility value: Visible/Collapsed.
how can I achieve this ?
Inspired by the answer of "HDW Production", here's the code for Windows Store and Windows Phone Store apps:
public class FadingVisibilityGrid : Grid
{
public static readonly DependencyProperty DeferredVisibilityProperty = DependencyProperty.Register(
"DeferredVisibility", typeof (Visibility), typeof (FadingVisibilityGrid), new PropertyMetadata(default(Visibility), DeferredVisibilityChanged));
private static void DeferredVisibilityChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
var newVisibility = (Visibility)e.NewValue;
var grid = (FadingVisibilityGrid)sender;
var animation = new DoubleAnimation
{
Duration = new Duration(TimeSpan.FromMilliseconds(200))
};
Storyboard.SetTarget(animation, grid);
Storyboard.SetTargetProperty(animation, "Grid.Opacity");
grid.FadeStoryBoard.Stop();
grid.FadeStoryBoard = new Storyboard();
grid.FadeStoryBoard.Children.Add(animation);
if (newVisibility == Visibility.Visible)
{
animation.From = 0;
animation.To = 1;
grid.Visibility = Visibility.Visible;
grid.FadeStoryBoard.Begin();
}
else
{
animation.From = 1;
animation.To = 0;
grid.FadeStoryBoard.Completed += (o, o1) =>
{
grid.Visibility = newVisibility;
};
grid.FadeStoryBoard.Begin();
}
}
public Visibility DeferredVisibility
{
get { return (Visibility) GetValue(DeferredVisibilityProperty); }
set { SetValue(DeferredVisibilityProperty, value); }
}
private Storyboard _fadeStoryBoard = new Storyboard();
public Storyboard FadeStoryBoard
{
get { return _fadeStoryBoard; }
set { _fadeStoryBoard = value; }
}
}
You need a new DependencyProperty, either by inheriting from Grid and adding one or by creating an attached property. Let's call it DeferredVisibility and let it be of type Visibility.
When DeferredVisibility is changed to Visible, set the Visibility to Visible and animate the opacity from 0 to 1.
When DeferredVisibility is changed to Collapsed, animate the opacity from 1 to 0 and THEN set the Visibility to Collapsed.

How to add css style to custom image node in JavaScript InfoVis ToolKit

I have created custom nodes for my force directed InfoVis graph in which I display a user's image. I want to now add style to the image, such as adding a border and making it a circle. I tried adding css class as follows, but it's not working.
img.className = myClass;
here's my custom node code:
//Custom nodes
$jit.ForceDirected.Plot.NodeTypes.implement({
'customImage':
{
'render': function (node, canvas)
{
var ctx = canvas.getCtx();
var img = new Image();
var pos = node.getPos();
img.onload = function ()
{
ctx.drawImage(img, pos.x - 16, pos.y - 16);
}
var n = _nodes[node.id];
if (n && n.imageUrl)
{
var size = 52;
var url = n.imageUrl.replace("{width}", size).replace("{height}", size);
img.src = url;
img.className = myClass;
}
else
{
img.src = '../Images/UserNoImage.png';
}
},
'contains': function (node, pos)
{
var npos = node.pos.getc(true),
dim = node.getData('dim');
return this.nodeHelper.square.contains(npos, pos, dim);
}
}
});
You can apply CSS styles to the html elements. The custom node which you have defined is simply drawing image on the canvas. The node does not correspond to any html element.
Hence before you call function drawImage you should make sure that the image is customized to your requirement, only then you call drawImage. In this case infovis does not know anything about css, all that it does is call drawImage which simply draws an image on the canvas.
Thus, the question you should tackle is, how do you apply css to the image so that its customized to your requirement. And this question is independent of infovis.