Xamarin Forms TableView Default Padding - xaml

I want to add ViewCell and SwitchCell inside a TableView. I want to know what is the default margin for SwitchCell so I can make the TableView looks beautiful. Can you help me?
<TableView Intent="Form">
<TableRoot>
<TableSection>
<ViewCell>
<StackLayout Padding="?, ?, ?, ?">
<!-- Something-->
</StackLayout>
</ViewCell>
<SwitchCell Text="Something"/>
</TableSection>
</TableRoot>
</TableView>

You can use Grid instead of ViewCell. Try like this
<TableView Intent="Form">
<TableRoot>
<TableSection>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackLayout Grid.Column="0" Padding="?, ?, ?, ?">
<!-- Something-->
</StackLayout>
<SwitchCell Grid.Column="1" Text="Something"/>
</Grid>
</TableSection>
</TableRoot>
</TableView>

In a custom renderer for a view cell on iOS, you get access to the TableView. The TableView has a SeparatorInset value for the inset of the separator, which handily is the same as the margin we require for the view cell.
This seems to work well across all the iPhone emulator images I tried (SE, iPhone XR, iPhone XS) on iOS 12.2.
public override UIKit.UITableViewCell GetCell(Cell item, UIKit.UITableViewCell reusableCell, UIKit.UITableView tv)
{
var inset = tv.SeparatorInset.Left;
var viewCell = (ViewCell) item;
viewCell.View.Margin = new Thickness(inset, 0, inset, 0);
return base.GetCell(item, reusableCell, tv);
}

Related

Invisible Control becomes Visible when closing page Xamarin Forms

I have a frame, the IsVisible is binded to a property in my model view that is set to false. when I change the flyout in my shell, the frame makes an appearance as the shell flyout is closing. Any idea why this is happening ?
// in my model view this is the property
public bool ShowPanel{ get { return _showPanel; } set { _showPanel =
value; OnPropertyChange(); } }
// in my view this is the panel
<Frame IsVisible="{Binding ShowPanel}" BackgroundColor="White" BorderColor="Purple" AbsoluteLayout.LayoutFlags="PositionProportional" WidthRequest="100" HeightRequest="200" AbsoluteLayout.LayoutBounds="0,0,200,250">
<local:ExtendedListView ItemTapped="ExtendedListView_ItemTapped" ItemsSource="{Binding AllItems}" IsVisible="{Binding ShowPanel}" SelectionMode="None" HorizontalScrollBarVisibility="Always" HorizontalOptions="Fill" VerticalOptions="Fill" BackgroundColor="Transparent">
<local:ExtendedListView.ItemTemplate >
<DataTemplate>
<ViewCell>
<Grid Padding="0">
<Grid.RowDefinitions>
<RowDefinition Height="20" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="20*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Image.Source="{Binding ImageUrl}" HorizontalOptions="FillAndExpand" VerticalOptions="CenterAndExpand" WidthRequest="50" HeightRequest="50" x:DataType="local1:ServiceLayers"></Image>
<CheckBox Grid.Column="1" IsChecked="{Binding IsVisible, Mode=TwoWay}" Color="Purple" VerticalOptions="Center" HorizontalOptions="Center" x:DataType="local1:ServiceLayers"></CheckBox>
<Label Padding="-5,0,0,0" HorizontalOptions="StartAndExpand" FontAttributes="Bold" TextColor="Black" Grid.Row="0" Grid.Column="2" HorizontalTextAlignment="Start" Text="{Binding Name}" x:DataType="local1:Service"></Label>
<Label></Label>
</Grid>
</ViewCell>
</DataTemplate>
</local:ExtendedListView.ItemTemplate>
</local:ExtendedListView>
</Frame>
// In the View Class
protected override bool OnBackButtonPressed() {
await Shell.Current.GoToAsync($"//{nameof(MainPage)}");
return true;
}
If the BindingContext is removed/changed as you navigate away from the page, the Frame would appear as the binding is invalidated and updated by the binding engine. You have two options:
Don't manually clear the BindingContext from the page as the navigation lifecycle and GC should clean up those resources on their own.
Use binding fallbacks to define behavior when the binding source can't be resolved (because you've nulled the BindingContext) or the binding source is resolved but the bound property is null.

