Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable Button to have a Content #8191

Open
AndreasReitberger opened this issue Jun 21, 2022 · 22 comments
Open

Enable Button to have a Content #8191

AndreasReitberger opened this issue Jun 21, 2022 · 22 comments
Labels
area-controls-button Button, ImageButton labs-candidate Issues that could be done as independent experiments partner/cat 😻 this is an issue that impacts one of our partners or a customer our advisory team is engaged with proposal/open
Milestone

Comments

@AndreasReitberger
Copy link

Description

It would be great to allow the Button control to accept not only a Text, but also a Content or FormattedText.

Public API Changes

<Button 
          VerticalOptions="Start"
          Command="{Binding EnableWebCamCommand}"
          TextColor="{DynamicResource White}"
          FontSize="24" 
          Margin="5,5"
          BackgroundColor="{DynamicResource Transparent}"
          >
          <Button.Content>
              <Grid>
                  <Grid.ColumnDefinitions>
                      <ColumnDefinition Width="Auto"/>
                      <ColumnDefinition />
                  </Grid.ColumnDefinitions>
                  <Label 
                      Text="{StaticResource MaterialDesign_Webcam}"
                      Style="{StaticResource MaterialFontFamilyIconLabelStyle}"
                      TextColor="{DynamicResource White}"
                      VerticalTextAlignment="Center"
                      />
                  <Label
                      Text="{x:Static localization:Strings.On}"
                      TextColor="{DynamicResource White}"
                      Style="{StaticResource LabelStyle}"
                      Grid.Column="1"
                      VerticalTextAlignment="Center"
                      />
              </Grid>
          </Button.Content>
</Button>

Intended Use-Case

In this case, for instance, an icon and a label can be added to the button.
Maybe supporting FormattedText like on the Label control would do the same job (in my case)

@VladislavAntonyuk
Copy link
Contributor

it is not needed as you can use GestureRecognizers to achieve command and clicks

@Symbai
Copy link
Contributor

Symbai commented Jun 21, 2022

it is not needed as you can use GestureRecognizers to achieve command and clicks

Which is much more complicated plus the GestureRecognizer does not work properly, for example #7403 the above proposal already exist in WPF and makes the developer's work much easier. Then it also wouldn't need an extra ImageButton which is also buggy at the moment.

@Eilon Eilon added the legacy-area-controls Label, Button, CheckBox, Slider, Stepper, Switch, Picker, Entry, Editor label Jun 21, 2022
@AndreasReitberger
Copy link
Author

it is not needed as you can use GestureRecognizers to achieve command and clicks

How should this work out? Just add the GestureRecognizer to a label and make it Button like in style?

I rather prefer to do it like above. This makes it more easier and it also does work like this in WPF.

I do not know how much effort this is, but in my opinion this is the "cleanest" way.

Best,
Andreas

@mobilewares
Copy link

it is not needed as you can use GestureRecognizers to achieve command and clicks

It's very limited if other base controls are used - the TapGestureRecognizer only fires an event after the press is complete (finger taken off control). In the App I'm currently working on (where I have custom Templated button control) inherited from a Border class I really need visual/haptic feedback (and command to be executed) on the press action not the release action.

Also it makes total sense to allow for much more powerful customization of buttons OOB too - I think what Syncfusion have done in their Xamarin control set is more along the lines of what devs would regularly need.

@yairp03
Copy link

yairp03 commented Jun 22, 2022

Also, GestureRecognizers don't do the pressing and releasing animation of a button

@mikeparker104 mikeparker104 added the partner/cat 😻 this is an issue that impacts one of our partners or a customer our advisory team is engaged with label Nov 21, 2022
@davepruitt
Copy link

I 100% support this. We need a content button.

@Stratosf
Copy link

Stratosf commented Jan 4, 2023

Yes please! We need that. Does anyone have a workaround for now ?

@janseris
Copy link

janseris commented Jan 4, 2023

@Stratosf Please upvote the post so that it gains priority because .NET GitHub is built on this system.

@samhouts samhouts added this to the Backlog milestone Jan 26, 2023
@ghost
Copy link

ghost commented Jan 26, 2023

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

@JPZV
Copy link

JPZV commented Mar 17, 2023

I totally agree with @yairp03 and @Symbai, using GestureRecognizers which was proposed by @VladislavAntonyuk is awful and pretty much a very bad way for archiving this. There're multiple issues, like overlapping other Tap gestures (like scrolling), uncommanded clicks by the user, no feedback for the user (i.e. the animations), and many visual issues.

I mean, you can implement that with some workarounds on Maui side, like putting a BoxView with alpha and making it visible on press and invisible on release, but that is so ugly, specially if buttons like from Android have nice animations.

So, I made a new Control using Handlers. It's not bullet proof nor it works like you could expect, but at least it's a starting point (and a better workaround for now). I didn't implement Windows nor Tizen as I don't work on those platforms, but you should make it work by looking the code and implement it on those sides.

