1 Ext.define('Ext.navigation.View', { 2 extend: 'Ext.Container', 3 alternateClassName: 'Ext.NavigationView', 4 xtype: 'navigationview', 5 requires: ['Ext.navigation.Bar'], 6 config: { 7 /** 8 * @cfg 9 * @inheritdoc 10 */ 11 baseCls: Ext.baseCSSPrefix + 'navigationview', 12 /** 13 * @cfg {Boolean/Object} navigationBar 14 * 用以配置导航栏 15 */ 16 navigationBar: { 17 docked: 'top' 18 }, 19 /** 20 * @cfg {String} defaultBackButtonText 21 * 返回按钮默认显示值 22 */ 23 defaultBackButtonText: 'Back', 24 /** 25 * @cfg {Boolean} useTitleForBackButtonText 26 * 当此值为false时,返回按钮显示值为defaultBackButtonText中设置的值 27 * 当此值为true时,返回按钮显示值为上个项的title值 28 * @accessor 29 */ 30 useTitleForBackButtonText: false, 31 /** 32 * @cfg 33 * @hide 34 */ 35 layout: { 36 type: 'card', 37 animation: { 38 duration: 300, 39 easing: 'ease-out', 40 type: 'slide', 41 direction: 'left' 42 } 43 } 44 }, 45 // @private 46 initialize: function () { 47 var me = this, 48 navBar = me.getNavigationBar(); 49 50 //为导航栏上的后退按钮,添加监听 51 navBar.on({ 52 back: me.onBackButtonTap, 53 scope: me 54 }); 55 56 me.relayEvents(navBar, 'rightbuttontap'); 57 58 me.relayEvents(me, { 59 add: 'push', 60 remove: 'pop' 61 }); 62 63 //<debug> 64 var layout = me.getLayout(); 65 if (layout && !layout.isCard) { 66 Ext.Logger.error('The base layout for a NavigationView must always be a Card Layout'); 67 } 68 //</debug> 69 }, 70 /** 71 * @private 72 */ 73 applyLayout: function (config) { 74 config = config || {}; 75 76 return config; 77 }, 78 /** 79 * @private 80 * 用户点击返回按钮 81 */ 82 onBackButtonTap: function () { 83 this.pop(); 84 this.fireEvent('back', this); 85 }, 86 /** 87 * 添加并且显示一个新项 88 * @return {Ext.Component} 89 */ 90 push: function (view) { 91 return this.add(view); 92 }, 93 /** 94 * 不填写参数时,移除当前项,返回到上一项 95 * 如果参数是数字,则从最后一项开始移除指定数目的项 96 * 如果参数是string,则移除指定类型的项 97 * 如果参数是项,则移除传入的项 98 * 不论参数如何,都会保留一个活动项 99 * @return {Ext.Component} 当前活动项 100 */ 101 pop: function (count) { 102 if (this.beforePop(count)) { 103 return this.doPop(); 104 } 105 }, 106 /** 107 * @private 108 *删除指定项 109 */ 110 beforePop: function (count) { 111 var me = this, 112 innerItems = me.getInnerItems(); 113 114 if (Ext.isString(count) || Ext.isObject(count)) { 115 var last = innerItems.length - 1, 116 i; 117 for (i = last; i >= 0; i--) { 118 if ((Ext.isString(count) && Ext.ComponentQuery.is(innerItems[i], count)) || (Ext.isObject(count) && count == innerItems[i])) { 119 //获得移除项序号 120 count = last - i; 121 break; 122 } 123 } 124 125 if (!Ext.isNumber(count)) { 126 return false; 127 } 128 } 129 130 var ln = innerItems.length, 131 toRemove; 132 133 //默认移除一项 134 if (!Ext.isNumber(count) || count < 1) { 135 count = 1; 136 } 137 138 //当我们试图移除更多视图时 139 count = Math.min(count, ln - 1); 140 141 if (count) { 142 //更新导航栏 143 me.getNavigationBar().beforePop(count); 144 145 //开始移除视图 146 toRemove = innerItems.splice(-count, count - 1); 147 for (i = 0; i < toRemove.length; i++) { 148 this.remove(toRemove[i]); 149 } 150 151 return true; 152 } 153 154 return false; 155 }, 156 /** 157 * @private 158 *移除最后一项 159 */ 160 doPop: function () { 161 var me = this, 162 innerItems = this.getInnerItems(); 163 me.remove(innerItems[innerItems.length - 1]); 164 return this.getActiveItem(); 165 }, 166 /** 167 * 获取上一项 168 * @return {Mixed} 上一项 169 */ 170 getPreviousItem: function () { 171 var innerItems = this.getInnerItems(); 172 return innerItems[innerItems.length - 2]; 173 }, 174 /** 175 * 更新导航栏标题栏 {@link #navigationBar} 176 * @private 177 */ 178 updateUseTitleForBackButtonText: function (useTitleForBackButtonText) { 179 var navigationBar = this.getNavigationBar(); 180 if (navigationBar) { 181 navigationBar.setUseTitleForBackButtonText(useTitleForBackButtonText); 182 } 183 }, 184 /** 185 * 更新后退按钮显示值 {@link #navigationBar} 186 * @private 187 */ 188 updateDefaultBackButtonText: function (defaultBackButtonText) { 189 var navigationBar = this.getNavigationBar(); 190 if (navigationBar) { 191 navigationBar.setDefaultBackButtonText(defaultBackButtonText); 192 } 193 }, 194 // @private 初始化时添加导航栏 195 applyNavigationBar: function (config) { 196 if (!config) { 197 config = { 198 hidden: true, 199 docked: 'top' 200 }; 201 } 202 203 if (config.title) { 204 delete config.title; 205 //<debug> 206 Ext.Logger.warn("Ext.navigation.View: The 'navigationBar' configuration does not accept a 'title' property. You " + 207 "set the title of the navigationBar by giving this navigation view's children a 'title' property."); 208 //</debug> 209 } 210 211 config.view = this; 212 config.useTitleForBackButtonText = this.getUseTitleForBackButtonText(); 213 214 return Ext.factory(config, Ext.navigation.Bar, this.getNavigationBar()); 215 }, 216 // @private 更新导航栏 217 updateNavigationBar: function (newNavigationBar, oldNavigationBar) { 218 if (oldNavigationBar) { 219 this.remove(oldNavigationBar, true); 220 } 221 222 if (newNavigationBar) { 223 this.add(newNavigationBar); 224 } 225 }, 226 /** 227 * @private 228 */ 229 applyActiveItem: function (activeItem, currentActiveItem) { 230 var me = this, 231 innerItems = me.getInnerItems(); 232 233 // 确保已经初始化 234 me.getItems(); 235 236 // 如果没有初始化,将堆栈中最后一项设置为活动 237 if (!me.initialized) { 238 activeItem = innerItems.length - 1; 239 } 240 241 return this.callParent([activeItem, currentActiveItem]); 242 }, 243 doResetActiveItem: function (innerIndex) { 244 var me = this, 245 innerItems = me.getInnerItems(), 246 animation = me.getLayout().getAnimation(); 247 248 if (innerIndex > 0) { 249 if (animation && animation.isAnimation) { 250 animation.setReverse(true); 251 } 252 me.setActiveItem(innerIndex - 1); 253 me.getNavigationBar().onViewRemove(me, innerItems[innerIndex], innerIndex); 254 } 255 }, 256 /** 257 * @private 258 *执行移除项,调用remove方法后自动执行 259 */ 260 doRemove: function () { 261 var animation = this.getLayout().getAnimation(); 262 263 if (animation && animation.isAnimation) { 264 animation.setReverse(false); 265 } 266 267 this.callParent(arguments); 268 }, 269 /** 270 * @private 271 *执行添加项,调用add方法后自动执行 272 */ 273 onItemAdd: function (item, index) { 274 this.doItemLayoutAdd(item, index); 275 276 if (!this.isItemsInitializing && item.isInnerItem()) { 277 this.setActiveItem(item); 278 this.getNavigationBar().onViewAdd(this, item, index); 279 } 280 281 if (this.initialized) { 282 this.fireEvent('add', this, item, index); 283 } 284 }, 285 /** 286 * 移除第一项和最后项之间的所有项(包括最后项) 287 * @return {Ext.Component} 当前活动视图 288 */ 289 reset: function () { 290 return this.pop(this.getInnerItems().length); 291 } 292 });