Hoe to make an ImageButton with a label ontop clickable

So I've run into a problem with Imagebuttons in XAML.
I usually render a background image from photoshop and then use this button everywhere and just add a label ontop that says what it does:
enter image description here
This here for isntance comes from this code (partially):
<!--Grid for button-->
<Grid Grid.Row="1" >
<ImageButton
x:Name="btn_register_mainpage"
Source="btn_emptydummy.png" BackgroundColor="#00000000"/>
<Label
FontFamily="arial"
TextColor="#272727"
Text="Profil erstellen"
HorizontalOptions="Center"
VerticalOptions="Center"/>
</Grid>
Now, this works just fine, unless you want to click on it.
As you can see I gave the button a name, I can now catch that name in code and delegate a click to it:
btn_register_mainpage.Clicked += async delegate
{
await Navigation.PushAsync(new Screen_EditInformation());
};
However, this only works when the user clicks on the button - but NOT on the label since this is on top and has no click assigned to it.
So, what I could do is just assign the same click event to both objects (the label and the image button) but that seems rather unusual.
What is the best way to have a custom image as a button with a label ontop that is clickable?
You can add GestureRecognizers to any control in Xamarin.Forms. In your case you could add one to the Grid layout
YourView.xaml
<Grid Grid.Row="1" >
<Grid.GestureRecognizers>
<TapGestureRecognizer
Tapped="OnTapGestureRecognizerTapped"
NumberOfTapsRequired="1" />
</Grid.GestureRecognizers>
<ImageButton
x:Name="btn_register_mainpage"
InputTransparent="True"
Source="btn_emptydummy.png" BackgroundColor="#00000000"/>
<Label
FontFamily="arial"
TextColor="#272727"
Text="Profil erstellen"
HorizontalOptions="Center"
VerticalOptions="Center"/>
</Grid>
YourView.xaml.cs
private void OnTapGestureRecognizerTapped(object sender, EventArgs e)
{
Navigation.PushAsync(new Screen_EditInformation());
}
You could add a TapGestureRecognizer on the label .
<Grid Grid.Row="1" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<ImageButton
Clicked="Button_Clicked"
Grid.Row="0"
x:Name="btn_register_mainpage"
BackgroundColor="LightBlue"/>
<Label
Grid.Row="0"
FontFamily="arial"
TextColor="#272727"
Text="Profil erstellen"
HorizontalOptions="Center"
VerticalOptions="Center">
<Label.GestureRecognizers>
<TapGestureRecognizer
Tapped="Button_Clicked"
NumberOfTapsRequired="1" />
</Label.GestureRecognizers>
</Label>
</Grid>

AbsoluteLayout with proportional height and with minimum and maximum heights

We need a banner, called bannerView in the code bellow, to shrink or expand according to the device height.
However this banner height:
cannot be smaller than 60 units
cannot be bigger than 146 units
code:
<AbsoluteLayout>
<StackLayout
Padding="0"
AbsoluteLayout.LayoutBounds="0,0,1,1"
AbsoluteLayout.LayoutFlags="SizeProportional"
HorizontalOptions="FillAndExpand">
<AbsoluteLayout
x:Name="bannerView">
<Image
AbsoluteLayout.LayoutBounds="0,0,1.05,1"
AbsoluteLayout.LayoutFlags="SizeProportional"
Aspect="AspectFill"
Source="banner.jpg">
</Image>
<Label
Margin="16,18,16,36"
AbsoluteLayout.LayoutBounds="0,1,-1,-1"
AbsoluteLayout.LayoutFlags="PositionProportional"
Text="{Binding Name}">
</Label>
<Label
Margin="16,18,16,18"
AbsoluteLayout.LayoutBounds="0,1,-1,-1"
AbsoluteLayout.LayoutFlags="PositionProportional"
Text="{Binding EmployeeId}">
</Label>
</AbsoluteLayout>
<StackLayout>
<!-- Dynamic content -->
</StackLayout>
</StackLayout>
</AbsoluteLayout>
Note: We need the outer AbsoluteLayout to add a gradient effect on the screen
Have you considered the possibility to use a FlexLayout containing the banner view element, and this one having the HeightRequest attribute binded to view model?
I used something similar as ControlTemplate to achieve a custom page's header depending on the device navigation bar height:
<FlexLayout Direction="Column" JustifyContent="Center">
<!--HEADER-->
<Grid IsVisible="{TemplateBinding BindingContext.ToolbarVisibled}" HeightRequest="{TemplateBinding BindingContext.ToolbarHeight}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".8*"/>
<ColumnDefinition Width=".2*"/>
</Grid.ColumnDefinitions>
<!--...-->
</Grid>
<!--CONTENT HERE-->
<FlexLayout Direction="Column" JustifyContent="Center">
<ContentPresenter FlexLayout.Grow="1"/>
</FlexLayout>
</FlexLayout>

