First time with cross-platform apps with xamarin, i'm working with xamarin forms in visual studio 2017 community.
I have a button with an image and text but the text needs to be below the image. currently the text is displaying to the left of the image, how can i do this?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xamarin.Forms;
namespace AppUnap
{
public class PPrincipal : ContentPage
{
public PPrincipal()
{
Button btn1= new Button();
btn1.Image = "notas.png";
btn1.Text = "Calificaciones";
btn1.HorizontalOptions = LayoutOptions.CenterAndExpand;
Button btn2 = new Button();
btn2.Image = "notas.png";
btn2.Text = "Aula Virtual";
btn2.HorizontalOptions = LayoutOptions.CenterAndExpand;
Content = new StackLayout
{
Spacing = 0,
VerticalOptions = LayoutOptions.CenterAndExpand,
Children =
{
new StackLayout
{
Spacing = 0,
Orientation = StackOrientation.Horizontal,
Children =
{
btn1,
btn2,
}
}
}
};
}
}
}
You need to use ContentLayout on your button.
Here is the code I use in XAML:
<Button Command="{Binding MyCommand}" ContentLayout="Top,0" Text="mytext" Image="myimage.png" />
Top = Position of the Image
0 = spacing between image & text
You should find easily how to use the ContentLayout in C#
To get the above result I used a ImageButtom, because is possible adjust the image size. I made like this:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label
Text="{Binding CountryId}"
TextColor="{DynamicResource PrimaryDarkColor}"
FontFamily="MontSerratBold"
Margin="0, 0, 0, 10"
VerticalOptions="End"
HorizontalTextAlignment="Center"
VerticalTextAlignment="End"/>
<ImageButton
Source="{Binding CountryUrl}"
HorizontalOptions="Center"
VerticalOptions="Start"
BackgroundColor="Transparent"
Padding="0, 10, 0, 30"
HeightRequest="90"
Command="{Binding OpenPickerPopUp}"/>
Related
I created a simple program with MAUI to load 2 images, specified as Embedded Resources.
This is the MainPage:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Surprise.MainPage">
<ScrollView>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="550"/>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<VerticalStackLayout x:Name="ImageContainer"
Grid.Row="0"
HeightRequest="500"
VerticalOptions="Center"
HorizontalOptions="Center" />
<Grid Grid.Row="1"
HorizontalOptions="Center"
HeightRequest="40">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="30" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button Text="Image1"
Grid.Column="0"
Clicked="OnImage1ButtonClicked" />
<Button Text="Image2"
Grid.Column="2"
Clicked="OnImage2ButtonClicked" />
</Grid>
</Grid>
</ScrollView>
</ContentPage>
and this is its code behind:
public partial class MainPage : ContentPage
{
private readonly Image _image1;
private readonly Image _image2;
public MainPage()
{
InitializeComponent();
_image1 = new Image()
{
Source = ImageSource.FromResource("Surprise.Resources.Images.image1.jpeg"),
VerticalOptions = LayoutOptions.Center,
HeightRequest = 500
};
_image2 = new Image()
{
Source = ImageSource.FromResource("Surprise.Resources.Images.image2.jpg"),
VerticalOptions = LayoutOptions.Center,
HeightRequest = 500
};
}
private void OnImage1ButtonClicked(object sender, EventArgs e)
{
ImageContainer.Children.Clear();
ImageContainer.Children.Add(_image1);
}
private void OnImage2ButtonClicked(object sender, EventArgs e)
{
ImageContainer.Children.Clear();
ImageContainer.Children.Add(_image2);
}
}
On Windows it works correctly.
On Android sometimes the images are loaded in wrong order or even the same image is loaded when I press each button.
Is it a MAUI bug or I'm missing something?
Thanks in advance.
Well, there are some changes that were made with Maui projects, we now have Maui-specific build actions that you can use to specify to your project/solution what the type of a certain file is.
In your Scenario, you should use the MauiImage build action then just uses the name of the file as shown here: https://learn.microsoft.com/en-us/dotnet/maui/user-interface/controls/image#load-a-local-image should be enough to fix your issue
I have a webview in one of my page and I want to add a stacklayout from the top then the webview. But Webview take whole screen and the stacklayout never get shown. I want to hide default navigation bar and create my own one. I still couldn't test for the apple side
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns:other="clr-namespace:CustApp.CusApp.Dushan.Other"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
EnableBackButtonOverride="True"
x:Class="CustApp.Views.GeneralPayments.MotorPayments.hnb.HNBmotorPayment">
<ContentPage.Content>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackLayout Grid.Row="0" VerticalOptions="Start" HorizontalOptions="FillAndExpand" Orientation="Horizontal" Padding="10,5,10,5">
<Image HorizontalOptions="StartAndExpand" Source="pdfDown.png"/>
<Label HorizontalOptions="CenterAndExpand" Text="ALL"/>
<Image HorizontalOptions="EndAndExpand" Source="pdfDown.png"/>
</StackLayout>
<WebView Grid.Row="1" x:Name="webView"
HorizontalOptions="CenterAndExpand"
Navigating="webView_Navigating"
Navigated="MywebView_Navigated"/>
</Grid>
</ContentPage.Content>
</ContentPage>
Code behind
protected override void OnAppearing()
{
base.OnAppearing();
NavigationPage.SetHasNavigationBar(this, false);
if (isFirstRun)
{
jsonOutput = JsonConvert.SerializeObject(payData);
//var htmlSource = new HtmlWebViewSource();
var urlSource = new UrlWebViewSource();
string url = DependencyService.Get<IBaseUrl>().Get();
TempUrl = Path.Combine(url, "xamarinhtmlmotor.html");
urlSource.Url = TempUrl;
webView.Source = urlSource;
isFirstRun = false;
Content = webView;
}
}
The cause is you set the Content = webView in code behind which means the the whole content is webview and those code in the Xaml will be overwritten.
Solution:
Remove Content = webView; and try again.
I'm making an app with Xamarin Form that should work both on iOS and Android, I have a carousel view with an image inside, so I have tried making a carousel with a cell using this nugget: URL
while working fine on iOS on android the cell keeps crashing so I've changed with a cell containing only one image with a binding on the URL
now everything working but the are sono images sporadically missing inside the carousel.
Am I missing something? is there a nugget package for xamarin form for caching displaying correctly all the images?
thanks
making FFImage.Loading working on Android with no success
android cell
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:ffimage="clr-namespace:FFImageLoading.Forms;assembly=FFImageLoading.Forms"
xmlns:local="clr-namespace:CTSApp.Utility"
x:Class="CTSApp.Celle.cella_volantino_android">
<ContentView.Content>
<ScrollView>
<StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="CenterAndExpand">
<local:PinchToZoomContainer>
<local:PinchToZoomContainer.Content>
<Image Source="{Binding url}" HorizontalOptions = "FillAndExpand"
VerticalOptions = "FillAndExpand" />
</local:PinchToZoomContainer.Content>
</local:PinchToZoomContainer>
</StackLayout>
</ScrollView>
</ContentView.Content>
</ContentView>
iOS cell
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:ffimage="clr-namespace:FFImageLoading.Forms;assembly=FFImageLoading.Forms"
xmlns:fftransf="clr-namespace:FFImageLoading.Transformations;assembly=FFImageLoading.Transformations"
xmlns:local="clr-namespace:CTSApp.Utility" x:Class="CTSApp.Celle.cella_volantino">
<ContentView.Content>
<ScrollView>
<StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="CenterAndExpand">
<local:PinchToZoomContainer>
<local:PinchToZoomContainer.Content>
<ffimage:CachedImage Grid.RowSpan="2" Aspect="AspectFill"
Source="{Binding url}"
DownsampleToViewSize="false"
LoadingPlaceholder="placeholder.png"
ErrorPlaceholder="placeholder.png"
VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand">
<ffimage:CachedImage.CacheDuration>
<x:TimeSpan>0,0,15,0</x:TimeSpan>
</ffimage:CachedImage.CacheDuration>
</ffimage:CachedImage>
</local:PinchToZoomContainer.Content>
</local:PinchToZoomContainer>
</StackLayout>
</ScrollView>
</ContentView.Content>
</ContentView>
thanks for help.
EDIT
Here is my main activity:
using Android.Content.PM;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Plugin.FirebasePushNotification;
using Firebase;
using Plugin.CurrentActivity;
using Plugin.Permissions;
using Xamarin;
using Xamarin.Forms;
using Android.Content.Res;
using SegmentedControl.FormsPlugin.Android;
using ZXing.Mobile;
namespace CTSApp.Droid
{
[Activity(Label = "CTSApp", Icon = "#drawable/ic_launcher", Theme = "#style/MyTheme.Splash", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
protected override void OnCreate(Bundle bundle)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
MobileBarcodeScanner.Initialize(Application);
Rg.Plugins.Popup.Popup.Init(this, bundle);
ZXing.Net.Mobile.Forms.Android.Platform.Init();
FFImageLoading.Forms.Droid.CachedImageRenderer.Init(enableFastRenderer: true);
Plugin.CurrentActivity.CrossCurrentActivity.Current.Activity = this;
CrossCurrentActivity.Current.Init(this, bundle);
SegmentedControlRenderer.Init();
FirebasePushNotificationManager.ProcessIntent(Intent);
LoadApplication(new App());
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
{
Plugin.Permissions.PermissionsImplementation.Current.OnRequestPermissionsResult(requestCode, permissions, grantResults);
PermissionsImplementation.Current.OnRequestPermissionsResult(requestCode, permissions, grantResults);
global::ZXing.Net.Mobile.Forms.Android.PermissionsHandler.OnRequestPermissionsResult (requestCode, permissions, grantResults);
}
}
}
FFImageLoader version 2.4.3.840
Xamarin form version 2.50
EDIT 2
Maybe I've found the problem, here is the new definitive cell I'm using
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:ffimage="clr-namespace:FFImageLoading.Forms;assembly=FFImageLoading.Forms"
xmlns:local="clr-namespace:CTSApp.Utility"
x:Class="CTSApp.Celle.cella_volantino_android">
<ContentView.Content>
<ScrollView>
<StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="CenterAndExpand">
<local:PinchToZoomContainer>
<local:PinchToZoomContainer.Content>
<Image Source="{Binding url}" HorizontalOptions = "FillAndExpand"
VerticalOptions = "FillAndExpand" >
<Image.Source>
<UriImageSource Uri="{Binding url}"
CacheValidity="14"
CachingEnabled="true"/>
</Image.Source>
</Image>
</local:PinchToZoomContainer.Content>
</local:PinchToZoomContainer>
</StackLayout>
</ScrollView>
</ContentView.Content>
</ContentView>
Now I'm using the standard image with caching , now on iOS everything works fine , on android I'm getting error from some pages
ImageLoaderSourceHandler: Could not retrieve image or image data was invalid: Uri:
that obviously does not load, I've followed the tutorial here
https://doumer.me/resolve-image-loading-error-in-xamarin-forms/
Still no luck, but if I turn the phone horizontally the image load correctly, I really have no clue
video here:
https://streamable.com/rk1rv
Here is a sample with CarouselView to show image.All can work in IOS and Android.If want to use ffimage:CachedImage ,replacing Image with it.
Here is Xaml code:
<StackLayout>
<CarouselView x:Name="carousel" ItemsSource="{Binding uris}">
<CarouselView.ItemTemplate>
<DataTemplate>
<Image
x:Name="PlantPicture"
Source="{Binding uri}"
HorizontalOptions="Center"
VerticalOptions="Center"
WidthRequest="150"
HeightRequest="150">
</Image>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
</StackLayout>
Model code :
public class FloraData
{
public class StringData
{
public string uri { get; set; }
}
public List<StringData> uris { get; set; }
public FloraData()
{
uris = new List<StringData>() { new StringData() { uri = "https://static.inaturalist.org/photos/504134/medium.jpg?1379628103" },
new StringData() { uri = "https://static.inaturalist.org/photos/8784478/small.jpg?1499006293" },
new StringData() { uri = "https://api.idigbio.org/v2/media/23cbb9eb2750e80848ac95b5d2919323?size=thumbnail" },
new StringData() { uri = "https://api.idigbio.org/v2/media/c085496285be91ace0768eb517cc704b?size=thumbnail" },
new StringData() { uri = "http://swbiodiversity.org/imglib/arizona/IND/IND-0049/IND-0049216_1491615930_tn.jpg" }};
}
}
Finally , ContentPage.cs BindingContext :
FloraData floraData = new FloraData();
carousel.BindingContext = floraData;
why isn't the WebView showing ? I have tried FillAndExpand and CenterAndExpand , but it still not working!
<?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:views="clr-namespace:MyApp.Views;assembly=MyApp"
x:Class="MyApp.Pages.Main">
<StackLayout>
<StackLayout Orientation="Horizontal" VerticalOptions="Start">
<!-- top controls -->
</StackLayout>
<StackLayout x:Name="WebViewLayout" VerticalOptions="CenterAndExpand">
<WebView Source="https://www.google.com/" VerticalOptions="CenterAndExpand" HorizontalOptions="FillAndExpand"/>
</StackLayout>
<StackLayout Orientation="Horizontal" VerticalOptions="End">
<views:AdMobView WidthRequest="400" HeightRequest="50" />
</StackLayout>
</StackLayout>
</ContentPage>
Change the Vertical Options of the StackLayout (which holds the WebView) from CenterAndExpand to FillAndExpand and the WebView itself.
I hope this helps. :)
<StackLayout x:Name="WebViewLayout" VerticalOptions="FillAndExpand">
<WebView Source="https://www.google.com/" VerticalOptions = "FillAndExpand"/>
</StackLayout>
I would suggest taking the WebView out of the parent StackLayout and the change the outer most StackLayout to a Grid.
That being said, I think that might help solve the issue without doing that:
public override void OnAppearing() {
SizeChanged += (sender, e) => {
WebViewItem.WidthRequest = Width;
WebViewItem.HeightRequest = 200; //Or what ever
}
OnSizeChanged(null, null); //Make it run at least once
}
I can't say exactly why but setting the VerticalOptions on the stack layout seemed to solve it for me. The following results in the web view being drawn:
var webView = new WebView();
webView.Source = "https://www.xamarin.com";
webView.MinimumWidthRequest = 200;
webView.MinimumHeightRequest = 200;
webView.HorizontalOptions = LayoutOptions.FillAndExpand;
webView.VerticalOptions = LayoutOptions.FillAndExpand;
var stackLayout = new StackLayout;
this.Content = stackLayout;
stackLayout.Children.Add(webView);
stackLayout.HorizontalOptions = LayoutOptions.FillAndExpand;
stackLayout.VerticalOptions = LayoutOptions.FillAndExpand;
I admit the layout behavior for StackLayout is pretty confusing.
In a litte Test Application I have the following ContentPage:
public class LoginPage:ContentPage
{
public LoginPage()
{
Label l = Device.OnPlatform<Label>(
new Label
{
HeightRequest = 150,
XAlign = TextAlignment.Center,
YAlign = TextAlignment.Center,
},
new Label
{
HeightRequest = 120,
XAlign = TextAlignment.Center,
YAlign = TextAlignment.Center,
},
new Label
{
HeightRequest = 500,
XAlign = TextAlignment.Center,
YAlign = TextAlignment.End,
});
l.Text = "App Login";
l.FontSize = 30;
StackLayout sl = new StackLayout()
{
BackgroundColor = Color.FromHex("559db7ec"),
HorizontalOptions = LayoutOptions.Fill,
VerticalOptions = LayoutOptions.Fill,
Children =
{
new StackLayout
{
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center,
Children =
{
l,
//new Label{ Text = "MaintMobile", FontSize = 30, HeightRequest = 120, XAlign = TextAlignment.Center, YAlign = TextAlignment.Center },
new Label{ Text = "Please login", FontSize = 15, HeightRequest = 90, XAlign = TextAlignment.Center, YAlign = TextAlignment.Center },
new Entry{ Placeholder = "Username", WidthRequest = 300 },
new Entry{ Placeholder = "Password", IsPassword = true },
new Button{ Text = "Login" }
}
}
}
};
Content = sl;
}
}
This is the MainPage of the App. While this is doing fine on Android, the YAlign seems to be not working on WinPhone. All the time the Text of the Label is stuck to the top of the Device regardless of what i set it to align to.
Could this be a Bug, or am I doing something wrong?
This was tested on a Lumia 630 and 930
If it works on one platform and not the other I would say its a bug.
You are probably finding that the Label height isn't being considered in that layout setup on Windows and hence always looks like it is at the top but what is really happening is the label height isn't what you expect.
What I would recommend is setting the VerticalOptions to Start or Centered, rather than Text Alignment. The Label will expand as needed.
As another way to look at layouts, I normally recommend this approach for laying out something centered, like the login page. The Grid is the fastest to compute in terms of UI for Xamarin Forms.
<?xml version="1.0" encoding="utf-8" ?>
<local:BasePage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Mobile.View"
x:Class="Mobile.View.LoginPage">
<Grid>
<Image Style="{StaticResource BackgroundImageStyle}" />
<ContentView Style="{StaticResource OverlayStyle}" />
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="350" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Image Source="Logo.png" Grid.Row="0" VerticalOptions="End" HorizontalOptions="Center" />
<StackLayout Grid.Row="1" VerticalOptions="CenterAndExpand">
<Entry StyleId="EmailEntry" Text="{Binding Model.Email}" Placeholder="Email (is demo)" />
<Entry StyleId="PasswordEntry" Text="{Binding Model.Password}" IsPassword="True" Placeholder="Password (is demo)" />
<Button Command="{Binding LoginCommand}" StyleId="LoginButton" Text="Login" IsEnabled="{Binding IsBusy, Converter={StaticResource NotConverter}}" />
</StackLayout>
</Grid>
</Grid>
</local:BasePage>
Sorry its in XAML, I work with XAML for views, but you can see I use a Grid, with 3 rows and the top and bottom ones are *, while the middle has a defined height.
I normally recommend that type of layout for anything you want centered as StackLayouts or RelativeLayouts can be tricky. The calculations that go into rendering them also lead to bugs and poor UI performance.