-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Conversation
Some thoughts:
I could have done all that already by I'm waiting for your input in order to plan my effort efficiently, thanks. |
d23c9af
to
e882632
Compare
I'll add the Tizen implementation through the subsequent PR. 😉 |
3e9f3d3
to
9497861
Compare
We also have #4369, and as you mentioned, there can be some shared code there. I wonder how we do that without causing a tangled mess. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reviewed the Core part only.
Thanks for this, I'm quite happy with what I'm seeing. Could you please review and discuss naming and code sharing strategies (with Switch), and also review the groupName scoping ? Thanks
Xamarin.Forms.Core/PlatformConfiguration/AndroidSpecific/RadioButton.cs
Outdated
Show resolved
Hide resolved
This is very different than how the CheckBox works. I wish there was some feedback. I put a considerable amount of time on this PR, I'm not sure how to continue with this now. |
Can you elaborate on this a bit? Are you saying that your approach of an implementation is different than how we did CheckBox? Or that fundamentally the two don't align so nothing should be shared betewen them?
I feel like the mileage here of a common base class wouldn't give us too much. I've found that just using interfaces to illustrate shared property is enough and then just reusing the bindable properties via the classes like
Don't we want to add something like (or just exactly) ContentLayout to Checkbox and Radiobutton as well so you can position the text to the right or left of the checkbox and also effect the spacing? I hadn't dove into it yet but my plan for checkbox was to just pass the checkbox into buttonlayoutmanager, initialize it the same way it's initialized on material, and then just hope it all works :-) Checkbox, RadioButton, and Button with an Image Source set
The implementation of ButtonRenderer on ios is super thin. It's more just passing things to Managers. I think just following the same strategy with the checkbox renderer of passing to the managers first is a good idea. Then once it's done and working we can look at refactoring to a base class. Either way I feel like this is a minor detail as most of the core shared code here was already refactored to managers |
My RadioButton impl. is very different than the CheckBox impl. I wanted the RadioButton to be a button , with text, pressed states. After all on native platforms which have a CheckBox (and all have it except iOS), the native check-box control is actually a button.
They should be aligned I think, they are both toggle buttons and share similar properties (same IsChecked property, same CheckChanged event, and same visual states, same border properties), just with a different UI, and the RadioButton has some extra logic for grouping.
A toggle button base class would have important advantages in my opinion:
However, if you still think it doesn't make sense to have a common class, that's OK for me. If you'd like me to still work on this control, please let me know feedback on the existing PR. Thanks! |
I feel like very different is a bit of an overstatement :-) Currently I see CheckBox as a subset to your vision. CheckBox and RadioButton are effectively the same controls just with different images and different state behavior when you click on them. So I see whatever you are doing for RB as something that's just going to be symmetrically applied to CB by whatever means of sharing we come up with
Still not sure. Switch has IsToggled and CheckBox has IsChecked. Checkbox hasn't been released so should we call it IsToggled instead and create common base class? In a perfect world I'd say we go the android route and just create a CompoundButton that inherits from Button then just make switch, radio, checkbox all inherit from that because even at the platform level they are all just buttons with states so literally all the code we have that operates on buttons should just be applied to cb, rb, switch. Let me bounce this off a few people then get back to you. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Compilation error
Xamarin.Forms.Platform.iOS\Renderers\RadioButtonRenderer.cs(82,34): Error CS0311: The type 'Xamarin.Forms.RadioButton' cannot be used as type parameter 'T' in the generic type or method 'VisualElementExtensions.UseLegacyColorManagement<T>(T)'. There is no implicit reference conversion from 'Xamarin.Forms.RadioButton' to 'Xamarin.Forms.IElementConfiguration<Xamarin.Forms.RadioButton>'.
Xamarin.Forms.Platform.UAP\RadioButtonRenderer.cs(69,8): Error CS0311: The type 'Xamarin.Forms.RadioButton' cannot be used as type parameter 'T' in the generic type or method 'VisualElementExtensions.UseFormsVsm<T>(T)'. There is no implicit reference conversion from 'Xamarin.Forms.RadioButton' to 'Xamarin.Forms.IElementConfiguration<Xamarin.Forms.RadioButton>'.
Process 'msbuild.exe' exited with code '1'.
- On iOS I can "uncheck" the RadioButton if I click it twice.
- UWP isn't using the ContentLayout property
- On iOS can we also refactor that to use the ButtonLayoutManager?
Tag = this; | ||
} | ||
|
||
void UpdateFont() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we just move all of this code into ButtonLayoutManager and anything else that's the same among the buttons? How much of the identical code can we just move into ButtonLayoutManager?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
only re-reviewed the Core, we're not there yet (but making progress)
set { SetValue(IsCheckedProperty, value); } | ||
} | ||
|
||
public string GroupName |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you have
StackLayout
Frame
RadioButton
Frame
RadioButton
so the 2 radio buttons aren't in the same group ?
public static readonly BindableProperty ButtonSourceProperty = BindableProperty.Create( | ||
nameof(ButtonSource), typeof(ImageSource), typeof(RadioButton), null); | ||
|
||
public event EventHandler<CheckedChangedEventArgs> CheckedChanged; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see how this is resolved
[RenderWith(typeof(_RadioButtonRenderer))] | ||
public partial class RadioButton : IToggleButtonElement, IToggleButtonController, ITextButtonElement | ||
{ | ||
static Dictionary<string, List<WeakReference<RadioButton>>> _groupNameToElements; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the problem with this approach is the List keeps getting populated, and so the performance degrades over time
set { SetValue(IsCheckedProperty, value); } | ||
} | ||
|
||
public string GroupName |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also, you say the scope is the parent, but looking at GetVisualRoot, the scope is the page. what if I have this
Page
StackLayout
YesNoMaybeControl
YesNoMaybeControl
YesNoMaybeControl
} | ||
} | ||
|
||
static Element GetVisualRoot(Element element) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👎
[RenderWith(typeof(_RadioButtonRenderer))] | ||
public partial class RadioButton : IToggleButtonElement, IToggleButtonController, ITextButtonElement | ||
{ | ||
static Dictionary<string, List<WeakReference<RadioButton>>> _groupNameToElements; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've seen PurgeDeads
, but we probably can do better
|
||
public event EventHandler<CheckedChangedEventArgs> CheckedChanged; | ||
|
||
public bool IsChecked |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Checked
is probably a better name. We try to avoid property names containing multiple verbs. The IsXxxx
construct is valid when Xxxx is an adjective. We can debate that in this case Checked
is used as an adjective or not, I still think the name is overloaded
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is not a big deal, I know we have IsEnabled
already, and might want to reserve the Checked
name for the event. so it's fine to leave it as is, and rename the event
namespace Xamarin.Forms | ||
{ | ||
[RenderWith(typeof(_RadioButtonRenderer))] | ||
public partial class RadioButton : Button |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
drop the partial. where is the IToggleElement
interface you use to have ?
|
||
public const string IsCheckedVisualState = "IsChecked"; | ||
|
||
public static readonly BindableProperty IsCheckedProperty = BindableProperty.Create( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this isn't 2-Way, but should
public static readonly BindableProperty GroupNameProperty = BindableProperty.Create( | ||
nameof(GroupName), typeof(string), typeof(RadioButton), null, propertyChanged: (b, o, n) => ((RadioButton)b).OnGroupNamePropertyChanged((string)o, (string)n)); | ||
|
||
public static readonly BindableProperty ButtonSourceProperty = BindableProperty.Create( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how does this works ? is this a spriteMap ? don't we need a source for both on and off ?
@andreinitescu There is some feedback (and also conflicts). Let us know if we can help you with something ;) |
* RadioButton * Removed unused files * Rebase and make it run * First round of feedback * Revert AppCompatButton -> AButton * Cleaned minor usings * Fix unselecting radiobutton on iOS * Fixed Mac OS grouping * [Android] Fix API29 usages Co-authored-by: Andrei Nitescu <nitescua@yahoo.com> Co-authored-by: Rui Marinho <me@ruimarinho.net>
How end user can differentiate between RadioButton and Checkbox in iOS ? |
Description of Change
RadioButton implementation.
Issues Resolved
API Changes
Added:
Platforms Affected
Behavioral/Visual Changes
GroupName property
The "RadioButton group Gallery - Legacy" has three tabs which show group behavior.
Radio-buttons with group name null are grouped by their parent.
Radio-buttons with same group name, no matter the hierarchy, are grouped at page level.
Video: https://www.youtube.com/watch?v=fwYSmvjCfbw
Before/After Screenshots
Testing Procedure
PR Checklist