Adjust Width of Master on MasterDetailPage

BetaVIBetaVI USMember ✭✭

I am using the MasterDetailPage for the NavigationDrawer on Android. Implementing the functionality has gone perfectly, however the width is too large and i would like to adjust it.

I have tried to set the WidthRequest for the ListView CellTemplate, ListView, and the Master Property of the MasterDetailPage all to the same value, and i can see that the cells are at the right width but the slide out part is still too big.

public MainPage(Action loginFaliedCallback) { MenuPage menu = new MenuPage { Title = "Menu", WidthRequest = 250 }; menu.Menu.ItemSelected += (s, e) => NavigateTo(e.SelectedItem as MenuItem); Master = menu; Master.WidthRequest = 250; }
Any information would be greatly appreciated. Thanks in advance.

Best Answers

«1

Answers

  • BetaVIBetaVI USMember ✭✭

    Could this be accomplished with a custom renderer?

  • PedroLimaPedroLima US ✭✭
    edited June 2014

    This MenuPage is a ContentPage? The width used will be that of the View that is set to the Content property of ContentPage. Try setting a StackLayout to MenuPage.Content with a WidthRequest to see what happens.

    Can you post your MenuPage code?

  • BetaVIBetaVI USMember ✭✭

    Yes The MenuPage is a ContentPage. The View that i am setting for the Content of my MenuPage is a ListView with the WidthRequest set to 250

    public class MenuPage : ContentPage

    {
    
        public static List<MenuItem> MenuItems = new List<MenuItem>()
    
        {
    
            new HeaderMenuItem("menuitem"),
            new EnabledMenuItem("menuitem2"),
            new HeaderMenuItem("menuitem3"),
            new ShiftMenuItem("menuitem4",()=>true),
            new ShiftMenuItem("menuitem5",()=>true),
            new EnabledMenuItem("menuitem6"),
            new EnabledMenuItem("menuitem7"),
            new HeaderMenuItem("menuitem8"),
            new EnabledMenuItem("menuitem9"),
            new EnabledMenuItem("menuitem10"),
            new ShiftMenuItem("menuitem11",()=>true),
            new EnabledMenuItem("menuitem12"),
            new EnabledMenuItem("menuitem13")
        };
    
        public ListView Menu { get; set; }
    
        public MenuPage()
        {
            BackgroundColor = Color.FromHex("111111");
    
            Menu = new ListView()
            {
                ItemsSource = MenuItems,
                VerticalOptions = LayoutOptions.FillAndExpand,
                BackgroundColor = Color.Transparent,
                ItemTemplate = new DataTemplate(typeof(Cells.MenuItemCell)),
                HorizontalOptions = LayoutOptions.Start,
                WidthRequest = 250
            };
    
            Content = Menu;
        }
    }
    

    and here is the ItemTemplate


    public class MenuItemCell : ViewCell
    {

        public MenuItemCell()
        {
    
            StackLayout layout = new StackLayout() { Orientation = StackOrientation.Vertical, Padding = new Thickness(20, 10, 20, 10), Spacing = 10, WidthRequest = 250 };
            layout.SetBinding(View.BackgroundColorProperty, new Binding("IsHeader", BindingMode.OneWay, new HeaderConverter()));
            layout.SetBinding(View.IsEnabledProperty, "IsEnabled");
    
            Label label = new Label() { TextColor = Color.White };
            label.SetBinding(Label.TextProperty, "Title");
            layout.Children.Add(label);
    
            View = layout;
        }
    }
    

    Sorry about the code layout, for some reason it doesn't like me. As you can see i am settings the WidthRequest for the ItemTemplate, the ListView, and the Master on the MasterDetailPage, but the screen shot is the best that i can do.

    If i have to use a custom renderer, that is what i will do. However i wanted to know if there was a way to do this with out it.

    Thanks in advance

  • BetaVIBetaVI USMember ✭✭

    @PedroLima‌ sorry forgot to tag you with last response

  • PedroLimaPedroLima US ✭✭

    On your MenuPage class try setting the Content like this:

        Content = new StackLayout() {
                        WidthRequest = 250,
                        Padding = new Thickness(0),
                        Children = { Menu }
                    };
    

    If this doesn't work then probably one of your items in your ListView is trying to get more space than it should. To debug this, try setting different background colors for your various visual elements to find out which one is the culprit.

  • BetaVIBetaVI USMember ✭✭

    @PedroLima‌ Doing some further debugging, and changing background colors I think it is the ContentPage that i am setting to the Master of the MasterDetailPage. I even simplified the code to see where the issue was.

        public MainPage(IActivityIndicator indicator)
        {
            ListView lv = new ListView
            {
                ItemsSource = MenuItems,
                VerticalOptions = LayoutOptions.FillAndExpand,
                BackgroundColor = Color.Aqua,
                ItemTemplate = new DataTemplate(typeof(Cells.MenuItemCell)),
                HorizontalOptions = LayoutOptions.Start,
                WidthRequest = 250
            };
            lv.ItemSelected += async (s, e) =>
            {
                if (e.SelectedItem != null)
                {
                    MenuItem item = e.SelectedItem as MenuItem;
                    if (item.Title == "No Sale")
                        NavigateTo(item);
                    else
                        await StarPrinter.OpenCashDrawer();
                }
            };
    
            Master = new ContentPage { Title = "Menu", BackgroundColor = Color.Yellow, WidthRequest = 250, Content = lv };
        }
    

    In my attached screenshot you can see the ListView is the Aqua background, the item templates are transparent(except the DarkGray ones) and the ContentPage is the Yellow.

    I was trying to explicitly set the width for the page using a custom renderer but there is not much documentation on how to do that.

  • BetaVIBetaVI USMember ✭✭

    @JasonASmith‌ is this something that i could accomplish with a customrenderer?
    Would this be available in the future?

  • BetaVIBetaVI USMember ✭✭

    @RyanHatfield‌ Thanks for the reply. I will have to give that a try. I agree the menu is too large on the tablet, and have been trying figure out how to achieve this with a custom renderer. I will let you know how it works for me.

  • RyanHatfieldOldRyanHatfieldOld USMember, Insider ✭✭✭

    @BetaVI‌ if you use this code, it sets a static width, it'll look exactly that size on the tablet too (the way I think it should work by default, not a percentage)

    Granted this only works on create, but could be modified to work whenever the property changes (since that's a bindable property)

    here's a constructor to help you react to that property changing (it was hard for me to initially find code like this, so i figured i'd post it here)

    public MyMasterDetailRenderer()
            {
                this.Element.PropertyChanged += (sender, e) =>
                {
                    MyMasterDetailPage page = (MyMasterDetailPage)this.Element;
                    if(e.PropertyName == MyMasterDetailPage.DrawerWidthProperty.PropertyName)
                    {
                //do something awesome
                    }
    
                };
            }
    
  • RyanHatfieldOldRyanHatfieldOld USMember, Insider ✭✭✭

    Wait, why is

    Sorry you cant currently adjust the width of the MasterDetailPage

    from @JasonASmith‌ an acceptable answer?

  • BetaVIBetaVI USMember ✭✭

    It was at the time. Once I have a chance to try your code, I will gladly accept your comment as the accepted answer

  • BetaVIBetaVI USMember ✭✭

    @RyanHatfield‌ your solution worked perfectly, Thanks. That's the last time that i accept "can't do it" as an answer :-)

  • @RayanHatfield your solution was amazing but for iOS renderer there is no AddView method to override. What would be the way to do this on iOS?

  • RyanHatfieldOldRyanHatfieldOld USMember, Insider ✭✭✭

    I'd love to help @arashpourmoghaddam‌ but I don't have an iOS license so I have no idea. Maybe I should start a kickstarter for one ... haha I'll try and update this if I ever get a license.

  • Thanks a lot Ryan. Actually me too I do not have environment ready for iOS . However I am making an app that obviously need to support both android and iOS. So I was wondering how to tackle this issue for iOS. I wonder if anyone have even faced this issue of width in iOS or this issue only appear in android? If it only happens in android then I wont need to worry about renderer for iOS. Does anyone have had width issue with master page in iOS or event tested it before?

  • RyanHatfieldOldRyanHatfieldOld USMember, Insider ✭✭✭

    I've developed apps that compile for both, someone else has the iOS seat that I work with. It hasn't been an issue, either he made a custom render that was simple enough, or (more likely) it just wasn't an issue.

  • deckertron9000deckertron9000 USUniversity ✭✭✭

    @RyanHatfield.9864‌
    Is this still a working hack in Xamarin.Forms version 1.2.3.6257? I'm unable to override AddView in my inherited MasterDetailRenderer class.

  • RyanHatfieldOldRyanHatfieldOld USMember, Insider ✭✭✭

    @deckertron9000‌ Still works 100% for me, are you using the full render class? and what do you mean by you're unable to override AddView? MasterDetailRenderer actually extends from DrawerLayout in android, so you'll always be able to extend AddView. Now if @JasonASmith‌ or @ermau‌ would quit being greedy with IDrawerListener and expose the OnDrawerSlide events, I could fix the stupid Hamburger Menu icon not moving >:D ... but that's not for this post.

    Here's the render code again (the forums are wreaking havoc on my triple tic code markup notation

    public class MyMasterDetailRenderer : MasterDetailRenderer
    {
        bool firstDone;
        public override void AddView(View child)
        {
            if (firstDone)
            {
                MyMasterDetailPage page = (MyMasterDetailPage)this.Element;
                LayoutParams p = (LayoutParams)child.LayoutParameters;
                p.Width = page.DrawerWidth;
                base.AddView(child, p);
            }
            else
            {
                firstDone = true;
                base.AddView(child);
            }
        }
    
    }
    
  • RyanHatfieldOldRyanHatfieldOld USMember, Insider ✭✭✭

    I made a pull request to the Xamarin Forms Labs project on github, the request is here

    If you're having problems just pasting in the code, try using the normal tab tab convention and start typing AddView and let Visual/Xamarin Studio complete it for you.
    You might be having a namespace issue with View (Android.Views.View / Xamarin.Forms.View)

  • deckertron9000deckertron9000 USUniversity ✭✭✭

    @RyanHatfield‌
    I gave it another shot this morning and Resharper autocompleted it immediately for me. Yesterday it was saying there was no suitable method for override (which in retrospect was probably due to the namespace collision you mentioned). Thanks a bunch!

  • MichaelEngelmannMichaelEngelmann FRMember ✭✭
    edited December 2014

    @RayanHatfield Very cool :smile: saved me a lot of time.
    I suggest adding a constructor to the ExtendedMasterDetailPage in order to make it more fool proof :wink: :

      public ExtendedMasterDetailPage()
      {
         // Setting default value, 
         // otherwise if value is not set in implementation the menu won’t obviously not be visible as its width=0
         DrawerWidth = 200;
      }
    
  • VinayakGHVinayakGH USMember

    Hey Hii... I am trying for master view to be displayed on the right side... what are the options available for that?

    As of now the main page looks like this...I want to change the master view orientation towards Right..

  • Bartosz.9096Bartosz.9096 USMember

    Hi,

    I cannot get it working for me. I set DrawerWidth property and a drawer itself has desired width however its content is still positioned to previous (hardcoded by Xamarin) value. See screenshot below for a reference. The label and button are being cut. I guess the container in the drawer hadn't its size updated somehow. The code from the custom renderer is called. I am using Xamarin.Forms 1.4.2.6359 and Xamarin.Android.Support.v4 21.0.3.0.

    Here is my code:

        public App ()
        {
            var mdp = new MyMasterDetailPage ();
            mdp.DrawerWidth = 100;
            mdp.Title = "MainPage";
            mdp.Master = new ContentPage {                              
                                Title="Master",
                                BackgroundColor = Color.Yellow,
                                Content = new StackLayout {
                                    VerticalOptions = LayoutOptions.Center,
                                    Children = {
                                        new Label {
                                            XAlign = TextAlignment.Center,
                                            Text = "Welcome to Xamarin Forms!"
                                        },
                                        new Button{Text="Test 1 button"}
                                    }
                                }
                            };
            mdp.Detail = new NavigationPage (new ContentPage {
                BackgroundColor = Color.Red,
                Content = new StackLayout (){ BackgroundColor = Color.Aqua }
            });
    
            MainPage = mdp;
    
        }
    

    And implementation of MyMasterDetailPage is just the code pasted here by @RyanHatfield‌.

  • MaruuMaruu USMember

    @esam: great solution, saved me a lot of time!!!

  • Abhijeet_SuryaAbhijeet_Surya USMember ✭✭✭

    @RyanHatfieldOld

    Thanks a lot, your solutions works perfectly for android.

  • SmartyPSmartyP USInsider, University ✭✭

    @RyanHatfieldOld

    Your custom renderer worked great for me. One minor point - it may be necessary to specify Android.Views.View as the type for the 'child' parameter in the AddView() method override as there is a View class in both Xamarin.Forms and Xamarin.Forms.Platform.Android. I only ran into this because I didn't use a custom subclass based on MasterDetailPage, but just changed the renderer for MasterDetailPage directly.

    Thanks so much for your post!

  • OlivierAnsquerOlivierAnsquer FRUniversity ✭✭

    Solutions in this thread don't work for me on Android tablet in landscape mode with a fixed master panel.
    I have created a suggestion :

    [http://xamarin.uservoice.com/forums/258559-xamarin-forms-suggestions/suggestions/11516232-add-a-property-to-set-master-panel-width-in-a-mast]

  • GaganSinghGaganSingh USUniversity ✭✭✭
    edited March 2016

    I can't get this to work. Could someone please post a working sample project?
    By the way, Im using the Hanselman.Forms sample. So im not sure if its done the same way.

    Thank you!

  • RaymondKellyRaymondKelly USMember ✭✭✭

    Is there really still no way to adjust this natively with the MasterDetail page? Seems crazy this does not auto adjust to the content of the menu items or at least be setable! And it appears that unenven rows is set for android causing the overly large icons in the menu. It just looks awful! How can this have been this way for so long?? @RyanHatfieldOld @TheRealJasonSmith

  • ErkanGozukucukErkanGozukucuk USMember ✭✭

    For shrink master page's width, you shuld set master page's "padding" property.

  • JoeGloryJoeGlory MYMember

    Hai Joe, here I running into the "Object not set to references" error when using the Custom Master Detail Page.

  • MCvelMCvel USMember ✭✭✭

    old thread, but same issue,

    does anybody knows or can point me in the right direction to change the Width of the MasterDetailPage (menu) in iOS?
    the custom render solution proposed here worked perfect in Android,

    thank you all!

  • @JoeGlory hi
    i am also having the same issue, do you got any solution for this...
    if have, please share it to me too,
    thank you

  • RadoslavYordanovRadoslavYordanov USMember
    edited November 2016

    To adjust the width of the MasterDetailPage in the iOS project create this file:
    https://gist.github.com/radoslavyordanov/e62f673e45983ec0ae56cd6b336f68ff

    To set the width of the master view in the method:
    void LayoutChildren(bool animated)
    Use:
    masterFrame.Width = value;

    Currently it will expand to the full screen size of the device.

  • ManishJain.1426ManishJain.1426 USUniversity ✭✭

    @RyanHatfieldOld - Custom renderer code no more works on recent version of Xamarin Forms version="2.3.2.127"

  • RadoslavYordanovRadoslavYordanov USMember
    edited November 2016

    @ManishJain.1426,

    Currently I'm using the same version of Xamarin Forms and I can confirm that it works.

Sign In or Register to comment.