To make it work, just download the zip below (at the end of my comment) and add its content to your solution, then add this lines on MauiProgram.cs

.ConfigureMauiHandlers(handlers =>
{
    handlers.AddHandler(typeof(ContentButton), typeof(ContentButtonHandler));
});

(You will need to add the respective namespace, but just use intellisense for that)

Then, add this namespace to the XAML where you'll use the ContentButton:

xmlns:nm="clr-namespace:NotMaui.Controls"

And then, just use the ContentButton like a mix between a ContentView and a Button. E.g.:

<nm:ContentButton BorderColor="Transparent"
			      BorderWidth="7"
			      Command="{Binding ButtonClickCommand}">

	<nm:ContentButton.Triggers>
		<DataTrigger TargetType="nm:ContentButton" Binding="{Binding IsReadyToSubmit}" Value="True">
			<Setter Property="BorderColor" Value="{StaticResource Primary}"/>
		</DataTrigger>
	</nm:ContentButton.Triggers>

	<Grid>
		<Grid.ColumnDefinitions>
			<ColumnDefinition Width="*"/>
			<ColumnDefinition Width="*"/>
		</Grid.ColumnDefinitions>

		<Image Grid.Column="0"
			   VerticalOptions="Center"
			   Source="{AppThemeBinding Light=add_item.png, Dark=add_item_dark.png}"/>

		<VerticalStackLayout Grid.Column="1"
							 VerticalOptions="Center">
			<Label Text="Add Item"/>

			<Label Text="{Binding ParentName}"
				   Style={StaticResource Subtitle}/>
		</VerticalStackLayout>
	</Grid>
</nm:ContentButton>

You may want to add an default Style, as it'll not consume the default one for the original Button:

<Style TargetType="nm:ContentButton">
        <Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
        <Setter Property="CornerRadius" Value="8"/>
        <Setter Property="Padding" Value="14,10"/>
        <Setter Property="MinimumHeightRequest" Value="44"/>
        <Setter Property="MinimumWidthRequest" Value="44"/>
        <Setter Property="VisualStateManager.VisualStateGroups">
            <VisualStateGroupList>
                <VisualStateGroup x:Name="CommonStates">
                    <VisualState x:Name="Normal" />
                    <VisualState x:Name="Disabled">
                        <VisualState.Setters>
                            <Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray600}}" />
                        </VisualState.Setters>
                    </VisualState>
                </VisualStateGroup>
            </VisualStateGroupList>
        </Setter>
    </Style>

I hope my Workaround helps you, and I totally hope that Microsoft use part of my work (which is based on ImageButton, Button, and ContentView, with some resources from the Internet) to implement an official ContentButton. Again, this should be a Must feature 🙏

NotMaui.zip

@ADL450
Copy link

ADL450 commented Apr 7, 2023

My reason for wanting this: I need small buttons 25x25 with text in it and MAUI won't display text (of any font size) when button size is 32 or lower. Having a content button would surely have been an easier way to tailor a custom-made button to my needs.

In case anyone wonder why small buttons, let me reassure you it's not for day to day operation by end users. It's meant for a customization mode that allows run-time changes of any text displayed within the app (combined with responsive UI that adjust itself).

@JPZV
Copy link

JPZV commented Apr 7, 2023

MAUI won't display text (of any font size) when button size is 32 or lower

Check if your button have any padding and/or margin larger than zero. You may want this:

<ContentButton Text="hi" WithRequest="25" HeightRequest="25" Padding="0" FontSize="27"/>

@ADL450
Copy link

ADL450 commented Apr 8, 2023

It did solve my issue thanks @JPZV but I implemented your solution and works like a charm. I did have to implement a Windows handler to make it work though. Even though I may not have been in need for it this time, I still believe it truly make sense to have a content button.

@aaronsuydam
Copy link

Also 100% Support this

@samhouts samhouts modified the milestones: Backlog, .NET 8 Planning May 2, 2023
@Sebosek
Copy link

Sebosek commented May 18, 2023

@VladislavAntonyuk Unfortunately, the way how the button and gesture recognizer work is probably different. Currently, I have a bug that is not present if I use buttons, but using the gesture recognizer the bug appears. As expected, I have to use a gesture recognizer because that only way how can I have content, but I can't, and I am officially screwed. 🐖😬
#15147

@samhouts samhouts added the area-controls-button Button, ImageButton label Jul 12, 2023
@cavasinf
Copy link

cavasinf commented Aug 2, 2023

I'm trying to replicate a phone keypad, with the 0 button when long pressed adds a +,
but with the current state of <Button> component there's no way to render that + on the 0 text

image

@larsduewel
Copy link

Also, Gesture Recognizers don't do the pressing and releasing animation of a button

Totally agree, a button needs a proper press and release animation on all supported platforms. I wonder why this is not an high priority issue, since this is one of the first issues you run into when start to develop UI's.

@kisjoke91
Copy link

