-->

Show/hide a toolbar with slide animation in Sencha

2020-02-29 11:24发布

问题:

I have a toolbar docked to the top of the main viewport, and a panel with card layout below. The idea is to have the toolbar slide down from the top upon touching a button, and slide back up when dismissed. It should not overlay the content below it, everything below it should slide down as well to make room for the toolbar.

Firstly, how can I animate the toolbar show/hide with a slide transition? This is how I am showing/hiding the toolbar at the moment:

toggleMenu:function(){
    if (tkwine.views.menu.hidden){
        tkwine.views.menu.show();
    }else{
        tkwine.views.menu.hide();
    }

    //force the viewport to lay itself out again after toolbar hide/show 
    tkwine.viewport.doComponentLayout();
}

Secondly, this seems to work fine once, but after showing and hiding the toolbar once, the second time I attempt to show it, the toolbar overlays the content below instead of pushing it down. Why would this be?

This is my viewport if it might help debug the second issue:

tkwine.views.Viewport = Ext.extend(Ext.Panel, {
    id: 'viewport',
    layout: 'card',
    cardSwitchAnimation: 'slide',
    fullscreen: true,

    initComponent: function() {

        //put instances of cards into app.views namespace
        Ext.apply(tkwine.views, {
            menu: new tkwine.views.Menu(),
            home: new tkwine.views.Home(),
            trailsList: new tkwine.views.TrailsList(),
            trailDetail: new tkwine.views.TrailDetail(),
            createTrail: new tkwine.views.CreateTrail()
        });

        Ext.apply(tkwine.controllers, {
            historyManager: new tkwine.controllers.HistoryManager(tkwine.views.home)
        });

        Ext.apply(this, {
            dockedItems: [tkwine.views.menu],
            items: [
                tkwine.views.home,
                tkwine.views.trailsList,
                tkwine.views.trailDetail,
                tkwine.views.createTrail,
            ],
        });

        tkwine.views.Viewport.superclass.initComponent.apply(this, arguments);
    }
});

and my toolbar:

tkwine.views.Menu = Ext.extend(Ext.Toolbar, {
    hidden: true,
    overlay: false,
    layout: {
        pack: 'center',
    },

    defaults:{
        ui: 'plain',
        iconMask: true,
    },

    initComponent: function() {
        Ext.apply(this, {
            items:[
                {
                    iconCls: 'toolBarIconExplore',
                    handler:function(button, event){
                        Ext.dispatch({
                          controller: tkwine.controllers.controller,
                          action: 'showWineTrails',
                        });
                    }
                },
                {
                    xtype: 'spacer',
                },
                {
                    iconCls: 'toolBarIconCreate',
                    handler:function(button, event){
                        Ext.dispatch({
                          controller: tkwine.controllers.controller,
                          action: 'showCreateTrail',
                        });
                    }
                },
                {
                    xtype: 'spacer',
                },
                {
                    iconCls: 'toolBarIconItineraries',
                    handler:function(button, event){
                    }
                },
                {
                    xtype: 'spacer',
                },
                {
                    iconCls: 'toolBarIconCellar',
                    handler:function(button, event){
                    }
                },
                {
                    xtype: 'spacer',
                },
                {
                    iconCls: 'toolBarIconAction',
                    handler:function(button, event){
                    }
                }
            ],
        });

        tkwine.views.Menu.superclass.initComponent.apply(this, arguments);
    },

});

Ext.reg('menu', tkwine.views.Menu);

回答1:

Try adding listeners to your menu (warning, not tested):

show: function() {
    Ext.Anim.run(this, "slide", {
        direction: "down"
    });
},
hide: function() {
    Ext.Anim.run(this, "slide", {
        direction: "up"
    });
}

Your second problem is because of your conditional if (tkwine.views.menu.hidden). hidden is a config option, not a public property, so you can't access it directly. You need to use the getter:

if (tkwine.views.menu.isHidden())


回答2:

tkwine.views.menu.show({type: 'slide', direction: 'up'});
tkwine.views.menu.hide({type: 'slide', direction: 'down'});


回答3:

Code below works for me for something similar. However, I have much more than just this so I haven't tested the sliding all by itself. This method doesn't require to do doComponentLayout as it gracefully slides everything in the viewport. If it doesn't work, don't dismiss it but work on this as it does exactly what you want on my end.

tkwine.views.menu.show(Ext.Anim({
    easing: 'easeInOut',
    duration: 3000,
    autoClear: false,
    from: {
        opacity: 0,
        height: '0px'
    },
    to: {
        opacity: 1,
        height: tkwine.views.menu.getHeight() + 'px'
    }
}));

tkwine.views.menu.hide(Ext.Anim({
    easing: 'easeInOut',
    duration: 3000,
    autoClear: false,
    from: {
        opacity: 1,
        height: tkwine.views.menu.getHeight() + 'px'
    },
    to: {
        opacity: 0,
        height: '0px'
    }
}));