Xamarin Android: Underline Custom Label Control (make it look like an Entry) - xamarin

In our application we have some controls that are Entry controls that take in numbers, so we want the user to be able to type into them. Other controls are popup selections such as a Date, or a Picker control, of which we code as Label controls.
To give the user the same consistency as Entry controls, for iOS we put the same frames around them as an Entry control in iOS such as this:
Standard Entry Control Xaml:
<Entry Grid.Row="0" Grid.Column="1" Keyboard="Numeric" ReturnType="Done" WidthRequest="60"
Text="{Binding SocketItem.QuantityPerSys, Converter={StaticResource IntComma}}"
TextChanged="OnIntegerEntryChanging" Placeholder="0"
AutomationId="SocketQtySysValueEntry" />
Mimic'ed Entry Control for iOS Rendering:
<Frame Grid.Row="1" Grid.Column="1" AutomationId="SocketDecisionDateEntryFrame">
<Label Text="{Binding SocketItem.DecisionDate, StringFormat='{0:M/d/yy}', Converter={StaticResource LocalTime}}"
HorizontalTextAlignment="Center" HorizontalOptions="FillAndExpand" AutomationId="SocketDecisionDateValueEntry"/>
<Frame.GestureRecognizers>
<TapGestureRecognizer Tapped="OnSocketDateTapped" CommandParameter="DecisionDate" />
</Frame.GestureRecognizers>
</Frame>
However in Android the Entry controls have a line underneath them:
Android Entry Control
We want to render these label controls the same as the Entry controls so they are consistent:
Label and Entry controls
My assumption is that I have to use a custom renderer of which I already have setup, but with just a normal underline of the text (which is of course what I don't want):
class UnderlinedLabelRenderer : LabelRenderer
{
public UnderlinedLabelRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
if (Control != null && Control is FormsTextView textView)
{
textView.PaintFlags |= PaintFlags.UnderlineText;
}
}
}
I've tried investigating the actual Xamarin.Forms renderer code for the Entry control, but I'm not familiar enough with it or know exactly which class to look at to figure it out (I'll continue that route in the mean time). I am assuming I'll have to somehow add a new box control to the label cell or something.
I've also looked at this question: Xamarin Forms Android EntryCell Underline which is related but the opposite of what I want to do.
I also tried making the controls disabled Entry controls:
<StackLayout Grid.Row="1" Grid.Column="1" HorizontalOptions="End" AutomationId="OppApplicationValueFrame">
<controls:ReadonlyEntry Text="{Binding Opportunity.Application}" IsEnabled="False"
AutomationId="OppApplicationValueEntry"/>
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Tapped="OnApplicationTapped" />
</StackLayout.GestureRecognizers>
</StackLayout>
but that yielded light gray text (due to the disabled). I then created a custom renderer to fix the text:
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (Control != null && Control is FormsEditText editText)
{
editText.SetTextColor(Android.Graphics.Color.Gray);
//editText.SetBackgroundColor(Android.Graphics.Color.Gray);
}
}
but the underline on the control is still light grey (disabled color). I referenced this question on how to remove the underline: Xamarin Forms Android EntryCell Underline. But doing the opposite of setting it to another color makes the entire cell Gray.
How do I change the color of the underline in the CustomRenderer?
Any help would be great or a place to start looking.

I think the easiest way to achieve your requirement is to use a Entry instead of a Label, disable the edit ability of the entry and add a TapGestureRecognizers there to handle event:
<StackLayout>
<Entry IsEnabled="False" Text="test" HorizontalTextAlignment="Center" />
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped" NumberOfTapsRequired="1" />
</StackLayout.GestureRecognizers>
</StackLayout>
And I don't think you can achieve this by using a custom renderer of Lable, native TextView does not has this feature.
Another way is to create a custom control, like a view contains a label and a view(height =1) with black background color which stay under the label.
Update:
Code in the custom renderer to change the color of underline:
[assembly: ExportRenderer(typeof(myEntry), typeof(MyEntryRenderer))]
namespace App557.Android
{
class MyEntryRenderer : EntryRenderer
{
public MyEntryRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (Control != null)
{
EditText editText = Control as EditText;
editText.Enabled = false;
editText.SetTextColor(global::Android.Graphics.Color.LightGreen);
editText.Background.SetColorFilter(global::Android.Graphics.Color.LightGreen, PorterDuff.Mode.SrcIn);
editText.SetSingleLine(true);
editText.Ellipsize = TruncateAt.End;
}
}
}
}