+1
The Button should definitely have a Content property.

@widavies
Copy link
Contributor

This seems to do the job https://github.com/IeuanWalker/Maui.StateButton

@samhouts samhouts modified the milestones: .NET 8 Planning, Under Consideration Sep 27, 2023
@maexsp
Copy link
Contributor

maexsp commented Dec 14, 2023

To use a GestureRecognizer with any Panel/Border will also create issues when doing UI Automation tests cause the tools like Appium etc. will not be able to identify the button control easily or in the way it should work. Often also because of that a XPath approach is needed to be used which will slow down UI Test performance drasticly. They will not find the UIButton or android.widget.Button as its supposed to be via the OS Automation Interface and this will result in a lot of work. Creating custom AutomationInterface/Properties for each plattform etc.

Any easy alternative with MAUI would be to create a custom control without handlers where a Button is placed within a custom control and in z-Order a ContentView (with InputTransparent) is above the Maui-Button. Create custom properties in the code behind and bind to it in your pages as needed.

@Schaeferje
Copy link

Schaeferje commented Feb 16, 2024

I managed to do a simple custom button with layout, that can use "pressed" and "released" events.

I simply put my button on top of my layout with a transparent background, then add an animation to make it look like a real button, not perfect but very simple.

xaml:
`

<Border BackgroundColor="FloralWhite" Margin="2, 5, 2, 0">
    <Border.Shadow>
        <Shadow Radius="5" Offset="2, 2" Opacity="0.3"/>
    </Border.Shadow>
    <Grid Padding="5" Margin="0">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="50" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>

        <Image Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" Source="{Binding Source={x:Reference self}, Path=ActivityImage}" HeightRequest="50" WidthRequest="50" Margin="0, 0, 0, 0"/>

        <Label Grid.Column="1" Grid.Row="0" Text="{Binding Source={x:Reference self}, Path=ActivityName}" FontSize="18" Margin="15, 0, 0, 0"/>
        <Label Grid.Column="1" Grid.Row="1" Text="{Binding Source={x:Reference self}, Path=ActivityDescription}" FontAttributes="Italic" FontSize="12" Margin="15, 0, 0, 0"/>

        <Button Pressed="Button_Pressed" Released="Button_Released" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Grid.RowSpan="2" BackgroundColor="Transparent" Margin="-10,-10,-10,-10" Clicked="Button_Clicked"/>
    </Grid>
</Border>

`

and code behind:

`public partial class AppButton : ContentView
{
#region Public events
public delegate void OnAppButtonClicked(string activityName);
public static event OnAppButtonClicked OnAppButtonPressed;
#endregion Public events

#region Properties
public string ActivityName
{
    get => (string)GetValue(ActivityNameProperty);
    set => SetValue(ActivityNameProperty, value);
}

public ImageSource ActivityImage
{
    get => (string)GetValue(ActivityImageProperty);
    set => SetValue(ActivityImageProperty, value);
}

public string ActivityDescription
{
    get => (string)GetValue(ActivityDescriptionProperty);
    set => SetValue(ActivityDescriptionProperty, value);
}

public static readonly BindableProperty ActivityNameProperty = BindableProperty.Create(nameof(ActivityName), typeof(string), typeof(AppButton));
public static readonly BindableProperty ActivityImageProperty = BindableProperty.Create(nameof(ActivityImage), typeof(string), typeof(AppButton));
public static readonly BindableProperty ActivityDescriptionProperty = BindableProperty.Create(nameof(ActivityDescription), typeof(string), typeof(AppButton));
#endregion Properties

public AppButton()
{
	InitializeComponent();
}

public AppButton(string activityName, string activityDescription, string activityImage)
{
    ActivityName = activityName;
    ActivityDescription = activityDescription;
    ActivityImage = ImageSource.FromResource(activityImage);
}

private void Button_Clicked(object sender, EventArgs e)
{
    OnAppButtonPressed?.Invoke(ActivityName);
}

private async void Button_Pressed(object sender, EventArgs e)
{
    await (sender as Button).BackgroundColorTo(Colors.FloralWhite);
}

private async void Button_Released(object sender, EventArgs e)
{
    await (sender as Button).BackgroundColorTo(Colors.Transparent);  
}

}`

It makes it look almost like a real button, and easiest way to do it in my opinion.

@Eilon Eilon added labs-candidate Issues that could be done as independent experiments and removed area/labs legacy-area-controls Label, Button, CheckBox, Slider, Stepper, Switch, Picker, Entry, Editor labels May 10, 2024
@AndreasReitberger
Copy link
Author

Any news on this one? :)

@PureWeen PureWeen modified the milestones: Under Consideration, Backlog Aug 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-controls-button Button, ImageButton labs-candidate Issues that could be done as independent experiments partner/cat 😻 this is an issue that impacts one of our partners or a customer our advisory team is engaged with proposal/open
Projects
None yet
Development

No branches or pull requests