Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling different orientations while developing Windows 8 Store applications

I've been writing Android applications for some years and now I'm developing a Windows Store/Windows 8 application.

I'm very confused about how to write different screen layouts for landscape and portrait orientations.

In Android, all we must do is to write 2 layouts, one for portrait and another for landscape, following some name conventions for the file names, and when we rotate the device the platform changes the screen layout automatically.

I've been googling for some solution to do the same in my Windows 8 application, and all I've found was a solution using Visual State Groups and Visual States, putting in the same XAML some modifications that happen to our widgets when we rotate the device.

For example, to make a textblock change its position when I rotate the device to portrait orientation:

<VisualState x:Name="FullScreenPortrait" >
    <Storyboard>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.ColumnSpan)" Storyboard.TargetName="GridViewTitle">
            <DiscreteObjectKeyFrame KeyTime="0">
                <DiscreteObjectKeyFrame.Value>
                    <x:Int32>3</x:Int32>
                </DiscreteObjectKeyFrame.Value>
            </DiscreteObjectKeyFrame>
        </ObjectAnimationUsingKeyFrames>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Margin)" Storyboard.TargetName="GridViewTitle">
            <DiscreteObjectKeyFrame KeyTime="0">
                <DiscreteObjectKeyFrame.Value>
                    <Thickness>0,10,10,807</Thickness>
                </DiscreteObjectKeyFrame.Value>
            </DiscreteObjectKeyFrame>
        </ObjectAnimationUsingKeyFrames>
    </Storyboard>
</VisualState>

It doesn't look very clean and simple to me, and even doing that using the Visual Studio's approach of dragging and dropping widgets to generate code I have the impression that there must be some easier and cleaner solution than what I'm doing.

So my question is: is there any easier solution to write XAML layouts for each orientation or am I going the right, but hard way?

Thanks!

like image 745
Esdras Beleza Avatar asked Oct 22 '22 10:10

Esdras Beleza


2 Answers

One way to handle different orientations is to create two Grid elements with their children inside and change Grids' visibilities according to orientation.

To detect orientation changes, you can also use SimpleOrientation sensor like the code below:

    public sealed partial class MainPage : Page
    {
        private SimpleOrientationSensor _oSensor;

        public MainPage()
        {
            this.InitializeComponent();

            _oSensor = SimpleOrientationSensor.GetDefault();

        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            if (_oSensor != null)
                _oSensor.OrientationChanged += (s, a) =>
                {
                    Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
                    {
                        switch (a.Orientation)
                        {
                            case SimpleOrientation.NotRotated:
                            case SimpleOrientation.Rotated180DegreesCounterclockwise:
                                currentOrientation.Text = "Landscape";
                                break;
                            case SimpleOrientation.Rotated270DegreesCounterclockwise:
                            case SimpleOrientation.Rotated90DegreesCounterclockwise:
                                currentOrientation.Text = "Portrait";
                                break;
                            default:
                                currentOrientation.Text = "N/A";
                                break;
                        }
                    });
                };
        }

    }

Or the easiest way is to handle SizeChanged event like the code below:

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();

        mainGrid.SizeChanged += mainGrid_SizeChanged;
    }

    void mainGrid_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        if (mainGrid.ActualHeight > mainGrid.ActualWidth)
            currentOrientation.Text = "Portrait";
        else
            currentOrientation.Text = "Landscape";
    }

}

Hope this helps!

like image 93
kimsk Avatar answered Jan 02 '23 20:01

kimsk


Esdras - you're not wrong, there should probably be an easier way but the only other option is the software Expression Blend. And I will concede there isa learning curve to get up and running.

Also for orientation changes written in Xaml, the parent control must drive from a control that can be extend (not internal sealed) and must be layout aware. So for instance if you put a textbox on a layout aware page its orientation will change, but if you put a grid on the Layout aware page and a text box in the grid... The default behavior is that the grid will respond but the textbox will not.

You may also notice that although it's messy and every control needs a control modifier like you ve provided for each element that should respond to orientation change...The benefit is that it requires no native code to define the state or transition and so designers are able to use the xml look alike called xaml to describe the changes in the view whether it be orientation or the states of other controls.

If you can get your hands on the program Expression Blend it was made for that purpose.

like image 45
Zack Weiner Avatar answered Jan 02 '23 19:01

Zack Weiner