Related

How to disable Syncfusion's Autocomplete from moving to the next entry when completed?

I'm using Syncfusion's Autocomplete entry in Xamarin.Forms in a way not related to a form. Thus, I don't want it to step to the next Entry object in the UI. However, doesn't matter what I try doing, when finishing putting in the input, it jumps to the next Entry.
I have tried setting both Entrys IsTabStop to False, as well as setting the second one's TabIndex to be smaller the other one's. Nothing worked, the only think which I have found to work is disabling the second Entry while the other one is focused.
XAML:
<ScrollView ...>
// ....
<StackLayout>
// ....
<autocomp:SfAutoComplete x:Name="TagsAutoComplete"
WidthRequest="100"
NoResultsFoundText="New Tag..."
DisplayMemberPath="Name"
Keyboard="Chat"
IsTabStop="False"
IsVisible="False"
Completed="AddTagAutoComplete_Completed" />
// ....
</StackLayout>
// ....
<Frame>
<Grid>
// ....
<Entry FontSize="18" TextColor="Black"
WidthRequest="150" VerticalOptions="Center"
Unfocused="EquValueEntry_Unfocused"
TabIndex="-1" IsTabStop="False" />
// ....
</Grid>
</Frame>
// ....
</ScrollView>
My workaround uses the Focused and Unfocused methods of the Autocomplete, which simply set the IsEnabled property of the second Entry to False and True respectively. Does anyone have a better, more elegant solution?
We would like to let know that you can stop the next Entry focus by Return type and IME option.
UWP:
Setting IsTabStop as false it disables the next Entry focus.
Android:
By changing the input method options of EditText in autocomplete (using ImeOptions property)
protected override void OnElementChanged(ElementChangedEventArgs<SfAutoComplete> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.GetAutoEditText().ImeOptions = Android.Views.InputMethods.ImeAction.Done;
Control.GetAutoEditText().SetImeActionLabel("Send", Android.Views.InputMethods.ImeAction.Done);
}
iOS:
By changing the return type property of UITextField in autocomplete (using ReturnKeyType property)
protected override void OnElementChanged(ElementChangedEventArgs<SfAutoComplete> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.TextField.ReturnKeyType = UIReturnKeyType.Done;
}
}
We have prepared a sample for your reference get it from below link.
Sample: https://www.syncfusion.com/downloads/support/directtrac/general/ze/AutoComplete_EntryNotFocus1409818301
For more information refer the link:
https://www.syncfusion.com/kb/10690/how-to-change-return-button-type-in-sfautocomplete

How to make frame contents respect its corner radius?

I have different elements, controls and views wrapped in frames in order to apply corner radius, which is working fine on Android. But on the iOS side, even though the frame is round cornered, its contents does not clip to its radius but stays square as if nothing is applied.
Sample:-
<Frame BackgroundColor="{DynamicResource Theme}" CornerRadius="15" Padding="0">
<Image Source="{Binding PImage}" HeightRequest="132.5" Aspect="AspectFill"/>
</Frame>
Expected (Which happens in Android):-
Actual:-
How to make the frame contents respect the corner radius like what happens in Android ?
Clip the content of the frame to its boundaries:
<StackLayout Padding="30">
<Frame CornerRadius="30" Padding="0" IsClippedToBounds="True">
<Image Source="https://aka.ms/campus.jpg" />
</Frame>
</StackLayout>
https://stackoverflow.com/a/55611485/1039935
From shared code works in my local site :
The sample solution : Have a check with the version of Visual Studio and Xamarin Forms .Be sure that have updated to the latest version (Visual Studio: 16.6.5, Xamarin Forms : 4.7.0.1239).
Otherwise , you can create a Custom Frame Renderer in iOS to set CornerRadius .
Create a CustomFrame :
public class CustomFrame: Frame
{
}
Create a Custom renderer in iOS:
public class CustomFrameRenderer : FrameRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Frame> e)
{
base.OnElementChanged(e);
Layer.CornerRadius = Element.CornerRadius;
//Layer.CornerRadius = 15;
Layer.MasksToBounds = true;
}
}
In Xaml use the custom Renderer :
<local:CustomFrame BackgroundColor="CadetBlue"
Padding="0">
<Image Source="XamarinLogo.png"
HeightRequest="132.5"
Aspect="AspectFill" />
</local:CustomFrame>

