zoukankan      html  css  js  c++  java
  • sencha touch 扩展官方NavigationView 灵活添加按钮组,导航栏,自由隐藏返回按钮(2014-5-15)

    扩展视频讲解:http://www.cnblogs.com/mlzs/p/3652094.html
    官方NavigationView详解:http://www.cnblogs.com/mlzs/p/3550011.html
    官方Container详解:http://www.cnblogs.com/mlzs/p/3548720.html

    示例源码参见:https://bitbucket.org/moLangZaiShi/demo
    注:扩展源码以示例为准

    扩展源码:

      1 Ext.define('ux.navigation.View', {
      2     extend: 'Ext.Container',
      3     alternateClassName: 'ux.NavigationView',
      4     xtype: 'uxNavigationView',
      5     requires: ['ux.navigation.Bar'],
      6 
      7     config: {
      8         baseCls: Ext.baseCSSPrefix + 'navigationview',
      9         navigationBar: {
     10             docked: 'top',
     11             cls: 'navigationBar'
     12         },
     13         defaultBackButtonText: 'Back',
     14         useTitleForBackButtonText: false,
     15         layout: {
     16             type: 'card',
     17             animation: {
     18                 duration: 300,
     19                 easing: 'ease-out',
     20                 type: 'slide',
     21                 direction: 'left'
     22             }
     23         },
     24         index: null,
     25         //不推荐使用
     26         menu: null
     27     },
     28 
     29     platformConfig: [{
     30         theme: ['Blackberry'],
     31         navigationBar: {
     32             splitNavigation: true
     33         }
     34     }],
     35 
     36     // @private
     37     initialize: function () {
     38         var me = this,
     39         navBar = me.getNavigationBar();
     40 
     41         //监听导航栏返回按钮
     42         if (navBar) {
     43             navBar.on({
     44                 back: me.onBackButtonTap,
     45                 scope: me
     46             });
     47 
     48             me.relayEvents(navBar, 'rightbuttontap');
     49 
     50             me.relayEvents(me, {
     51                 add: 'push',
     52                 remove: 'pop'
     53             });
     54         }
     55         //<debug>
     56         var layout = me.getLayout();
     57         if (layout && !layout.isCard) {
     58             Ext.Logger.error('The base layout for a NavigationView must always be a Card Layout');
     59         }
     60         //</debug>
     61     },
     62 
     63     /**
     64      * @private
     65      */
     66     applyLayout: function (config) {
     67         config = config || {};
     68 
     69         return config;
     70     },
     71     //更新标题
     72     setTitle: function (text) {
     73         var me = this,
     74         nav = me.getNavigationBar();
     75         nav.setTitle(text);
     76         nav.backButtonStack[nav.backButtonStack.length - 1].title = text;
     77     },
     78     /*创建其他导航栏*/
     79     applyMenu: function (newItem) {
     80         if (!newItem) {
     81             return false;
     82         }
     83         var me = this;
     84         return me.factoryItem(newItem);
     85     },
     86     /*更新其他导航栏*/
     87     updateMenu: function (newItem, oldItem) {
     88         if (oldItem) {
     89             //console.log('oldItem:', oldItem.getItemId());
     90             this.remove(oldItem);
     91         }
     92         if (newItem) {
     93             //console.log('newItem:', newItem.getItemId());
     94             this.add(newItem);
     95         }
     96     },
     97     //更新index
     98     updateIndex: function (newItem, oldItem) {
     99         var me = this,
    100         animation = this.getLayout().getAnimation(),
    101         event = {
    102             scope: me,
    103             animationend: 'clearItem'
    104         };
    105         //添加监听
    106         if (oldItem) {
    107             //移除动画结束监听
    108             animation.un(event);
    109         }
    110         if (Ext.isNumber(newItem)) {
    111             //添加动画结束监听
    112             animation.on(event);
    113         }
    114     },
    115     //根据index清理多余的项
    116     clearItem: function () {
    117         var me = this,
    118         innerItems = me.getInnerItems(),
    119         length = innerItems.length,
    120         index = me.getIndex();
    121         count = length - index - 1;
    122         toRemove = innerItems.splice(me.getIndex(), count);
    123         //移除子项
    124         for (i = 0; i < toRemove.length; i++) {
    125             me.remove(toRemove[i]);
    126         }
    127     },
    128     /**
    129      * @private
    130      * 点击返回按钮
    131      */
    132     onBackButtonTap: function () {
    133         this.pop();
    134         this.fireEvent('back', this);
    135     },
    136 
    137     push: function (xtype, params) {
    138         var me = this,
    139         view = me.down('#' + xtype);
    140         if (!view) {
    141             params = params || {};
    142             params.itemId = xtype;
    143             view = Ext.create(xtype, params);
    144             me.add(view);
    145         } else if (view != me.getActiveItem()) {
    146             me.pop(xtype);
    147         }
    148         return view;
    149     },
    150     /*移除当前激活项然后添加新的项xtype为null则只移除*/
    151     popAndPush: function (xtype, params) {
    152         this.pop(null, xtype);
    153         if (xtype) {
    154             this.push(xtype, params);
    155         }
    156     },
    157     /**
    158       * 不填写参数时,移除当前项,返回到上一项
    159       * 如果参数是数字,则从最后一项开始移除指定数目的项
    160       * 如果参数是string,则移除指定类型的项
    161       * 如果参数是项,则移除传入的项
    162       * 不论参数如何,都会保留一个活动项
    163       * @return {Ext.Component} 当前活动项
    164       */
    165     pop: function (count, hide) {
    166         if (this.beforePop(count)) {
    167             return this.doPop(hide);
    168         }
    169     },
    170 
    171     /*删除指定项*/
    172     beforePop: function (count) {
    173         var me = this,
    174         innerItems = me.getInnerItems();
    175         if (Ext.isString(count) || Ext.isObject(count)) {
    176             var last = innerItems.length - 1,
    177             i;
    178 
    179             for (i = last; i >= 0; i--) {
    180                 if ((Ext.isString(count) && Ext.ComponentQuery.is(innerItems[i], count)) || (Ext.isObject(count) && count == innerItems[i])) {
    181                     count = last - i;
    182                     break;
    183                 }
    184             }
    185 
    186             if (!Ext.isNumber(count)) {
    187                 return false;
    188             }
    189         }
    190 
    191         var ln = innerItems.length,
    192         toRemove;
    193         //default to 1 pop
    194         if (!Ext.isNumber(count) || count < 1) {
    195             count = 1;
    196         }
    197 
    198         //check if we are trying to remove more items than we have
    199         count = Math.min(count, ln - 1);
    200 
    201         if (count) {
    202             //we need to reset the backButtonStack in the navigation bar
    203             me.getNavigationBar().beforePop(count);
    204 
    205             //get the items we need to remove from the view and remove theme
    206             toRemove = innerItems.splice(-count, count - 1);
    207             for (i = 0; i < toRemove.length; i++) {
    208                 this.remove(toRemove[i]);
    209             }
    210 
    211             return true;
    212         }
    213 
    214         return false;
    215     },
    216 
    217     /**
    218      * @private
    219      */
    220     doPop: function (hide) {
    221         var me = this,
    222         innerItems = this.getInnerItems(),
    223         item = innerItems[innerItems.length - 1];
    224         if (hide) {
    225             item.hide();
    226         }
    227         //set the new active item to be the new last item of the stack
    228         me.remove(item);
    229 
    230         // Hide the backButton
    231         if (innerItems.length < 3 && this.$backButton) {
    232             this.$backButton.hide();
    233         }
    234 
    235         // Update the title container
    236         if (this.$titleContainer) {
    237             //<debug>
    238             if (!this.$titleContainer.setTitle) {
    239                 Ext.Logger.error('You have selected to display a title in a component that does not 
    240                     support titles in NavigationView. Please remove the `title` configuration from your 
    241                     NavigationView item, or change it to a component that has a `setTitle` method.');
    242             }
    243             //</debug>
    244             var item = innerItems[innerItems.length - 2];
    245             this.$titleContainer.setTitle((item.getTitle) ? item.getTitle() : item.config.title);
    246         }
    247 
    248         return this.getActiveItem();
    249     },
    250 
    251     /**
    252      * 返回上一项
    253      * @return {Mixed} The previous view
    254      */
    255     getPreviousItem: function () {
    256         var innerItems = this.getInnerItems();
    257         return innerItems[innerItems.length - 2];
    258     },
    259 
    260     /**
    261      * Updates the backbutton text accordingly in the {@link #navigationBar}
    262      * @private
    263      */
    264     updateUseTitleForBackButtonText: function (useTitleForBackButtonText) {
    265         var navigationBar = this.getNavigationBar();
    266         if (navigationBar) {
    267             navigationBar.setUseTitleForBackButtonText(useTitleForBackButtonText);
    268         }
    269     },
    270 
    271     /**
    272      * Updates the backbutton text accordingly in the {@link #navigationBar}
    273      * @private
    274      */
    275     updateDefaultBackButtonText: function (defaultBackButtonText) {
    276         var navigationBar = this.getNavigationBar();
    277         if (navigationBar) {
    278             navigationBar.setDefaultBackButtonText(defaultBackButtonText);
    279         }
    280     },
    281 
    282     // @private
    283     applyNavigationBar: function (config) {
    284         if (!config) {
    285             config = {
    286                 hidden: true,
    287                 docked: 'top'
    288             };
    289         }
    290 
    291         if (config.title) {
    292             delete config.title;
    293             //<debug>
    294             Ext.Logger.warn("Ext.navigation.View: The 'navigationBar' configuration does not accept a 'title' property. You " + "set the title of the navigationBar by giving this navigation view's children a 'title' property.");
    295             //</debug>
    296         }
    297 
    298         config.view = this;
    299         config.useTitleForBackButtonText = this.getUseTitleForBackButtonText();
    300         //是否分离导航按钮和标题栏
    301         if (config.splitNavigation) {
    302             this.$titleContainer = this.add({
    303                 docked: 'top',
    304                 xtype: 'titlebar',
    305                 ui: 'light',
    306                 title: this.$currentTitle || ''
    307             });
    308 
    309             var containerConfig = (config.splitNavigation === true) ? {} : config.splitNavigation;
    310 
    311             this.$backButtonContainer = this.add(Ext.apply({
    312                 xtype: 'toolbar',
    313                 docked: 'bottom'
    314             },
    315             containerConfig));
    316 
    317             this.$backButton = this.$backButtonContainer.add({
    318                 xtype: 'button',
    319                 text: 'Back',
    320                 hidden: true,
    321                 ui: 'back'
    322             });
    323 
    324             this.$backButton.on({
    325                 scope: this,
    326                 tap: this.onBackButtonTap
    327             });
    328 
    329             config = {
    330                 hidden: true,
    331                 docked: 'top'
    332             };
    333         }
    334 
    335         return Ext.factory(config, ux.navigation.Bar, this.getNavigationBar());
    336     },
    337 
    338     // @private
    339     updateNavigationBar: function (newNavigationBar, oldNavigationBar) {
    340         if (oldNavigationBar) {
    341             this.remove(oldNavigationBar, true);
    342         }
    343 
    344         if (newNavigationBar) {
    345             this.add(newNavigationBar);
    346         }
    347     },
    348 
    349     /**
    350      * @private
    351      */
    352     applyActiveItem: function (activeItem, currentActiveItem) {
    353         var me = this,
    354         innerItems = me.getInnerItems();
    355 
    356         // 确保项目已初始化
    357         me.getItems();
    358 
    359         // 如果没有初始化, 将最后的子项激活
    360         if (!me.initialized) {
    361             activeItem = innerItems.length - 1;
    362         }
    363         //console.log(this.getItems().keys);
    364         return this.callParent([activeItem, currentActiveItem]);
    365     },
    366     /*pop时反转切换动画*/
    367     doResetActiveItem: function (innerIndex) {
    368         var me = this,
    369         innerItems = me.getInnerItems(),
    370         animation = me.getLayout().getAnimation();
    371 
    372         if (innerIndex > 0) {
    373             if (animation && animation.isAnimation) {
    374                 animation.setReverse(true);
    375             }
    376             me.setActiveItem(innerIndex - 1);
    377             me.getNavigationBar().onViewRemove(me, innerItems[innerIndex], innerIndex);
    378         }
    379     },
    380 
    381     /**
    382      * 移除子项,调用remove方法后自动执行
    383      * @private
    384      */
    385     doRemove: function () {
    386         var animation = this.getLayout().getAnimation();
    387 
    388         if (animation && animation.isAnimation) {
    389             animation.setReverse(false);
    390         }
    391 
    392         this.callParent(arguments);
    393     },
    394 
    395     onActivate: function (view) {
    396         //更新menu
    397         this.setMenu((view.getMenu) ? view.getMenu() : view.config.Menu);
    398     },
    399     /**
    400      * 添加子项,调用add方法后自动执行
    401      * @private
    402      */
    403     onItemAdd: function (item, index) {
    404 
    405         // 检测title配置
    406         if (item && item.getDocked() && item.config.title === true) {
    407             this.$titleContainer = item;
    408         }
    409         if (item.isInnerItem()) {
    410             //添加监听,监听视图激活事件
    411             item.on({
    412                 scope: this,
    413                 activate: 'onActivate'
    414             });
    415         }
    416         this.doItemLayoutAdd(item, index);
    417 
    418         var navigaitonBar = this.getInitialConfig().navigationBar;
    419 
    420         if (!this.isItemsInitializing && item.isInnerItem()) {
    421 
    422             this.setActiveItem(item);
    423             // 更新navigationBar
    424             if (navigaitonBar) {
    425                 //强制排序
    426                 this.setIndex((item.getIndex) ? item.getIndex() : item.config.index);
    427 
    428                 this.getNavigationBar().onViewAdd(this, item, index);
    429             }
    430 
    431             // 更新返回按钮
    432             if (this.$backButtonContainer) {
    433                 this.$backButton.show();
    434             }
    435         }
    436 
    437         if (item && item.isInnerItem()) {
    438             // 更新标题
    439             //console.log('更新标题', item);
    440             this.updateTitleContainerTitle((item.getTitle) ? item.getTitle() : item.config.title);
    441         }
    442 
    443         if (this.initialized) {
    444             this.fireEvent('add', this, item, index);
    445         }
    446     },
    447 
    448     /**
    449      * @private
    450      * 更新titleContainer的标题,如果存在
    451      */
    452     updateTitleContainerTitle: function (title) {
    453         if (this.$titleContainer) {
    454             //<debug>
    455             if (!this.$titleContainer.setTitle) {
    456                 Ext.Logger.error('You have selected to display a title in a component that does not 
    457                     support titles in NavigationView. Please remove the `title` configuration from your 
    458                     NavigationView item, or change it to a component that has a `setTitle` method.');
    459             }
    460             //</debug>
    461             this.$titleContainer.setTitle(title);
    462         } else {
    463             this.$currentTitle = title;
    464         }
    465     },
    466 
    467     /**
    468      * 移除第一项和最后项之间的所有项(包括最后项)
    469      * @return {Ext.Component} The view that is now active
    470      */
    471     reset: function () {
    472         return this.pop(this.getInnerItems().length);
    473     }
    474 });
      1 /**
      2  * This component is used in {@link Ext.navigation.View} to control animations in the toolbar. You should never need to
      3  * interact with the component directly, unless you are subclassing it.
      4  * @private
      5  * @author Robert Dougan <rob@sencha.com>
      6  */
      7 Ext.define('ux.navigation.Bar', {
      8     extend: 'Ext.TitleBar',
      9 
     10     requires: ['Ext.Button', 'Ext.Spacer'],
     11 
     12     // @private
     13     isToolbar: true,
     14 
     15     config: {
     16         /**
     17          * @cfg
     18          * @inheritdoc
     19          */
     20         baseCls: Ext.baseCSSPrefix + 'toolbar',
     21         /**
     22          * @cfg {String} ui
     23          * Style options for Toolbar. Either 'light' or 'dark'.
     24          * @accessor
     25          */
     26         ui: 'dark',
     27 
     28         /**
     29          * @cfg {String} title
     30          * The title of the toolbar. You should NEVER set this, it is used internally. You set the title of the
     31          * navigation bar by giving a navigation views children a title configuration.
     32          * @private
     33          * @accessor
     34          */
     35         title: null,
     36 
     37         /**
     38          * @cfg
     39          * @hide
     40          * @accessor
     41          */
     42         defaultType: 'button',
     43 
     44         /**
     45          * @cfg
     46          * @ignore
     47          * @accessor
     48          */
     49         layout: {
     50             type: 'hbox'
     51         },
     52 
     53         /**
     54          * @cfg {Array/Object} items The child items to add to this NavigationBar. The {@link #cfg-defaultType} of
     55          * a NavigationBar is {@link Ext.Button}, so you do not need to specify an `xtype` if you are adding
     56          * buttons.
     57          *
     58          * You can also give items a `align` configuration which will align the item to the `left` or `right` of
     59          * the NavigationBar.
     60          * @hide
     61          * @accessor
     62          */
     63 
     64         /**
     65          * @cfg {String} defaultBackButtonText
     66          * The text to be displayed on the back button if:
     67          * a) The previous view does not have a title
     68          * b) The {@link #useTitleForBackButtonText} configuration is true.
     69          * @private
     70          * @accessor
     71          */
     72         defaultBackButtonText: '返回',
     73 
     74         /**
     75          * @cfg {Object} animation
     76          * @private
     77          * @accessor
     78          */
     79         animation: {
     80             duration: 300
     81         },
     82 
     83         /**
     84          * @cfg {Boolean} useTitleForBackButtonText
     85          * Set to false if you always want to display the {@link #defaultBackButtonText} as the text
     86          * on the back button. True if you want to use the previous views title.
     87          * @private
     88          * @accessor
     89          */
     90         useTitleForBackButtonText: null,
     91 
     92         /**
     93          * @cfg {Ext.navigation.View} view A reference to the navigation view this bar is linked to.
     94          * @private
     95          * @accessor
     96          */
     97         view: null,
     98 
     99         /**
    100          * @cfg {Boolean} androidAnimation Optionally enable CSS transforms on Android 2
    101          * for NavigationBar animations.  Note that this may cause flickering if the
    102          * NavigationBar is hidden.
    103          * @accessor
    104          */
    105         android2Transforms: false,
    106 
    107         /**
    108          * @cfg {Ext.Button/Object} backButton The configuration for the back button
    109          * @private
    110          * @accessor
    111          */
    112         backButton: {
    113             align: 'left',
    114             ui: 'back',
    115             hidden: true
    116         },
    117         /*导航栏临时控件组,在子项中配置*/
    118         tmpItems: null,
    119         /*导航栏临时cls,在子项中配置*/
    120         tmpCls: null,
    121         /*是否隐藏返回按钮,在子项中配置*/
    122         backHide: true
    123     },
    124 
    125     platformConfig: [{
    126         theme: ['Blackberry'],
    127         animation: false
    128     }],
    129 
    130     /**
    131      * @event back
    132      * Fires when the back button was tapped.
    133      * @param {Ext.navigation.Bar} this This bar
    134      */
    135 
    136     constructor: function (config) {
    137         config = config || {};
    138 
    139         if (!config.items) {
    140             config.items = [];
    141         }
    142 
    143         this.backButtonStack = [];
    144         this.activeAnimations = [];
    145 
    146         this.callParent([config]);
    147     },
    148     /*创建导航栏临时控件组*/
    149     applyTmpItems: function (newItems) {
    150         if (!newItems) return false;
    151         var me = this,
    152         navItems = [],
    153         i,
    154         ln;
    155         newItems = Ext.Array.from(newItems);
    156         for (i = 0, ln = newItems.length; i < ln; i++) {
    157             var item = newItems[i],
    158             fire = item.fire,
    159             btn = me.factoryItem(item);
    160             if (fire) {
    161                 btn.on({
    162                     tap: 'onTmpItemTap',
    163                     scope: me
    164                 });
    165             }
    166             navItems.push(me.factoryItem(btn));
    167         }
    168         return navItems;
    169     },
    170     //临时控件被点击时
    171     onTmpItemTap: function (t) {
    172         var me = this,
    173         view = me.getView().getActiveItem(),
    174         fire = t.fire;
    175         view.fireAction(fire, [me, view, t], 'do' + fire);
    176     },
    177     /*更新导航栏临时控件组*/
    178     updateTmpItems: function (newItem, oldItem) {
    179         if (oldItem) {
    180             var i, ln;
    181             for (i = 0, ln = oldItem.length; i < ln; i++) {
    182                 this.remove(oldItem[i]);
    183             }
    184         }
    185         if (newItem) {
    186             this.add(newItem);
    187         }
    188     },
    189     /*更新导航栏临时cls*/
    190     updateTmpCls: function (newItem, oldItem) {
    191         if (oldItem) {
    192             this.removeCls(oldItem);
    193         }
    194         if (newItem) {
    195             this.addCls(newItem);
    196         }
    197     },
    198     /**
    199      * @private
    200      */
    201     applyBackButton: function (config) {
    202         return Ext.factory(config, Ext.Button, this.getBackButton());
    203     },
    204 
    205     /**
    206      * @private
    207      */
    208     updateBackButton: function (newBackButton, oldBackButton) {
    209         if (oldBackButton) {
    210             this.remove(oldBackButton);
    211         }
    212 
    213         if (newBackButton) {
    214             this.add(newBackButton);
    215 
    216             newBackButton.on({
    217                 scope: this,
    218                 tap: this.onBackButtonTap
    219             });
    220         }
    221     },
    222 
    223     onBackButtonTap: function () {
    224         this.fireEvent('back', this);
    225     },
    226 
    227     /**
    228      * @private
    229      */
    230     updateView: function (newView) {
    231         var me = this,
    232         backButton = me.getBackButton(),
    233         innerItems,
    234         i,
    235         backButtonText,
    236         item,
    237         title,
    238         titleText,
    239         bar;
    240 
    241         me.getItems();
    242 
    243         if (newView) {
    244             //update the back button stack with the current inner items of the view
    245             innerItems = newView.getInnerItems();
    246             for (i = 0; i < innerItems.length; i++) {
    247                 item = innerItems[i];
    248                 title = (item.getTitle) ? item.getTitle() : item.config.title;
    249                 bar = (item.getBar) ? item.getBar() : item.config.bar;
    250 
    251                 me.backButtonStack.push({
    252                     title: title || '&nbsp;',
    253                     bar: bar
    254                 });
    255             }
    256             titleText = me.getTitleText();
    257 
    258             if (titleText === undefined) {
    259                 titleText = '';
    260             }
    261 
    262             me.setTitle(titleText);
    263 
    264             backButtonText = me.getBackButtonText();
    265             if (backButtonText) {
    266                 backButton.setText(backButtonText);
    267                 backButton.show();
    268             }
    269             //更新bar
    270             me.updateBar();
    271         }
    272     },
    273 
    274     /**
    275      * @private
    276      */
    277     onViewAdd: function (view, item) {
    278         var me = this,
    279         backButtonStack = me.backButtonStack,
    280         hasPrevious, title, bar;
    281 
    282         me.endAnimation();
    283 
    284         title = (item.getTitle) ? item.getTitle() : item.config.title;
    285         bar = (item.getBar) ? item.getBar() : item.config.bar;
    286         //移除额外的历史记录
    287         var index = (item.getIndex) ? item.getIndex() : item.config.index;
    288         if (Ext.isNumber(index)) {
    289             var length = view.getInnerItems().length,
    290             count = length - index;
    291             me.beforePop(count);
    292         }
    293         backButtonStack.push({
    294             title: title || '&nbsp;',
    295             bar: bar
    296         });
    297 
    298         hasPrevious = backButtonStack.length > 1;
    299         me.doChangeView(view, hasPrevious, false);
    300     },
    301 
    302     /**
    303      * @private
    304      */
    305     onViewRemove: function (view) {
    306         var me = this,
    307         backButtonStack = me.backButtonStack,
    308         hasPrevious;
    309 
    310         me.endAnimation();
    311         backButtonStack.pop();
    312         hasPrevious = backButtonStack.length > 1;
    313 
    314         me.doChangeView(view, hasPrevious, true);
    315     },
    316 
    317     /**
    318      * @private
    319      */
    320     doChangeView: function (view, hasPrevious, reverse) {
    321         var me = this,
    322         leftBox = me.leftBox,
    323         leftBoxElement = leftBox.element,
    324         titleComponent = me.titleComponent,
    325         titleElement = titleComponent.element,
    326         backButton = me.getBackButton(),
    327         titleText = me.getTitleText(),
    328         backButtonText = me.getBackButtonText(),
    329         animation = me.getAnimation() && view.getLayout().getAnimation(),
    330         animated = animation && animation.isAnimation && view.isPainted(),
    331         properties,
    332         leftGhost,
    333         titleGhost,
    334         leftProps,
    335         titleProps;
    336 
    337         if (animated) {
    338             leftGhost = me.createProxy(leftBox.element);
    339             leftBoxElement.setStyle('opacity', '0');
    340             backButton.setText(backButtonText);
    341             backButton[hasPrevious ? 'show' : 'hide']();
    342 
    343             titleGhost = me.createProxy(titleComponent.element.getParent());
    344             titleElement.setStyle('opacity', '0');
    345             me.setTitle(titleText);
    346 
    347             properties = me.measureView(leftGhost, titleGhost, reverse);
    348             leftProps = properties.left;
    349             titleProps = properties.title;
    350 
    351             me.isAnimating = true;
    352             me.animate(leftBoxElement, leftProps.element);
    353             me.animate(titleElement, titleProps.element,
    354             function () {
    355                 titleElement.setLeft(properties.titleLeft);
    356                 me.isAnimating = false;
    357                 me.refreshTitlePosition();
    358             });
    359 
    360             if (Ext.browser.is.AndroidStock2 && !this.getAndroid2Transforms()) {
    361                 leftGhost.ghost.destroy();
    362                 titleGhost.ghost.destroy();
    363             } else {
    364                 me.animate(leftGhost.ghost, leftProps.ghost);
    365                 me.animate(titleGhost.ghost, titleProps.ghost,
    366                 function () {
    367                     leftGhost.ghost.destroy();
    368                     titleGhost.ghost.destroy();
    369                 });
    370             }
    371 
    372         } else {
    373             if (hasPrevious) {
    374                 backButton.setText(backButtonText);
    375                 backButton.show();
    376             } else {
    377                 backButton.hide();
    378             }
    379             me.setTitle(titleText);
    380         }
    381         me.updateBar();
    382     },
    383     //更新bar
    384     updateBar: function () {
    385         //更新其他
    386         var bar = this.getBar() || {};
    387         //设置导航栏临时控件组
    388         this.setTmpItems(bar.items);
    389         //设置导航栏临时cls
    390         this.setTmpCls(bar.cls);
    391         //更新返回按钮状态
    392         if (bar.backHide) {
    393             backButton.hide();
    394         }
    395     },
    396     /**
    397      * Calculates and returns the position values needed for the back button when you are pushing a title.
    398      * @private
    399      */
    400     measureView: function (oldLeft, oldTitle, reverse) {
    401         var me = this,
    402         barElement = me.element,
    403         newLeftElement = me.leftBox.element,
    404         titleElement = me.titleComponent.element,
    405         minOffset = Math.min(barElement.getWidth() / 3, 200),
    406         newLeftWidth = newLeftElement.getWidth(),
    407         barX = barElement.getX(),
    408         barWidth = barElement.getWidth(),
    409         titleX = titleElement.getX(),
    410         titleLeft = titleElement.getLeft(),
    411         titleWidth = titleElement.getWidth(),
    412         oldLeftX = oldLeft.x,
    413         oldLeftWidth = oldLeft.width,
    414         oldLeftLeft = oldLeft.left,
    415         useLeft = Ext.browser.is.AndroidStock2 && !this.getAndroid2Transforms(),
    416         newOffset,
    417         oldOffset,
    418         leftAnims,
    419         titleAnims,
    420         omega,
    421         theta;
    422 
    423         theta = barX - oldLeftX - oldLeftWidth;
    424         if (reverse) {
    425             newOffset = theta;
    426             oldOffset = Math.min(titleX - oldLeftWidth, minOffset);
    427         } else {
    428             oldOffset = theta;
    429             newOffset = Math.min(titleX - barX, minOffset);
    430         }
    431 
    432         if (useLeft) {
    433             leftAnims = {
    434                 element: {
    435                     from: {
    436                         left: newOffset,
    437                         opacity: 1
    438                     },
    439                     to: {
    440                         left: 0,
    441                         opacity: 1
    442                     }
    443                 }
    444             };
    445         } else {
    446             leftAnims = {
    447                 element: {
    448                     from: {
    449                         transform: {
    450                             translateX: newOffset
    451                         },
    452                         opacity: 0
    453                     },
    454                     to: {
    455                         transform: {
    456                             translateX: 0
    457                         },
    458                         opacity: 1
    459                     }
    460                 },
    461                 ghost: {
    462                     to: {
    463                         transform: {
    464                             translateX: oldOffset
    465                         },
    466                         opacity: 0
    467                     }
    468                 }
    469             };
    470         }
    471 
    472         theta = barX - titleX + newLeftWidth;
    473         if ((oldLeftLeft + titleWidth) > titleX) {
    474             omega = barX - titleX - titleWidth;
    475         }
    476 
    477         if (reverse) {
    478             titleElement.setLeft(0);
    479 
    480             oldOffset = barX + barWidth - titleX - titleWidth;
    481 
    482             if (omega !== undefined) {
    483                 newOffset = omega;
    484             } else {
    485                 newOffset = theta;
    486             }
    487         } else {
    488             newOffset = barX + barWidth - titleX - titleWidth;
    489 
    490             if (omega !== undefined) {
    491                 oldOffset = omega;
    492             } else {
    493                 oldOffset = theta;
    494             }
    495 
    496             newOffset = Math.max(titleLeft, newOffset);
    497         }
    498 
    499         if (useLeft) {
    500             titleAnims = {
    501                 element: {
    502                     from: {
    503                         left: newOffset,
    504                         opacity: 1
    505                     },
    506                     to: {
    507                         left: titleLeft,
    508                         opacity: 1
    509                     }
    510                 }
    511             };
    512         } else {
    513             titleAnims = {
    514                 element: {
    515                     from: {
    516                         transform: {
    517                             translateX: newOffset
    518                         },
    519                         opacity: 0
    520                     },
    521                     to: {
    522                         transform: {
    523                             translateX: titleLeft
    524                         },
    525                         opacity: 1
    526                     }
    527                 },
    528                 ghost: {
    529                     to: {
    530                         transform: {
    531                             translateX: oldOffset
    532                         },
    533                         opacity: 0
    534                     }
    535                 }
    536             };
    537         }
    538 
    539         return {
    540             left: leftAnims,
    541             title: titleAnims,
    542             titleLeft: titleLeft
    543         };
    544     },
    545 
    546     /**
    547      * Helper method used to animate elements.
    548      * You pass it an element, objects for the from and to positions an option onEnd callback called when the animation is over.
    549      * Normally this method is passed configurations returned from the methods such as #measureTitle(true) etc.
    550      * It is called from the #pushLeftBoxAnimated, #pushTitleAnimated, #popBackButtonAnimated and #popTitleAnimated
    551      * methods.
    552      *
    553      * If the current device is Android, it will use top/left to animate.
    554      * If it is anything else, it will use transform.
    555      * @private
    556      */
    557     animate: function (element, config, callback) {
    558         var me = this,
    559         animation;
    560 
    561         //reset the left of the element
    562         element.setLeft(0);
    563 
    564         config = Ext.apply(config, {
    565             element: element,
    566             easing: 'ease-in-out',
    567             duration: me.getAnimation().duration || 250,
    568             preserveEndState: true
    569         });
    570 
    571         animation = new Ext.fx.Animation(config);
    572         animation.on('animationend',
    573         function () {
    574             if (callback) {
    575                 callback.call(me);
    576             }
    577         },
    578         me);
    579 
    580         Ext.Animator.run(animation);
    581         me.activeAnimations.push(animation);
    582     },
    583 
    584     endAnimation: function () {
    585         var activeAnimations = this.activeAnimations,
    586         animation, i, ln;
    587 
    588         if (activeAnimations) {
    589             ln = activeAnimations.length;
    590             for (i = 0; i < ln; i++) {
    591                 animation = activeAnimations[i];
    592                 if (animation.isAnimating) {
    593                     animation.stopAnimation();
    594                 } else {
    595                     animation.destroy();
    596                 }
    597             }
    598             this.activeAnimations = [];
    599         }
    600     },
    601 
    602     refreshTitlePosition: function () {
    603         if (!this.isAnimating) {
    604             this.callParent();
    605         }
    606     },
    607 
    608     /**
    609      * Returns the text needed for the current back button at anytime.
    610      * @private
    611      */
    612     getBackButtonText: function () {
    613         var text = this.backButtonStack[this.backButtonStack.length - 2],
    614         useTitleForBackButtonText = this.getUseTitleForBackButtonText();
    615 
    616         if (!useTitleForBackButtonText) {
    617             if (text) {
    618                 text = this.getDefaultBackButtonText();
    619             }
    620         }
    621 
    622         return text;
    623     },
    624 
    625     /**
    626      * Returns the text needed for the current title at anytime.
    627      * @private
    628      */
    629     getTitleText: function () {
    630         if (this.backButtonStack.length == 0) {
    631             return '';
    632         }
    633         return this.backButtonStack[this.backButtonStack.length - 1].title;
    634     },
    635     getBar: function () {
    636         if (this.backButtonStack.length == 0) {
    637             return false;
    638         }
    639         return this.backButtonStack[this.backButtonStack.length - 1].bar;
    640     },
    641     /**
    642      * Handles removing back button stacks from this bar
    643      * @private
    644      */
    645     beforePop: function (count) {
    646         count--;
    647         for (var i = 0; i < count; i++) {
    648             this.backButtonStack.pop();
    649         }
    650     },
    651 
    652     /**
    653      * We override the hidden method because we don't want to remove it from the view using display:none. Instead we just position it off
    654      * the screen, much like the navigation bar proxy. This means that all animations, pushing, popping etc. all still work when if you hide/show
    655      * this bar at any time.
    656      * @private
    657      */
    658     doSetHidden: function (hidden) {
    659         if (!hidden) {
    660             this.element.setStyle({
    661                 position: 'relative',
    662                 top: 'auto',
    663                 left: 'auto',
    664                  'auto'
    665             });
    666         } else {
    667             this.element.setStyle({
    668                 position: 'absolute',
    669                 top: '-1000px',
    670                 left: '-1000px',
    671                  this.element.getWidth() + 'px'
    672             });
    673         }
    674     },
    675 
    676     /**
    677      * Creates a proxy element of the passed element, and positions it in the same position, using absolute positioning.
    678      * The createNavigationBarProxy method uses this to create proxies of the backButton and the title elements.
    679      * @private
    680      */
    681     createProxy: function (element) {
    682         var ghost, x, y, left, width;
    683 
    684         ghost = element.dom.cloneNode(true);
    685         ghost.id = element.id + '-proxy';
    686 
    687         //insert it into the toolbar
    688         element.getParent().dom.appendChild(ghost);
    689 
    690         //set the x/y
    691         ghost = Ext.get(ghost);
    692         x = element.getX();
    693         y = element.getY();
    694         left = element.getLeft();
    695         width = element.getWidth();
    696         ghost.setStyle('position', 'absolute');
    697         ghost.setX(x);
    698         ghost.setY(y);
    699         ghost.setHeight(element.getHeight());
    700         ghost.setWidth(width);
    701 
    702         return {
    703             x: x,
    704             y: y,
    705             left: left,
    706              width,
    707             ghost: ghost
    708         };
    709     }
    710 });
  • 相关阅读:
    bat 笔记 一
    air 桌面应用发布后可以删除的文件
    as3 去掉字符串空白问题
    as3 air 获取文件夹下的所有文件
    egret 配置设置
    egret 精简游戏项目
    starling 第一天
    《笨办法学Python》 第2课手记
    《笨办法学Python》 第1课手记
    《笨办法学Python》 第0课手记
  • 原文地址:https://www.cnblogs.com/mlzs/p/3655762.html
Copyright © 2011-2022 走看看