Xamarin.Forms not centering layouts in android - layout

I have 3 labels - I want to center the second label and to fill the other space with equal sizes for the first and third label.
Instead I see there is a consideration of the string when using the LayoutOption.FillANdExpand
here is my code:
class MainPage : ContentPage
{
public MainPage()
{
StackLayout a = new StackLayout();
a.Orientation = StackOrientation.Horizontal;
a.Spacing = 0;
a.Padding = new Thickness(0, 0, 0, 0);
a.HorizontalOptions = LayoutOptions.FillAndExpand;
Label l1 = new Label { Text = "1111", HorizontalOptions = LayoutOptions.FillAndExpand, HorizontalTextAlignment = TextAlignment.Center, BackgroundColor = Color.Red, };
Label l2 = new Label { Text = "2222222222222", HorizontalOptions = LayoutOptions.Center, HorizontalTextAlignment = TextAlignment.Center, BackgroundColor = Color.Gray };
Label l3 = new Label { Text = "333333333333", HorizontalOptions = LayoutOptions.FillAndExpand, HorizontalTextAlignment = TextAlignment.Center, BackgroundColor = Color.Red };
a.Children.Add(l1);
a.Children.Add(l2);
a.Children.Add(l3);
Content = a;
}
}
the result is this:
I want the 111 and the 33333... labels to have the same size and the 2222 label to be in the center of my page...

You could use Grid with 3 columns:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Label Text="1111" TextColor="White" BackgroundColor="Red" />
<Label Grid.Column="1" Text="2222222222222" TextColor="White" BackgroundColor="Gray" />
<Label Grid.Column="2" Text="33333" TextColor="White" BackgroundColor="Red" />
</Grid>

While Grid seems to work ok for that, it a little bit overhead. You can try this layout options:
Label l1 = new Label { Text = "1111", HorizontalOptions = LayoutOptions.StartAndExpand, HorizontalTextAlignment = TextAlignment.Center, BackgroundColor = Color.Red, };
Label l2 = new Label { Text = "2222222222222", HorizontalOptions = LayoutOptions.Center, HorizontalTextAlignment = TextAlignment.Center, BackgroundColor = Color.Gray };
Label l3 = new Label { Text = "333333333333", HorizontalOptions = LayoutOptions.EndAndExpand, HorizontalTextAlignment = TextAlignment.Center, BackgroundColor = Color.Red };

Related

Canvas incorrect measureText()

I am making a Discord bot and trying to display someone's level, I would like it to basically say "LEVEL 1" for example, but the distance between the word level and the actual level would change depending on the level they are on. So I am trying to offset the word a little, but when I use measureText(), it displays incorrectly. Code:
const levelNumber = '1';
const levelText = 'LEVEL';
ctx.font = '48px Shapirit';
ctx.fillStyle = '#FF1700';
ctx.textAlign = 'right';
ctx.fillText(levelNumber, 880, 96.8);
ctx.font = '22px Shapirit';
ctx.fillStyle = '#FF1700';
ctx.textAlign = 'right';
ctx.fillText(levelText, 880 - ctx.measureText(levelNumber).width - 20, 96.8);
Here is the current output:
Yes #Jay is right. You have to measureText with the right font, if not you get the wrong results.
See sample below
function drawLevel(x, y, txt, num, style) {
ctx.font = '48px Shapirit';
ctx.fillStyle = style;
ctx.textAlign = 'right';
ctx.fillText(num, x, y);
w = ctx.measureText(num).width
ctx.font = '22px Shapirit';
ctx.fillStyle = style;
ctx.textAlign = 'right';
ctx.fillText(txt, x - w - 20, y);
}
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
drawLevel(200, 40, 'LEVEL', '999', '#FF1700');
drawLevel(200, 80, 'LEVEL', '11', '#0000FF');
drawLevel(200, 120, 'LEVEL', '1', '#00FF00');
<canvas id="canvas">

Custom Toolbar in UINavigation Controller