How can I make the Tapped event of a ViewCell send a param to a generic function and then open up a picker for that ViewCell element?

Update: Just a reminder, there's a 500 point bonus on this if someone can just show me how to implement this functionality without using Gestures>
I am using a ViewCell and a gesture recognizer to open up a picker with the following code. The ViewCell has a label on the left and a label area on the right that is populated initially when the app starts and later with the picker when the ViewCell is clicked.
XAML
<ViewCell x:Name="ati" Tapped="OpenPickerCommand">
<Grid VerticalOptions="CenterAndExpand" Padding="20, 0">
<Grid.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding OpenPickerCommand}"
CommandParameter="{x:Reference atiPicker}" NumberOfTapsRequired="1" />
</Grid.GestureRecognizers>
<local:LabelBodyRendererClass Text="Answer Time Interval" HorizontalOptions="StartAndExpand" />
<Picker x:Name="atiPicker" IsVisible="false" HorizontalOptions="End" SelectedIndexChanged="atiPickerSelectedIndexChanged" ItemsSource="{Binding Times}"></Picker>
<local:LabelBodyRendererClass x:Name="atiLabel" HorizontalOptions="End"/>
</Grid>
</ViewCell>
<ViewCell x:Name="pti" Tapped="OpenPickerCommand">
<Grid VerticalOptions="CenterAndExpand" Padding="20, 0">
<Grid.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding OpenPickerCommand}"
CommandParameter="{x:Reference ptiPicker}" NumberOfTapsRequired="1" />
</Grid.GestureRecognizers>
<local:LabelBodyRendererClass Text="Phrase Time Interval" HorizontalOptions="StartAndExpand" />
<Picker x:Name="ptiPicker" IsVisible="false" HorizontalOptions="End" SelectedIndexChanged="ptiPickerSelectedIndexChanged" ItemsSource="{Binding Times}"></Picker>
<local:LabelBodyRendererClass x:Name="ptiLabel" HorizontalOptions="End"/>
</Grid>
</ViewCell>
C# This works for different pickers (ati, bti, pti etc) with CommandParameter
public SettingsPage()
{
InitializeComponent();
BindingContext = new CommandViewModel();
}
void atiPickerSelectedIndexChanged(object sender, EventArgs e)
{
var picker = (Picker)sender;
int selectedIndex = picker.SelectedIndex;
if (selectedIndex != -1)
{
App.DB.UpdateIntSetting(Settings.Ati, selectedIndex);
atiLabel.Text = AS.ati.Text();
}
}
void ptiPickerSelectedIndexChanged(object sender, EventArgs e)
{
var picker = (Picker)sender;
int selectedIndex = picker.SelectedIndex;
if (selectedIndex != -1)
{
App.DB.UpdateIntSetting(Settings.Pti, selectedIndex);
ptiLabel.Text = AS.pti.Text();
}
}
public class CommandViewModel: ObservableProperty
{
public ICommand openPickerCommand;
public CommandViewModel()
{
openPickerCommand = new Command<Picker>(PickerFocus);
//openPickerCommand = new Command(tapped);
}
public ICommand OpenPickerCommand
{
get { return openPickerCommand; }
}
void PickerFocus(Picker param)
{
param.Focus();
}
}
I would like to remove the use of TapGestureRecognizers but I still want to retain the functionality and layout.
It's been suggested to me that it would be better if I used the Tapped event of the ViewCell like this:
Tapped="OnTapped"
Can someone explain in some detail how I could wire this up in C#. Would I be best to code something into the CommandViewModel as well as in the C# backing code. Also can the view model have one method that takes an argument so it could be used to open up different pickers?
An example of how I could do this would be very much appreciated. Note that I don't particularly need to use the CommandViewModel if there is a way that I could do this by coding just in the .cs backing code.
(Sorry for the poor english)
Despite not being best practice, I guess you can do something like this, dismissing the viewmodel:
XAML:
<ViewCell x:Name="ati" Tapped="OpenPickerCommand">
<Grid VerticalOptions="CenterAndExpand" Padding="20, 0">
<local:LabelBodyRendererClass Text="Answer Time Interval" HorizontalOptions="StartAndExpand" />
<Picker x:Name="atiPicker"
IsVisible="false"
HorizontalOptions="End"
SelectedIndexChanged="atiPickerSelectedIndexChanged"
ItemsSource="{Binding Times}">
</Picker>
<local:LabelBodyRendererClass x:Name="atiLabel" HorizontalOptions="End"/>
</Grid>
</ViewCell>
<ViewCell x:Name="pti" Tapped="OpenPickerCommand">
<Grid VerticalOptions="CenterAndExpand" Padding="20, 0">
<local:LabelBodyRendererClass Text="Phrase Time Interval" HorizontalOptions="StartAndExpand" />
<Picker x:Name="ptiPicker" IsVisible="false" HorizontalOptions="End" SelectedIndexChanged="ptiPickerSelectedIndexChanged" ItemsSource="{Binding Times}"></Picker>
<local:LabelBodyRendererClass x:Name="ptiLabel" HorizontalOptions="End"/>
</Grid>
</ViewCell>
C#:
private void OpenPickerCommand(object sender, System.EventArgs e)
{
if (sender != null)
{
Picker pkr = sender == ati ? atiPicker : ptiPicker;
pkr.Focus();
}
}
Answering your question "Can the view model have one method that takes an argument?", it is exactly what you're already doing using the 'OpenPickerCommand' method. The problem is that using the ViewCell's public event 'Tapped', you can't set parameters to the delegate handler.
Let me know if it works for you or if you do need some more information.
I hope it helps.
You can solve this with attached properties. Simply define a "behavior" class for ViewCell that adds the Command/Parameter properties.
public static class TappedCommandViewCell
{
private const string TappedCommand = "TappedCommand";
private const string TappedCommandParameter = "TappedCommandParameter";
public static readonly BindableProperty TappedCommandProperty =
BindableProperty.CreateAttached(
TappedCommand,
typeof(ICommand),
typeof(TappedCommandViewCell),
default(ICommand),
BindingMode.OneWay,
null,
PropertyChanged);
public static readonly BindableProperty TappedCommandParameterProperty =
BindableProperty.CreateAttached(
TappedCommandParameter,
typeof(object),
typeof(TappedCommandViewCell),
default(object),
BindingMode.OneWay,
null);
private static void PropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
if (bindable is ViewCell cell)
{
cell.Tapped -= ViewCellOnTapped;
cell.Tapped += ViewCellOnTapped;
}
}
private static void ViewCellOnTapped(object sender, EventArgs e)
{
if (sender is ViewCell cell && cell.IsEnabled)
{
var command = GetTappedCommand(cell);
var parameter = GetTappedCommandParameter(cell);
if (command != null && command.CanExecute(parameter))
{
command.Execute(parameter);
}
}
}
public static ICommand GetTappedCommand(BindableObject bindableObject) =>
(ICommand)bindableObject.GetValue(TappedCommandProperty);
public static void SetTappedCommand(BindableObject bindableObject, object value) =>
bindableObject.SetValue(TappedCommandProperty, value);
public static object GetTappedCommandParameter(BindableObject bindableObject) =>
bindableObject.GetValue(TappedCommandParameterProperty);
public static void SetTappedCommandParameter(BindableObject bindableObject, object value) =>
bindableObject.SetValue(TappedCommandParameterProperty, value);
}
After that reference your behavior namespace in XAML and specify the property values using fully qualified names:
<ViewCell StyleId="disclosure-indicator"
behaviors:TappedCommandViewCell.TappedCommand="{Binding BrowseCommand}"
behaviors:TappedCommandViewCell.TappedCommandParameter="https://www.google.com">
<StackLayout Orientation="Horizontal">
<Label Text="Recipient"
VerticalOptions="Center"
Margin="20,0"/>
<Label Text="{Binding LedgerRecord.Recipient}"
HorizontalOptions="EndAndExpand"
VerticalOptions="Center"
Margin="0,0,20,0"/>
</Label>
</StackLayout>
</ViewCell>
The above will allow you to use MVVM and no Tap Gesture Recognizers.
The first problem is that you're mixing the code-behind and MVVM
approaches in the same code. It is confusing and certainly not the
right way to code what you want to achieve. So, all commanding must
be in the ViewModel attached to the View, no code-behind apart some
code only used for UI effects.
There is no need to define a gesture recognizer for all visual items since you just want to detect the tap on all the surface of the viewcell. To achieve this you must define all children of the ViewCell with InputTransparent=true. So the tap will not be detected and will be trapped by the parent ViewCell (you
must indicate the InpuTransparent because there is no tap event
bubbling in X.Forms).
Showing and Hidding the picker is a View problem not a ViewModel one. So here you can use some code-behind to create an event handler for the ViewCell Tapped event. This handler will just set visible=true on the picker.
The picker selected event must be connected to a corresponding Command in the ViewModel. So each time the picker is displayed and a value is selected your viewmodel will be aware of the action. This is the only command you need in your viewmodel. Depending of XForms version the picker has no bindable command, so you can use one of the numerous "bindablepicker" implementation you can find on the web or you can also use a XAML EventToCommand Behavior.
So there is two different problems : showing/hidding the picker which can be achieved directly in XAML or with the help of a bit of code-behind; and the picker item selection that must be managed using a Command in the viewmodel.
Hoping this will help you