Style Facebookand Google Login Button in Xamarin.Forms Portable Project

I'm developing an app for iOS and Android in Xamarin Forms and I've implemented the functionality for google and facebook login. I did that in the portable project and now I'm trying to style the buttons to look like the "Login with Facebook" button but the only style templates I found are for Android and iOS. I want to add the buttons to my MainPage.xaml so that the button is added to the view only there, but it is shown in the iOS and Android app.
Right now it looks like this without any style:
<Button x:Name="facebookLoginButton" Text="Facebook Login" Clicked="FacebookLoginButton_Clicked"/>
<Button x:Name="googleLoginButton" Text="Google Login" Clicked="GoogleLoginButton_Clicked"/>
There's a design guideline for the facebook here but I'm looking for a library which makes it possible to add the buttons to the MainPage.xaml without styling the buttons on my own.
In short: I'm looking for the following Android layout code snippet for Xamarin Forms which I can use in the xaml file
<com.facebook.widget.LoginButton
xmlns:fb="http://schemas.android.com/apk/res-auto"
android:id="#+id/loginFacebookButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
fb:login_text="#string/loginFacebookButton"
fb:logout_text=""
style="#style/FacebookLoginButton"/>
You have 3 ways of doing this :
You can do it the xaml way :
<Frame CornerRadius="3" BackgroundColor="#4167b2" HeightRequest="60" Margin="20" Padding="0" HasShadow="false">
<StackLayout Orientation="Horizontal" Padding="5">
<Image HeightRequest="80" Aspect="AspectFill" Source="http://3daystartup.org/wp-content/uploads/2011/07/facebook-logo-png-white-facebook-logo-png-white-facebook-icon-png-32.png" />
<Label Text="Continue with Facebook" VerticalOptions="CenterAndExpand" FontSize="20" FontAttributes="Bold" />
<StackLayout.GestureRecognizers>
<TapGestureRecognizer x:Name="FacebookButton" AutomationId="FacebookButton" Command="{Binding FacebookButtonCommand}" />
</StackLayout.GestureRecognizers>
</StackLayout>
</Frame>
You can do it the image way :
<Image HeightRequest="80" Aspect="AspectFill" Source="https://medyo.github.io/assets/images/facebook_connect_button.png">
<Image.GestureRecognizers>
<TapGestureRecognizer x:Name="FacebookImageButton" AutomationId="FacebookImageButton" Command="{Binding FacebookButtonCommand}" />
</Image.GestureRecognizers>
</Image>
Both methods have TapGestureRecognizer to it so you can click on it
please find the best answer here using facebook SDK and dependency injection.
https://blog.xamarin.com/native-android-facebook-authentication-azure-app-service/
as in the link described.
1) Create Button as view in Shared library
public class FacebookLoginButton : Xamarin.Forms.View
{
}
2) Use it in xaml
</code><?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:CoffeeCups.View;assembly:CoffeeCups"
x:Class="CoffeeCups.View.LoginPage">
<ContentPage.Content>
<StackLayout HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand"
Padding="8">
<Label Text="Login for Coffee!"
VerticalOptions="Center"/>
<controls:FacebookLoginButton/>
</StackLayout>
</ContentPage.Content>
</ContentPage>
3) you need to have render as below in your android project. it similar code in IOS.
using CoffeeCups.View;
using Xamarin.Forms;
using CoffeeCups.Droid;
using Xamarin.Forms.Platform.Android;
using Xamarin.Facebook.Login.Widget;
[assembly: ExportRenderer(typeof(FacebookLoginButton), typeof(FacebookLoginButtonRenderer))]
namespace CoffeeCups.Droid
{
public class FacebookLoginButtonRenderer : ViewRenderer<FacebookLoginButton, LoginButton>
{
LoginButton facebookLoginButton;
protected override void OnElementChanged(ElementChangedEventArgs<FacebookLoginButton> e)
{
base.OnElementChanged(e);
if(Control == null || facebookLoginButton == null)
{
facebookLoginButton = new LoginButton(Forms.Context);
SetNativeControl(facebookLoginButton);
}
}
}
}
Bonus UWP: this is not in the article but I achieved having native button in xamarin forms using winsdkfb library. basically your renderer in uwp looks like as below
[assembly: ExportRenderer(typeof(FacebookLoginButton), typeof(FacebookLoginButtonRendererUWP))]
namespace CoffeeCups.UWP
{
public class FacebookLoginButtonRendererUWP : ViewRenderer<FacebookLoginButton, FBLoginButton>
{
FBLoginButton facebookLoginButton;
protected override void OnElementChanged(ElementChangedEventArgs<FacebookLoginButton> e)
{
base.OnElementChanged(e);
if (Control == null || facebookLoginButton == null)
{
facebookLoginButton = new FBLoginButton();
SetNativeControl(facebookLoginButton);
Control.Click += buttonClick;
}
}
Button layout in Xamarin.Forms
I got facebook s logo from here:
http://3daystartup.org/wp-content/uploads/2011/07/facebook-logo-png-white-facebook-logo-png-white-facebook-icon-png-32.png
Put inside ContentPage.Content tag
<Frame CornerRadius="5"
HorizontalOptions="CenterAndExpand"
VerticalOptions="EndAndExpand"
BackgroundColor="#4167b2"
Margin="10"
Padding="5"
HasShadow="false">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<Image Source="facebook" HeightRequest="32" WidthRequest="32"
Grid.Column="0" Grid.Row="0" />
<Label Text="Entre com o Facebook" Grid.Column="1" Grid.Row="0"
VerticalOptions="CenterAndExpand" FontSize="20"
FontAttributes="Bold" TextColor="White" />
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding LoginCommand}" />
</Grid.GestureRecognizers>
</Grid>
</Frame>

How to fill a button with an image in Xamarin Forms?

I am trying to fill a Button with an Image. The button resides within a Grid. The problem is that the image is not fully filling the button. I have also tried to use the ImageButton control.
Here is how I am building my U.I:
<Grid Grid.Row="1" Grid.Column="1" x:Name="VotingGrid" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="45*" />
<ColumnDefinition Width="10*" />
<ColumnDefinition Width="45*" />
</Grid.ColumnDefinitions>
<Button Grid.Row="0" Grid.Column="0" Image="yay.png" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"/>
<Button Grid.Row="0" Grid.Column="2" Image="meh.png" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"/>
</Grid>
It currently looks like the image attached below, but I'd like to image to fill my button.
Any help will be appreciated!
Try to place an image instead of button.
You can make use of Tap Gesture Gesture Recognizer to take click events.
Try something like this :
<Image Source="tapped.jpg">
<Image.GestureRecognizers>
<TapGestureRecognizer
Tapped="OnTapGestureRecognizerTapped" />
</Image.GestureRecognizers>
</Image>
The code for the event handler
void OnTapGestureRecognizerTapped(object sender, EventArgs args) {
var imageSender = (Image)sender;
// Do something
DisplayAlert ("Alert", "Tap gesture recoganised", "OK");
}
Refer : Adding a Tap Gesture Gesture Recognizer
I have not used it myself but maybe you can use this one from XLab
https://github.com/XLabs/Xamarin-Forms-Labs/wiki/ImageButton