I am having trouble understanding what approach to take to customize my own Toolbar in Xamarin.ios. The Navigation controller comes with its own default toolbar but how can i change the height and have my own buttons, background image.
What is the best approach for the above ?
You can create a custom navigationBar as you want .
public class xxxViewController: UIViewController
{
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
NavigationController.NavigationBar.Hidden = true;
double height = IsiphoneX();
UIView backView = new UIView()
{
BackgroundColor = UIColor.White,
Frame = new CGRect(0,20,UIScreen.MainScreen.Bounds.Width, height),
};
UIButton backBtn = new UIButton() {
Frame = new CGRect(20, height-44, 40, 44),
Font = UIFont.SystemFontOfSize(18),
} ;
backBtn.SetTitle("Back", UIControlState.Normal);
backBtn.SetTitleColor(UIColor.Blue, UIControlState.Normal);
backBtn.AddTarget(this,new Selector("GoBack"),UIControlEvent.TouchUpInside);
UILabel titleLabel = new UILabel() {
Frame=new CGRect(UIScreen.MainScreen.Bounds.Width/2-75, 0,150, height),
Font = UIFont.SystemFontOfSize(20),
Text = "xxx",
TextColor = UIColor.Black,
Lines = 0,
};
UILabel line = new UILabel() {
Frame = new CGRect(0, height, UIScreen.MainScreen.Bounds.Width, 0.5),
BackgroundColor = UIColor.Black,
};
backView.AddSubview(backBtn);
backView.AddSubview(titleLabel);
backView.AddSubview(line);
View.AddSubview(backView);
}
double IsiphoneX()
{
double height = 44;
if (UIDevice.CurrentDevice.CheckSystemVersion(11, 0))
{
if (UIApplication.SharedApplication.Delegate.GetWindow().SafeAreaInsets.Bottom > 0.0)
{
height = 64;
}
}
return height;
}
[Export("GoBack")]
void GoBack()
{
NavigationController.PopViewController(true);
}
public override void ViewWillDisappear(bool animated)
{
base.ViewWillDisappear(animated);
NavigationController.NavigationBar.Hidden = false;
}
}
You can set the property of title , backButton and navigationBar as you need (such as text , color ,BackgroundColor ,font e.g.)

JSSOR toggle fullscreen

Hi the only thing I would like to have in JSSOR is to toggle fullscreen gallery. I am using Image gallery version of JSSOR. I would like to have fullscreen button on the right upper corner which toggles fullscreen (not full but maximized) view and I can move with images there.
I did not see any tutorial on official jssor page or any other thread.
I would like to have something like this in the upper right corner. Any help with this ?
<script src="jssor.slider.min.js"></script>
<div id="jssor_1" style="position:relative;top:0px;left:0px;width:980px;height:380px;overflow:hidden;">
<div data-u="slides" style="position:absolute;top:0px;left:0px;width:980px;height:380px;overflow:hidden;">
<div><img data-u="image" src="image1.jpg" /></div>
<div><img data-u="image" src="image2.jpg" /></div>
</div>
<!-- https://www.jssor.com/development/slider-with-fixed-static-element.html -->
<img id="fullscreen_toggle_button" src="toggle-fullscreen.png" style="position:absolute;top:5px;right:5px;" />
</div>
<script>
var options = { $AutoPlay: 1 };
var jssor_1_slider_element = document.getElementById("jssor_1");
var jssor_1_slider_parent_element = jssor_1_slider_element.parentNode;
var jssor_1_slider = new $JssorSlider$(jssor_1_slider_element, options);
var isFullscreenMode = false;
var fullscreenElement;
var fullscreen_toggle_button_element = document.getElementById("fullscreen_toggle_button");
function ToggleFullscreen() {
isFullscreenMode = !isFullscreenMode;
if(isFullscreenMode) {
//create fullscreen div, move jssor slider into the div
fullscreenElement = document.createElement("div");
fullscreenElement.style.position = "fixed";
fullscreenElement.style.top = 0;
fullscreenElement.style.left = 0;
fullscreenElement.style.width = "100%";
fullscreenElement.style.height = "100%";
fullscreenElement.style.zIndex = 1000000;
document.body.appendChild(fullscreenElement);
var fullscreenRect = fullscreenElement.getBoundingClientRect();
var width = fullscreenRect.right - fullscreenRect.left;
var height = fullscreenRect.bottom - fullscreenRect.top;
fullscreenElement.appendChild(jssor_1_slider_element);
jssor_slider.$ScaleSize(width, height);
}
else if(fullscreenElement) {
//move jssor slider into its original container, remove the fullscreen div
jssor_1_slider_parent_element.appendChild(jssor_1_slider_element);
var width = jssor_1_slider_parent_element.clientWidth;
jssor_slider.$ScaleWidth(width);
document.body.removeChild(fullscreenElement);
fullscreenElement = null;
}
}
fullscreen_toggle_button_element.addEventListener("click", ToggleFullscreen);
</script>

