Alan2
Alan2

Reputation: 24602

How can I achieve four spaced buttons on an iPhone that fill the screen and on bigger than an iPhone that fill half the screen?

I would like to have four buttons like this:

<Grid x:Name="buttonGrid" Grid.Row="3" Grid.Column="0" HorizontalOptions="FillAndExpand" VerticalOptions="Center" Padding="20, 0">
    <Button x:Name="zeroButton" Text="0" HeightRequest="60" BackgroundColor="#2D7BF7" HorizontalOptions="FillAndExpand" VerticalOptions="StartAndExpand"/>
    <Button x:Name="oneButton" Text="1" HeightRequest="60" BackgroundColor="#2D7BF7" HorizontalOptions="FillAndExpand" VerticalOptions="StartAndExpand"/>
    <Button x:Name="twoButton" Text="2" HeightRequest="60" BackgroundColor="#2D7BF7" HorizontalOptions="FillAndExpand" VerticalOptions="StartAndExpand"/>
    <Button x:Name="fiveButton" Text="5" HeightRequest="60" BackgroundColor="#2D7BF7" HorizontalOptions="FillAndExpand" VerticalOptions="StartAndExpand"/>
</Grid>

On an iPhone or a small mobile I would like to have these fill 90% of the screen width. But on a bigger screen I would like the buttons to only fill 50% of the screen width.

Can anyone suggest to me how I can do this?

Upvotes: 5

Views: 232

Answers (1)

Brandon Minnick
Brandon Minnick

Reputation: 15420

Explanation

If you need to create layouts that reference the ContentPage.Width or ContentPage.Height properties, the best way to do it is by using a RelativeLayout.

If you try referencing the ContentPage.Width or ContentPage.Height properties directly, you will find that Xamarin.Forms returns -1. This is because -1 is the default value that Xamarin.Forms uses when it hasn't instantiated the control yet.

RelativeLayout uses Funcs to dynamically reference the page's Height and Width properties and will return the true value of the Height and Width properties once the ContentPage has been instantiated.

Code

using Xamarin.Forms;

namespace HorizontalButtonSampleApp
{
    public class ButtonPage : ContentPage
    {
        public ButtonPage()
        {
            const int relativeLayoutHorizontalSpacing = 5;
            const int numberOfButtons = 4;

            double screenUsePercentage;
            if (Device.Idiom.Equals(TargetIdiom.Phone))
                screenUsePercentage = 0.9;
            else
                screenUsePercentage = 0.5;

            var zeroButton = new StyledButton { Text = "0" };
            var oneButton = new StyledButton { Text = "1" };
            var twoButton = new StyledButton { Text = "2" };
            var fiveButton = new StyledButton { Text = "5" };

            var relativeLayout = new RelativeLayout();
            relativeLayout.Children.Add(zeroButton,
                                        Constraint.RelativeToParent(parent => parent.Width * (1 - screenUsePercentage) / 2),
                                        Constraint.Constant(0),
                                        Constraint.RelativeToParent(parent => (parent.Width * screenUsePercentage - relativeLayoutHorizontalSpacing * (numberOfButtons - 1)) / numberOfButtons));
            relativeLayout.Children.Add(oneButton,
                                        Constraint.RelativeToView(zeroButton, (parent, view) => view.X + view.Width + relativeLayoutHorizontalSpacing),
                                        Constraint.Constant(0),
                                        Constraint.RelativeToParent(parent => (parent.Width * screenUsePercentage - relativeLayoutHorizontalSpacing * (numberOfButtons - 1)) / numberOfButtons));
            relativeLayout.Children.Add(twoButton,
                                        Constraint.RelativeToView(oneButton, (parent, view) => view.X + view.Width + relativeLayoutHorizontalSpacing),
                                        Constraint.Constant(0),
                                        Constraint.RelativeToParent(parent => (parent.Width * screenUsePercentage - relativeLayoutHorizontalSpacing * (numberOfButtons - 1)) / numberOfButtons));
            relativeLayout.Children.Add(fiveButton,
                                        Constraint.RelativeToView(twoButton, (parent, view) => view.X + view.Width + relativeLayoutHorizontalSpacing),
                                        Constraint.Constant(0),
                                        Constraint.RelativeToParent(parent => (parent.Width * screenUsePercentage - relativeLayoutHorizontalSpacing * (numberOfButtons - 1)) / numberOfButtons));

            Content = relativeLayout;

            Padding = new Thickness(0, 20);

            Title = $"Button Page on a {Device.Idiom}";
        }
    }

    public class App : Application
    {
        public App()
        {
            MainPage = new NavigationPage(new ButtonPage());
        }
    }

    public class StyledButton : Button
    {
        public StyledButton()
        {
            TextColor = Color.Black;
            HeightRequest = 60;
            BackgroundColor = Color.FromHex("2D7BF7");
            HorizontalOptions = LayoutOptions.FillAndExpand;
            VerticalOptions = LayoutOptions.CenterAndExpand;
        }
    }
}

Tablet Screen Shot

enter image description here

Phone Screen Shot

enter image description here

Upvotes: 10

Related Questions