Xamarin Forms - Share Screen, can you share a "hyperlink"? - xamarin.forms

I'm learning Xamarin Forms. And specifically, if I want to share a complex link, but have the text be something simple how do you do that? What I have now is below.
await Share.RequestAsync(new ShareTextRequest
{
Uri = "thelink",
Title = "title", //ios doesn't use title
Text = "extra text"
});
That obviously just puts in the link and some text. But I want something more akin to an html hyperlink.

Well if you are asking how to put a hiperlink in Xamarin forms, you can do it like this, just create a class in the Portable project and then call it from your XAML page, but remember to read the Xamarin Essentials documentation cause you need to put this in you info.plist:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>lyft</string>
<string>fb</string>
</array>

If you mean the Label with Hyperlinks , you can have a look at this doc here .
The text displayed by Label and Span instances can be turned into hyperlinks, sample code as follow :
<Label>
<Label.FormattedText>
<FormattedString>
<Span Text="Alternatively, click " />
<Span Text="here"
TextColor="Blue"
TextDecorations="Underline">
<Span.GestureRecognizers>
<TapGestureRecognizer Command="{Binding TapCommand}"
CommandParameter="https://learn.microsoft.com/xamarin/" />
</Span.GestureRecognizers>
</Span>
<Span Text=" to view Xamarin documentation." />
</FormattedString>
</Label.FormattedText>
</Label>
When the hyperlink is tapped, the TapGestureRecognizer will respond by executing the ICommand defined by its Command property. In addition, the URL specified by the CommandParameter property will be passed to the ICommand as a parameter.
The code-behind for the XAML page contains the TapCommand implementation:
public partial class MainPage : ContentPage
{
// Launcher.OpenAsync is provided by Xamarin.Essentials.
public ICommand TapCommand => new Command<string>(async (url) => await Launcher.OpenAsync(url));
public MainPage()
{
InitializeComponent();
BindingContext = this;
}
}
The effect :
In addition , you also can create a reusable hyperlink class to make the xaml code more sample .

Related

Dynamically add Icons to titlebar Maui

Im creating an App where I want have multiple icons in my titlebar (they should be clickable). One Icon should be on the Left of the title text like so (this icon is static and will not change):
The other Icons should be on the right (these icons should be dynamic, as they will be used to alert the user if anything important happens):
I'm using a simple shell, so no Navigationpage, thus I don't think <NavigationPage.Titleview> can be used in this case. Is there any way to achieve something like this in Maui?
You can use the shell title view as stated in this answer, it is pointing to Xamarin documentation but it is also valid for MAUI.
In your case you will have something like this inside your AppShell.xaml :
<Shell.TitleView>
<Grid ColumnDefinitions="auto,*,auto">
<Label Text="Title" BackgroundColor="Red"></Label>
<HorizontalStackLayout Grid.Column="2">
<Label Text="Icon" BackgroundColor="Red"></Label>
</HorizontalStackLayout>
</Grid>
</Shell.TitleView>
Which look like this (very trendy design) :
How to update the icons can be done by data binding or creating directly the object from C# :
<HorizontalStackLayout Grid.Column="2" x:Name="IconsContainer">
<Label Text="Icon" BackgroundColor="Red" IsVisible="{Binding Icon1Visible}"></Label>
</HorizontalStackLayout>
And in the C# :
public partial class AppShell : Shell
{
public bool Icon1Visible { get; set; } = false;
public AppShell()
{
InitializeComponent();
// An object containing the binding data
BindingContext = this;
// Directly create a new icon
AddIcon();
// Show an icon through binding
ShowIcon();
}
public void ShowIcon()
{
Icon1Visible = true;
}
public void AddIcon()
{
var icon = new Label();
icon.Text = "And another one";
IconsContainer.Children.Add(icon);
}
}
To get whenever you want to update the icons I would go with dependency injection and either pass directly a view model to bind the icons on or using events.

Unable to select text in Xamarin.Forms Editor control or custom Borderless Editor using renderer