How can I restrict gestures are working only draw line area itself in Xamarin.Ios

What I have tried is
CAShapeLayer shapeLayer = new CAShapeLayer();
shapeLayer.Path = new CGPath();
shapeLayer.Path.AddLines(new CGPoint [] { startingPoint, endingPoint});
shapeLayer.StrokeColor = UIColor.Blue.CGColor;
shapeLayer.LineWidth = (System.nfloat)3.0;
shapeLayer.FillColor = UIColor.Clear.CGColor;
var width = Math.Abs(latestPoint.X - initioalPoint.X) + initioalPoint.X;
var height = Math.Abs(latestPoint.Y - initioalPoint.Y) + initioalPoint.Y;
var padding = 10;
shapeLayer.Frame = new CGRect(5, 5, width + padding - 2, height + padding - 2);
var view = new UIView();
view.Layer.AddSubLayer(shapeLayer);
CanvasView canvasDrawLine = new CanvasView(subView);
canvasDrawLine.Frame = new CGRect(5, 5, width + padding, height + padding[![enter image description here][1]][1]);
Public Class CanvasView : UIView
{
public CanvasView(drawline)
{
drawLine.ClipsToBounds = true;
var width = Math.Abs(endingPoint.X - initioalPoint.X) + initioalPoint.X;
var height = Math.Abs(endingPoint.Y - initioalPoint.Y) + initioalPoint.Y;
var padding = 10;
drawLine.Frame = new CGRect(5,5, width + padding, height + padding);
this.AddSubview(drawLine);
setUpGestures();
}
}
scrollView.AddSubview(canvasDrawLine );
when I set the width and height of the frame default, my gestures not working properly, for example If I have apply a pan gesture to the draw line even out of the draw line also pan gesture is working.How can I restrict all gestures are working only draw line area.
you can calculate bounds of your area covered by line :
CoreGraphics.CGPoint initialPoint = new CoreGraphics.CGPoint(1, 2);
CoreGraphics.CGPoint latestPoint = new CoreGraphics.CGPoint(1, 2);
var width = Math.Abs(latestPoint.X - initialPoint.X);
var height = Math.Abs(latestPoint.X - initialPoint.X);
var padding = 10;
subView.Frame = new CGRect(0, 0, width+padding, height+padding);
I have created sample code with simple view controller class -- Have assigned red colour to view containing line. And its working perfect. gesture recogniser is working on red part only --where line is.
public partial class ViewController : UIViewController
{
protected ViewController(IntPtr handle) : base(handle)
{
// Note: this .ctor should not contain any initialization logic.
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
CGPoint initioalPoint = new CGPoint(12, 12);
CGPoint latestPoint = new CGPoint(80, 45);
var shapeLayer = new CAShapeLayer();
shapeLayer.Path = new CGPath();
shapeLayer.Path.AddLines(new CGPoint[] { initioalPoint, latestPoint });
shapeLayer.StrokeColor = UIColor.Blue.CGColor;
shapeLayer.LineWidth = (System.nfloat)3.0;
shapeLayer.FillColor = UIColor.Clear.CGColor;
var subView = new UIView();
var width = Math.Abs(latestPoint.X - initioalPoint.X) + initioalPoint.X;
var height = Math.Abs(latestPoint.Y - initioalPoint.Y) + initioalPoint.Y;
var padding = 10;
subView.Frame = new CGRect(5, 5, width + padding, height + padding);
subView.Layer.AddSublayer(shapeLayer);
shapeLayer.Frame = new CGRect(5, 5, width + padding-2, height + padding-2);
subView.BackgroundColor = UIColor.Red;
var mainView = new UIView();
mainView.Frame = new CGRect(40, 40, width + padding+200, height + padding+200);
mainView.AddSubview(subView);
mainView.BackgroundColor = UIColor.Yellow;
this.View.AddSubview(mainView);
UITapGestureRecognizer tap = new UITapGestureRecognizer();
tap.AddTarget((obj) => {new UIAlertView("tapped","",null,"ok",null).Show();});
subView.AddGestureRecognizer(tap);
//UITapGestureRecognizer tap = new UITapGestureRecognizer(() => Console.WriteLine("tap"));
// Perform any additional setup after loading the view, typically from a nib.
}
public override void DidReceiveMemoryWarning()
{
base.DidReceiveMemoryWarning();
// Release any cached data, images, etc that aren't in use.
}
}
///To check if Touch Point is inside Given Polygon::
CGPoint pt1 = new CGPoint(initioalPoint.X - 50, initioalPoint.Y - 50);
CGPoint pt2 = new CGPoint(initioalPoint.X + 50, initioalPoint.Y - 50);
CGPoint pt3 = new CGPoint(latestPoint.X - 50, latestPoint.Y + 50);
CGPoint pt4 = new CGPoint(latestPoint.X + 50, latestPoint.Y + 50);
UIBezierPath path = new UIBezierPath();
path.MoveTo(pt1);
path.AddLineTo(pt2);
path.AddLineTo(pt3);
path.AddLineTo(pt4);
path.AddLineTo(pt1);
if (!path.ContainsPoint(ToucPoint))
return;