how to use radio buttons in xamarin forms

Creating a Registration page, I need to get the following data from user.
First Name
Last Name
Username
Email
Password
Date of Birth
Gender
User Role
For the last two parameters, I am unable to find how to use radio buttons in Xamarin.Forms. Following is my code for the Registration Page.
<StackLayout BackgroundColor="#30af91" Padding="60">
<Entry Text="{Binding FirstName}" Placeholder="First Name"/>
<Entry Text="{Binding LastName}" Placeholder="Last Name"/>
<Entry Text="{Binding UserName}" Placeholder="Last Name"/>
<Entry Text="{Binding Email}" Placeholder="Email" />
<Entry Text="{Binding Password}" Placeholder="Password" IsPassword="True"/>
<Entry Text="{Binding ConfirmPassword}" Placeholder="Confirm Password" IsPassword="True"/>
<DatePicker MinimumDate="1/1/1948" MaximumDate="12/31/2007"/>
<!--Radio buttons for Gender
1. Male 2.Female-->
<!--Radio Buttons for UserRole
1. Admin 2.Participant-->
<Button Command="{Binding RegisterCommand}" Text="Register"/>
<Label Text="{Binding Message}" />
</StackLayout>
Xamarin forms does not provide Radio Button.
You can either use
1)Switch
2)Picker
or any other component to fulfill your requirement
UPDATE
The xamarin forms update version 4.6 has introduced the Radio button control, Here is the official documentation
I think there is a simpler solution that is fairly easy and requires no libraries. Really a a radio group is just a fancy ListView. You would just need to create a viewModel for each radio button that has a IsSelected flag and switch between 2 images. I had a need to allow a user to select how long a token persisted:
XAML
<ListView
HasUnevenRows="True"
HorizontalOptions="FillAndExpand"
ItemsSource="{Binding Durations}"
ItemSelected="ListView_ItemSelected"
SelectedItem="{Binding SelectedDuration}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout
Orientation="Horizontal">
<Image
HeightRequest="18"
IsVisible="{Binding IsSelected}"
Source="radioButtonChecked.png"
WidthRequest="18"/>
<Image
HeightRequest="18"
IsVisible="{Binding IsUnselected}"
Source="radioButtonUnchecked.png"
WidthRequest="18"/>
<Label
Margin="8,0,0,0"
Text="{Binding Caption}"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
We create a listview in our content page and listen for the ItemSelected event. Each list item is a horizontal stack panel where we flip between two images depending on the selected state
Code Behind
public partial class LoginPage : ContentPage
{
LoginPageViewModel LoginPageViewModel { get; }
public LoginTwoFactorFrequencyPage ()
{
BindingContext = LoginPageViewModel = new LoginPageViewModel();
InitializeComponent ();
}
private void ListView_ItemSelected(object sender, SelectedItemChangedEventArgs e)
{
LoginPageViewModel.UpdateSelected(e.SelectedItem as PersistenceDuration);
}
}
The page's code behind instantiates a view model and calls an UpdateSelected method with the newly selected item on the page's view model*
RadioButton ViewModel
The view model for each radio button:
public class PersistenceDuration : ViewModelBase
{
bool isSelected;
public string Caption { get; set; }
public TwoFactorTokenPersistenceDuration Duration { get; set; }
public bool IsSelected
{
get => isSelected;
set
{
isSelected = value;
OnPropertyChanged();
OnPropertyChanged("IsUnselected");
}
}
public bool IsUnselected => !IsSelected;
public PersistenceDuration(string caption, TwoFactorTokenPersistenceDuration duration)
{
Caption = caption;
Duration = duration;
IsSelected = false;
}
}
The radio button view model holds selection info and the caption. We make sure to fire OnPropertyChanged whenever the selected state changes
Page ViewModel
public class LoginPageViewModel : ViewModelBase
{
PersistenceDuration duration;
PersistenceDuration selectedDuration;
public ObservableCollection<PersistenceDuration> Durations { get; }
public PersistenceDuration SelectedDuration
{
get => selectedDuration;
set
{
if (value != null)
{
duration = value;
UpdateSelected(duration);
}
OnPropertyChanged();
}
}
public LoginTwoFactorFrequencyViewModel()
{
Durations = new ObservableCollection<PersistenceDuration>(
new List<PersistenceDuration>()
{
new PersistenceDuration(AppResources.Save_code__forever, TwoFactorTokenPersistenceDuration.Forever),
new PersistenceDuration(AppResources.ChatRequireEvery30Days, TwoFactorTokenPersistenceDuration.ThirtyDays),
new PersistenceDuration(AppResources.ChatRequireEveryLogin, TwoFactorTokenPersistenceDuration.None),
});
}
public void UpdateSelected(PersistenceDuration persistenceDuration)
{
foreach (var item in Durations)
item.IsSelected = persistenceDuration == item;
}
}
In the page view model we create a list of radio button view models that the XAML binds to. When we UpdateSelected() all the IsSelected states are updated which trigger binding updates which flip the image.
You will still need to do something about the highlight when someone selects an item, but that is easy enough to find on the internet :)
You can use XLabs plugin from manage NuGets package. After installing you can use like this:
In Xaml:
controls:BindableRadioGroup x:Name="Radiobtn"
In C#:
string[] gender = {"MAlE","FEMALE"}
Radiobtn.Add(gender)
Refer Link
https://github.com/XLabs/Xamarin-Forms-Labs/tree/master/samples/XLabs.Samples/XLabs.Samples/Pages/Controls
You can get the radio button effect without a package. Use Labels with text unicode circle \u26AA or \u25CB. Attach a tab gesture recognizer to each label.
When tapped, change the text of the selected button to unicode circle bullet \u29BF and change the text of the other button(s) back to unicode circle \u26AA.
Test on your preferred platforms as each platform may display somewhat differently. You may need to adjust the font size as you change the text.
If you want real radiobuttons you can xlabs their package (https://github.com/XLabs/Xamarin-Forms-Labs/tree/master/src/Forms/XLabs.Forms/Controls/RadioButton)
Personally I'd just use a picker, Xlabs package hasn't been updated in a while so their might be some bugs in the radiobutton
You can use image as a radio button. When tou you click on it, it can change. It is not a good way to do it though.
This is xaml code:
<Image Scale="0.7" HorizontalOptions="Start" x:Name="radioButton" Source="unRadioBtn.png">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="radioButton_Clicked"></TapGestureRecognizer>
</Image.GestureRecognizers>
</Image>
And this is .cs:
private void radioButton_Clicked(object sender, EventArgs e)
{
radioButton.Source = "radioBtn.png";
}
Xamarin.Forms 4.6 introduced a new RadioButton control. You can find the documentation here: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/radiobutton
You can use the switch component. Also you can see the implementation for a checkbox component from the XLabs project which is now discontinued, get the code and modify it as you need.
Hint: You're gonna need the custom renderers per platform for it to work .
You need to use Picker
https://developer.xamarin.com/api/type/Xamarin.Forms.Picker/
Actually it is the best alternative to RadionButton On Xamarin.forms
XLabs RadioButton and BindableRadioGroup work well: XLabs RadioButton for Xamarin Forms
Here's a simple Yes/No radio using the BindableRadioGroup:
var answers = new List<string>();
answers.Add("Yes");
answers.Add("No");
var RadioGroup = new XLabs.Forms.Controls.BindableRadioGroup()
{
ItemsSource = answers,
Orientation = StackOrientation.Horizontal
};
Xamarin Forms now provides a Radio Button control.
See docs here:
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/radiobutton
As of XF 4.8 this is still experimental and I've not yet used this feature so can't comment on its stability.

Why can't I tap/click blank areas inside of a Border/ContentControl without setting the child's background to transparent?

I finally was able to create an "easy" transparent button control, based off a ContentControl. However, can someone explain why I couldn't click/tap any blank areas of the control until I set the background of the child element to transparent? I ran into this issue also when:
I tried to use Border
I set the ControlTemplate of a button rather than the ContentTemplate.
Here's my "button" class:
public class TransparentButton : ContentControl {
public TransparentButton() {
HorizontalContentAlignment = HorizontalAlignment.Stretch;
}
public override void OnApplyTemplate() {
var child = Content as Grid;
if (child != null) {
child.Background = new SolidColorBrush(Colors.Transparent);
}
base.OnApplyTemplate();
}
}
It's pretty specific to my cases when using (assuming a Grid child) but it works. The reason I use it is for lists (non-ListBox) with the TiltEffect enabled.
Context of the issue:
<ItemsControl x:Name="Items" toolkit:TiltEffect.IsTiltEnabled="True">
<ItemsControl.ItemTemplate>
<DataTemplate>
<controls:TransparentButton
cal:Message.Attach="[Event Tap] = [Action Go($dataContext)]">
<Grid>
<StackPanel HorizontalAlignment="Left">
<TextBlock Text="{Binding Test}" />
</StackPanel>
<StackPanel HorizontalAlignment="Right">
<TextBlock Text="{Binding Test2}" />
</StackPanel>
</Grid>
</controls:TransparentButton>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
If you click between the StackPanels inside the item, no event gets fired and nothing happens. Only when the Grid's Background is Transparent does it "take up space".
I come from a web background so this is confusing; a containing element should be "hit testable" even when it's background isn't set.
An object with no background is usually called as hollow or non-hittable in XAML terms. So it is must to set a background to make the object respond to hits. To achieve hit test for an transparent object, you should set the background to transparent.
More information about hit testing
http://msdn.microsoft.com/en-us/library/ms752097.aspx

Resources