I've implemented Borderless Editor in my Xamarin.Forms application using Custom EditorRenderer. But I'm facing an issue that the editor text is not selectable at all in both cases, neither in Forms editor control nor in Rendered native editor control. My app has the functionality to let user copy paste the text in the editor while typing, like in any other text editing app. This is a basic feature in most of the apps and is by default there. But it's not working in my app. I've tried enabling it through
Control.SetTextIsSelectable(true);
but still it's not working. I've tried other things too, like:
Control.CustomSelectionActionModeCallback = new
CustomSelectionActionModeCallback();
Control.CustomInsertionActionModeCallback = new CustomInsertionActionModeCallback();
But nothing is working at all and text is not getting selected even a single word. Does anyone has any idea about this issue? How can I make the text selectable and allow default copy paste feature in custom editor?
Here's my code in Xaml:
<renderer:BorderlessEditor
Grid.Row="1"
x:Name="UserTextEditorAndroid"
BackgroundColor="{StaticResource WhiteColor}"
HeightRequest="350"
Margin="20,2"
MaxLength="1024"
IsReadOnly="{Binding Source={x:Reference LongTextTemplate}, Path=Editable, Converter={StaticResource InverseBool}}" />
And the custom render code is:
public class BorderlessEditorRenderer : EditorRenderer
{
public BorderlessEditorRenderer()
{
}
public static void Init() { }
protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
{
base.OnElementChanged(e);
if (e.OldElement == null)
{
Control.Background = null;
var layoutParams = new MarginLayoutParams(Control.LayoutParameters);
layoutParams.SetMargins(0, 0, 0, 0);
LayoutParameters = layoutParams;
Control.LayoutParameters = layoutParams;
Control.SetPadding(0, 0, 0, 0);
SetPadding(0, 0, 0, 0);
Control.SetTextIsSelectable(true);
Control.VerticalScrollBarEnabled = false;
}
}
}
Even if I use Xamarin.Forms own editor in Xaml instead of custom renderer then also it doesn't work at all. The text is still un-selectable.
I am having the same problem - but I'm not using Telerik. I'm running VS 2019 on Win 10. This is easy to repro ...
Create a new "Mobile App (Xamarin Forms)" and simply add an Editor to the MainPage.xaml file. I also put the Editor inside a ScrollView for kicks. The code below only shows a few words of text placed in the Editor, but I actually used a long paragraph from the Microsoft docs. I left that out below so as to simplify code presentation ... and avoid a mess!
<?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:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="Editor_Test.MainPage">
<StackLayout>
<!-- Place new controls here -->
<ScrollView>
<Editor Text="Visual Studio makes it easier ..."
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand" />
</ScrollView>
</StackLayout>
</ContentPage>
I get normal behavior:
Because of the ScrollView, I can scroll the text with a finger (mouse) drag
A long press (click) selects the word pressed
A double tap (click) selects the word tapped
I get different results if I change 1 line of code in the App ctor, in App.xaml.cs, to instantiate the MainPage with a NavigationPage, like so:
public App()
{
InitializeComponent();
//MainPage = new MainPage();
MainPage = new NavigationPage(new MainPage());
}
Now the behavior changes:
A long press (click) has no effect (no selection)
A double tap (click) has no effect (no selection)
In fact there is no way at all that I can see to select text in the Editor. I don't know why this happens ... but it does. It drove me a bit mad until I realized what was causing it.
I'm using:
Xamarin Forms 4.5.0.495
Xamarin Essentials 1.3.1
Building for Android 9 (Pie)
I'm new to Android/Xamarin ... so my question is, how best to implement my own simple page navigation - ie, without using Xamarin's NavigationPage? I have a simple 3 page app I'd like to make some progress with!

Xamarin Forms data binding from xaml