How to know which element is in focus in Universal windows application in windows 10

I have a xaml page in universal windows application in windows 10. This page contains two listboxes. Both listboxes have the same ItemsSource like
public class CategoryModel
{
public int CategoryId {get; set;}
public string CategoryName {get; set;}
public List<string> ImageURL {get; set;}
}
The top listbox creates Menu header at the top in Horizontal manner and the bottom listbox creates Menu data at the bottom of the menu header in Vertical manner.
The problem is that how to know which menu data element at the bottom is in focus, so that I can highlight the same element in Menu header?
<ListView x:Name="lvMenuBar" Grid.Column="1" FlowDirection="LeftToRight" ItemsSource="{Binding MenuCategories}" Width="Auto">
<ListView.ItemTemplate>
<DataTemplate>
<Button Click="MenuBarClick" HorizontalAlignment="Center" VerticalAlignment="Top" Tag="{Binding CategoryId}" Content="{Binding CategoryName}" Style="{StaticResource CustomButtonStyle}" FontFamily="Segoe UI" FontWeight="SemiBold" FontSize="18" Margin="0" Padding="20" BorderBrush="Red" BorderThickness="0" Opacity="0.5" Foreground="Black"/>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
<ListView x:Name="lvMenuBar" Grid.Column="1" FlowDirection="LeftToRight" ItemsSource="{Binding MenuCategories}" Width="Auto">
<ListView.ItemTemplate>
<DataTemplate>
The above is my XAML
If I understand the question correctly, you want to select (or otherwise highlight) an item in the top list whenever that item is selected in the bottom list. You can do this with data binding, e.g.:
<ListView
Grid.Row="0"
ItemsSource="{Binding MenuCategories}"
Margin="8"
SelectedIndex="{Binding SelectedIndex, ElementName=verticalList, Mode=OneWay}"
>
Here the SelectedIndex property of the top list mirrors that of the bottom list.
In context, something like this:
<Page.Resources>
<Style x:Key="CustomButtonStyle" TargetType="Button" />
</Page.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ListView
Grid.Row="0"
ItemsSource="{Binding MenuCategories}"
Margin="8"
SelectedIndex="{Binding SelectedIndex, ElementName=verticalList, Mode=OneWay}"
>
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:CategoryModel">
<Button
HorizontalAlignment="Center"
VerticalAlignment="Top"
Tag="{Binding CategoryId}"
Content="{Binding CategoryName}"
Style="{StaticResource CustomButtonStyle}"
FontFamily="Segoe UI"
FontWeight="SemiBold"
FontSize="18"
Margin="0"
Padding="20"
BorderBrush="Red"
BorderThickness="0"
Opacity="0.5"
Foreground="Black"/>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
<ListView
x:Name="verticalList"
Grid.Row="1"
ItemsSource="{Binding MenuCategories}"
Margin="8"
IsItemClickEnabled="True"
SelectionMode="Single">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:CategoryModel">
<Button
HorizontalAlignment="Center"
VerticalAlignment="Top"
Tag="{Binding CategoryId}"
Content="{Binding CategoryName}"
Style="{StaticResource CustomButtonStyle}"
FontFamily="Segoe UI"
FontWeight="SemiBold"
FontSize="18"
Margin="0"
Padding="20"
BorderBrush="Red"
BorderThickness="0"
Opacity="0.5"
Foreground="Black"/>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
</Grid>
Caveat: When you click one of your buttons, the ListView doesn't see that click; if you want that click to select an item, do it in code-behind.
Note also the IsItemClickEnabled property on the second (vertical) list.
EDIT: If I understand you correctly, you want the selection in the upper horizontal list to track scrolling in the lower vertical instead of selection. In that case you need to get hold of the built-in ScrollViewer and do something like this:
public MainPage()
{
InitializeComponent();
DataContext = this;
Loaded += (sender, args) =>
{
ScrollViewer scrollViewer = FindVisualChild<ScrollViewer>(verticalList);
if (scrollViewer != null)
{
scrollViewer.ViewChanged += (o, eventArgs) =>
{
int length = MenuCategories.Length;
double offset = scrollViewer.VerticalOffset;
double height = scrollViewer.ExtentHeight;
int index = (int)(length * offset / height);
horizontalList.SelectedIndex = index;
};
}
};
}
private static T FindVisualChild<T>(DependencyObject parent)
where T : DependencyObject
{
if (parent != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(parent, i);
T candidate = child as T;
if (candidate != null)
{
return candidate;
}
T childOfChild = FindVisualChild<T>(child);
if (childOfChild != null)
{
return childOfChild;
}
}
}
return default(T);
}
You'll probably need to experiment with the calculations here; this is a bit experimental on my part.
This piece of code has solved much of my issue
private double _scrollExtentHeight;
private ScrollViewer _scrollViewer;
_scrollViewer = FindVisualChild<ScrollViewer>(lvMenuItems);
if (_scrollViewer != null)
{
_scrollViewer.ManipulationMode = ManipulationModes.TranslateY;
_scrollViewer.DirectManipulationCompleted += scrollViewerDirectManipulationCompleted;
_scrollExtentHeight = _scrollViewer.ExtentHeight;
}
private static T FindVisualChild<T>(DependencyObject parent)
where T : DependencyObject
{
if (parent != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(parent, i);
T candidate = child as T;
if (candidate != null)
{
return candidate;
}
T childOfChild = FindVisualChild<T>(child);
if (childOfChild != null)
{
return childOfChild;
}
}
}
return default(T);
}
private void scrollViewerDirectManipulationCompleted(object sender, object e)
{
_menuVM.StartDispatcher();
if (_scrollViewer != null)
{
int length = _menuVM.Categories.Count;
double offset = _scrollViewer.VerticalOffset;
//Horizontal scroll viewer
List<Button> menuItems = GetAllMenuItemControl(lvMenuBar);
int currIndex = 0, index = 0;
//Categories height ratio contains the height ratio of each element for total height
for (; index < _menuVM.CategoriesHeightRatio.Count; index++)
{
if ((_menuVM.CategoriesHeightRatio[index - 1 > 0 ? index - 1 : 0] * _scrollExtentHeight) < offset && (_menuVM.CategoriesHeightRatio[index] * _scrollExtentHeight) >= offset)
{
currIndex = index;
}
else
{
menuItems[index].BorderThickness = new Thickness(0, 0, 0, 0);
menuItems[index].Opacity = 0.5;
}
}
menuItems[currIndex].BorderThickness = new Thickness(0, 0, 0, 2);
menuItems[currIndex].Opacity = 1;
var transform = lvMenuBar.TransformToVisual(menuItems[currIndex]);
Point absolutePoint = transform.TransformPoint(new Point(0, 0));
svMenuBar.ChangeView(Math.Abs(absolutePoint.X), null, null, false);
}
}
private List<Button> GetAllMenuItemControl(DependencyObject parent)
{
var _List = new List<Button>();
for (int index = 0; index < VisualTreeHelper.GetChildrenCount(parent); index++)
{
var _Child = VisualTreeHelper.GetChild(parent, index);
if (_Child is Button)
_List.Add(_Child as Button);
_List.AddRange(GetAllMenuItemControl(_Child));
}
return _List;
}

Resources