I have an <Entry> in xaml, and I want to get that value the user types.
<Entry x:name="enteredInput>
The file with that <Entry> is in startingPage.xaml with a code behind class startingPage.xaml.cs.
Then I would like to transfer that value in the <Label> element of a different xaml, MainPage.xaml.
In your second page, add another constructor with string parameter.
For ex, If your page name is StartingPage.xaml, then add another constructor like below. Inside, assign the incoming value to your label.
public StartingPage(string entryTextFromStartingPage)
{
InitializeComponent();
lblEntryTextDisplay.Text = entryTextFromStartingPage;
}
From the StartingPage.xaml.cs, add the below code in a button click or any event that you are calling the Main page,
Navigation.PushAsync(new MainPage(enteredInput.Text);

Xamarin automatic sign-in credentials for Google Play's pre-launch report

I am building an Android application with Xamarin Forms 3 in Visual Studio 2017 and publishing to Google Play. Google Play offers automated testing (pre-launch report) but it cannot get past my sign-in screen.
Google Play has a place to enter the "username resource name", "password resource name", and "sign-in button resource name". I provided the Xamarin x:name for each control (txtEmail, txtPass, and btnSignIn), but apparently that is not correct, because the automated tester still can't get in and isn't even trying.
Here is my SignIn.xaml:
<Entry x:Name="txtEmail" Placeholder="email address" Keyboard="Email" />
<Entry x:Name="txtPass" IsPassword="True" />
<Button x:Name="btnSignIn" Text="Sign In" Clicked="OnSignInClicked" />
I've found these SO questions (here, here, and here) but they do not address my question from within a Xamarin Forms context. The first link seems particularly helpful but I do not know where to put that XML code.
It seems to me that Xamarin/C# is "compiled" into Android code and generates these XML files. How can I work with this process?
I understand an .APK file is just a ZIP file. Renaming the APK file I send to Google Play to .zip I'm able to browse the contents, but I do not see any XML code that makes sense.
For the moment, I added an extra "demo" button that, on click, puts a username and password into the fields and clicks the Sign In button. Google's automated tester likes this and can get in, but it's a terrible idea for human testing and I'd like to remove this workaround.
I've faced the same issue recently. I submitted an alpha build, enabled pre-launch report and got a policy violation error saying, that sign-in credentials are not provided. As it's stated in the question, I should have provided resource names along with the test credentials, but it wasn't obvious how to do it in Xamarin.Forms project. Nevertheless, I was able to workaround it using renderers. I know, it's a bit extreme to create a separate renderer and a control just to set id, but I really didn't want to change UI significantly, so, I created 3 empty controls:
public class UsernameEntry : Entry { }
public class PasswordEntry : Entry { }
public class LoginButton : Button { }
And used each of them in corresponding places on the login screen, instead of plain entries and the button.
Then I added ids.xml file into the Android project (Resource/values/ids.xml) and added 3 ids, one for every control:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="username_entry" type="id"/>
<item name="password_entry" type="id"/>
<item name="login_button" type="id"/>
</resources>
Finally, I created 3 renderers in the native Android project, one for each control. For example, this is how the UsernameEntryRenderer looks:
[assembly: ExportRenderer(typeof(UsernameEntry), typeof(UsernameEntryRenderer))]
namespace Android.Renderers
{
public class UsernameEntryRenderer : EntryRenderer
{
public UsernameEntryRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (Control != null)
{
// here I can reference the id created previously in ids.xml file
// and set the native android id property
Control.Id = Resource.Id.username_entry;
}
}
}
}
This is not the perfect way, but it worked well in my case. I didn't need to change the UI drastically or to introduce some hidden UI elements. Hopefully, this will be helpful for anyone facing similar problem.
Inspired by Yehor's answer, I was able to come up with a solution that uses Xamarin Effects without using custom controls.
First add ids.xml file into the Android project (Resource/values/ids.xml) and add 3 ids, one for every control. Make sure the Build action is set to AndroidResource and the Custom Tool is set to MSBuild:UpdateGeneratedFiles so the C# files can be generated automatically for the styles:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="username_entry" type="id"/>
<item name="password_entry" type="id"/>
<item name="login_button" type="id"/>
</resources>
Then define an enum so the effects can be defined easily:
public enum CustomIdType
{
None,
Username,
Password,
LoginButton
}
For the Android custom renderer, implement the following assign the android ID based on the custom effects.
[assembly: ResolutionGroupName("CustomRendererHandler")]
[assembly: ExportEffect(typeof(AndroidCustomIdEffect), "CustomIdEffect")]
namespace YOUR_ANDROID_NAMESPACE
{
public class AndroidCustomIdEffect : PlatformEffect
{
protected override void OnAttached()
{
// get autofill effect
var effect = (CustomIdEffect)Element.Effects
.FirstOrDefault(e => e is CustomIdEffect);
// assign android ID if custom ID effect is not null
if (effect != null) {
switch (effect.Type) {
case CustomIdType.Username:
Control.Id = Resource.Id.username_entry;
break;
case CustomIdType.Password:
Control.Id = Resource.Id.password_entry;
break;
case CustomIdType.LoginButton:
Control.Id = Resource.Id.login_button;
break;
}
}
}
protected override void OnDetached()
{
}
}
}
Then define a Routing Effect in your shared code to consume the Android custom renderer:
public class CustomIdEffect : RoutingEffect
{
public CustomIdType Type { get; set; }
public CustomIdEffect() : base("CustomRendererHandler." + nameof(CustomIdEffect))
{
}
}
Finally, to consume the Effects in your login page, simply add the Effects to the controls in XAML:
<Entry PlaceHolder="Enter Username">
<Entry.Effects>
<local:CustomIdEffect Type="Username"/>
</Entry.Effects>
</Entry>
<Entry PlaceHolder="Enter Password">
<Entry.Effects>
<local:CustomIdEffect Type="Password"/>
</Entry.Effects>
</Entry>
<Button Text="Login">
<Button.Effects>
<local:CustomIdEffect Type="LoginButton"/>
</Button.Effects>
</Button>
After that Google Pre-launch Report should be able to get pass the login screen if you provide the right sign-in credentials.

XF binding data from a popuppage to a contentpage through xaml

I have a popup page in my application which includes some checkboxes, and I also have a ContentPage in my MainPage which contains some stacklayouts, I want to bind the IsVisible Property of my stacklayout to the IsChecked property of my checkbox (which is in another page), but i don't know how to do it, can anybody please help?
I've tried this, but it doesn't work
here's the code in my popup page:
<StackLayout Orientation="Horizontal" Spacing="60">
<local:Checkbox x:Name="va1Checkbox" Text="VA1"/>
<local:Checkbox x:Name="va2Checkbox" Text="VA2"/>
</StackLayout>
and this is the piece of code i have in my MainPage:
<StackLayout IsVisible="{Binding Source={x:Reference
va1Checkbox},Path=IsChecked}">
</StackLayout>
Thanks in advance
<StackLayout Orientation="Horizontal" Spacing="60">
<local:Checkbox x:Name="va1Checkbox" Text="VA1"/>
<local:Checkbox x:Name="va2Checkbox" Text="VA2"/>
</StackLayout>
I believe your popup represents some kind of settings based on which you control your StackLayout in Main Page.
If this is the case, there are two possible solutions.
Create a separate class which is binding for both checkbox and layout. You can use this either with MVVM or without it.
Value Passing: open popup from Main Page and register to its close event. When popup is closed you can use its checkbox's value to enable/disable the layout.
In your Popup.xaml.cs :
create an event action
public event Action<Popup> OnClose;
I believe you will have a way to close it. I don't know you are closing it so I will just use OnBackButtonPressed() here:
protected override bool OnBackButtonPressed()
{
OnClose?.Invoke(this);
return base.OnBackButtonPressed();
}
In your MainPage.xaml.cs :
private void OpenPopup()
{
var popup = new PopupPage();
popup.OnClose += OnPopupClosed;
}
void OnPopupClosed(Popup popup)
{
yourStackLayout.IsVisible = popup.va1Checkbox.Value;
}
UPDATE:
You can pass custom data class instead of popup object:
public class PopupData
{
public bool va1CheckboxValue;
public bool va1CheckboxValue;
// other data which you need to access in other page.
}
then
public event Action<PopupData> OnClose;
and
protected override bool OnBackButtonPressed()
{
PopupData data = new PopupData() { va1CheckboxValue = va1Checkbox.Value; }
OnClose?.Invoke(data);
return base.OnBackButtonPressed();
}
and in main page:
void OnPopupClosed(PopupData data)
{
yourStackLayout.IsVisible = data.va1CheckboxValue;
}
Hope this helps.
I don't know very well XAML and MVVM, but I think you can pass MainPage's ViewModel to Popup... if you change MainPage's ViewModel properties in Popup I think these changes will reflect also to MainPage's binded controls.
If you are not using MVVM (you should...), I think you have to pass a reference to properties used in MainPage to Popup... in this way, Popup can change MainPage's properties and its UI could change

Resources