sencha touch 自定义cardpanel控件 模仿改进NavigationView 灵活添加按钮组,导航栏,自由隐藏返回按钮(废弃 仅参考)

最新版本我将会放在:http://www.cnblogs.com/mlzs/p/3382229.html这里的示例里面,这里不会再做更新

代码:

  1 /*
  2 *模仿且改进NavigationView
  3 *返回时自动销毁视图,节约内存
  4 */
  5 Ext.define('ux.CardPanel', {
  6     extend: 'Ext.Container',
  7     xtype: 'cardPanel',
  8     requires: ['Ext.TitleBar'],
  9     config: {
 10         //顶部导航条
 11         navBar: {
 12             docked: 'top'
 13         },
 14         //布局,type不可更改
 15         layout: {
 16             type: 'card',
 17             animation: {
 18                 duration: 300,
 19                 easing: 'ease-out',
 20                 type: 'slide',
 21                 direction: 'left'
 22             }
 23         },
 24         //顶部控件组,在子项中配置
 25         navBarItems: null,
 26         //返回按钮
 27         backBtn: {
 28             align: 'left',
 29             ui: 'back'
 30         },
 31         //返回按钮显示状态,在子项中配置
 32         backHide: false,
 33         //临时cls,在子项中配置
 34         pCls: null,
 35         //底部导航栏、可选格式btmBar:'xtype',在子项中配置
 36         btmBar: null,
 37         //当子项被激活后移除除了指定项之外的项,在子项中配置
 38         nRemove: null
 39     },
 40     //初始化
 41     initialize: function () {
 42         var layout = this.getLayout();
 43         if (layout && !layout.isCard) {
 44             Ext.Logger.error('CardPanel中layout的布局只能是card布局');
 45         }
 46         this.initStatus();
 47     },
 48     //初始化历史记录
 49     initStatus: function () {
 50         if (!this.viewStack) {
 51             //历史记录
 52             this.viewStack = [];
 53             //视图加载状态
 54             this.viewStatus = {};
 55         }
 56     },
 57     //更新返回按钮显示状态
 58     updateBackHide: function (newItem, oldItem) {
 59         var backBtn = this.getBackBtn();
 60         if (newItem) {
 61             backBtn.hide();
 62         } else {
 63             backBtn.show();
 64         }
 65     },
 66     //更新底部导航栏
 67     updateBtmBar: function (newItem, oldItem) {
 68         if (oldItem) {
 69             oldItem = this.down(oldItem);
 70             this.remove(oldItem);
 71         }
 72         if (newItem) {
 73             newItem = Ext.create(newItem);
 74             this.add(newItem);
 75         }
 76     },
 77     //创建导航栏控件组
 78     applyNavBarItems: function (newItems) {
 79         if (!newItems) return false;
 80         var me = this,
 81         navItems = [],
 82         i,
 83         ln;
 84         newItems = Ext.Array.from(newItems);
 85         for (i = 0, ln = newItems.length; i < ln; i++) {
 86             navItems.push(me.factoryItem(newItems[i]));
 87         }
 88         return navItems;
 89     },
 90     //更新导航栏控件组
 91     updateNavBarItems: function (newItem, oldItem) {
 92         var navBar = this.getNavBar();
 93         if (oldItem) {
 94             var i, ln;
 95             for (i = 0, ln = oldItem.length; i < ln; i++) {
 96                 navBar.remove(oldItem[i]);
 97             }
 98         }
 99         if (newItem) {
100             navBar.add(newItem);
101         }
102     },
103     //创建顶部导航栏
104     applyNavBar: function (config) {
105         return Ext.factory(config, Ext.TitleBar, this.getNavBar());
106     },
107     //更新顶部导航栏
108     updateNavBar: function (newItem, oldItem) {
109         if (oldItem) {
110             this.remove(oldItem);
111         }
112         if (newItem) {
113             this.add(newItem);
114         }
115     },
116     //更新临时cls
117     updatePCls: function (newItem, oldItem) {
118         if (oldItem) {
119             this.removeCls(oldItem);
120         }
121         if (newItem) {
122             this.addCls(newItem);
123         }
124     },
125     //创建返回按钮
126     applyBackBtn: function (config) {
127         return Ext.factory(config, Ext.Button, this.getBackBtn());
128     },
129     //更新返回按钮
130     updateBackBtn: function (newItem, oldItem) {
131         if (oldItem) {
132             this.getNavBar().remove(oldItem);
133         }
134         if (newItem) {
135             this.getNavBar().add(newItem);
136             newItem.on({
137                 scope: this,
138                 tap: this.onBackButtonTap
139             });
140         }
141     },
142     //更新移除
143     updateNRemove: function (newItem, oldItem) {
144         var animation = this.getLayout().getAnimation();
145         if (oldItem) {
146             //移除动画结束监听
147             animation.un({
148                 scope: this,
149                 animationend: 'onAnimationend'
150             });
151         }
152         if (newItem) {
153             //添加动画结束监听
154             animation.on({
155                 scope: this,
156                 animationend: 'onAnimationend'
157             });
158         }
159     },
160     /**
161     * 移除历史记录
162     * @private
163     */
164     viewStackPop: function (count) {
165         for (var i = 0; i < count; i++) {
166             this.viewStack.pop();
167         }
168     },
169     //添加视图
170     //注意xtype是指alternateClassName
171     push: function (xtype, params) {
172         var me = this,
173         view = this.getActiveItem(),
174         oldXtype = view && (view.config.xtype || view.getItemId());
175         /*过滤已经添加的视图*/
176         if (!this.viewStatus[xtype]) {
177             params = params || {};
178             params.itemId = xtype;
179             view = Ext.create(xtype, params);
180             this.add(view);
181         } else if (oldXtype != xtype) {
182             this.viewStack.push(xtype);
183             this.setActiveItem(xtype);
184         }
185     },
186     //当动画效果结束时,子项配置了nRemove属性将会激活
187     onAnimationend: function () {
188         //        console.log('animationend');
189         this.popAll(this.getNRemove());
190     },
191     //项被激活
192     onActivate: function (view) {
193         var config = view.config;
194         //        console.log('activate', config.xtype || view.getItemId());
195         //更新后退按钮
196         //        console.log('setBackHide', this.viewStack);
197         this.setBackHide(config.backHide || this.viewStack.length == 1);
198         //更新按钮组
199         var items = config.navBarItems || false;
200         this.setNavBarItems(items);
201         //更新cls
202         var pCls = config.pCls || false;
203         this.setPCls(pCls);
204         //更新标题
205         var title = config.title || '';
206         this.getNavBar().setTitle(title);
207         //更新底部导航栏
208         var btmBar = config.btmBar || false;
209         this.setBtmBar(btmBar);
210         //更新移除
211         var nRemove = config.nRemove || false;
212         this.setNRemove(nRemove);
213     },
214     //项被销毁
215     onDestroy: function (view) {
216         //        console.log('onDestroy', view.config.xtype || view.getItemId());
217         this.viewStatus[view.config.xtype || view.getItemId()] = false;
218     },
219     /**
220     * 不填写参数时,移除当前项,返回到上一项
221     * 如果参数是数字,则从最后一项开始移除指定数目的项
222     * 如果参数是string,则移除指定类型的项
223     * 如果参数是项,则移除传入的项
224     * 不论参数如何,都会保留一个活动项
225     * @return {Ext.Component} 当前活动项
226     */
227     pop: function (count) {
228         if (this.beforePop(count)) {
229             return this.doPop();
230         }
231     },
232     /**
233     * @private
234     *删除指定项
235     */
236     beforePop: function (count) {
237         var me = this,
238         innerItems = me.getInnerItems();
239         if (Ext.isString(count) || Ext.isObject(count)) {
240             var last = innerItems.length - 1,
241             i;
242             for (i = last; i >= 0; i--) {
243                 if ((Ext.isString(count) && Ext.ComponentQuery.is(innerItems[i], count)) || (Ext.isObject(count) && count == innerItems[i])) {
244                     //获得移除项序号
245                     count = last - i;
246                     break;
247                 }
248             }
249             if (!Ext.isNumber(count)) {
250                 return false;
251             }
252         }
253         var ln = innerItems.length,
254         toRemove;
255         //默认移除一项
256         if (!Ext.isNumber(count) || count < 1) {
257             count = 1;
258         }
259         //当我们试图移除更多视图时
260         count = Math.min(count, ln - 1);
261         if (count) {
262             this.viewStackPop(count);
263             //开始移除视图
264             toRemove = innerItems.splice(-count, count - 1);
265             for (i = 0; i < toRemove.length; i++) {
266                 this.remove(toRemove[i]);
267             }
268             return true;
269         }
270         return false;
271     },
272     /**
273     * @private
274     *移除最后一项
275     */
276     doPop: function () {
277         var me = this,
278         innerItems = this.getInnerItems(),
279         ord = innerItems[innerItems.length - 1];
280         me.remove(ord);
281         //触发被移除项的事件
282         return this.getActiveItem();
283     },
284     doResetActiveItem: function (innerIndex) {
285         var me = this,
286         innerItems = me.getInnerItems(),
287         animation = me.getLayout().getAnimation();
288         if (innerIndex > 0) {
289             if (animation && animation.isAnimation) {
290                 animation.setReverse(true);
291             }
292             me.setActiveItem(innerIndex - 1);
293         }
294     },
295     /**
296     * @private 
297     *执行移除项,调用remove方法后自动执行
298     */
299     doRemove: function () {
300         var animation = this.getLayout().getAnimation();
301         if (animation && animation.isAnimation) {
302             animation.setReverse(false);
303         }
304         this.callParent(arguments);
305     },
306     /**
307     * @private 
308     *执行添加项,调用add方法后自动执行
309     */
310     onItemAdd: function (item, index) {
311         if (item.isInnerItem()) {
312             var xtype = item.config.xtype || item.getItemId();
313             //如果配置了items,会先于initialize执行,所以需要初始化历史纪录
314             this.initStatus();
315             this.viewStatus[xtype] = true;
316             this.viewStack.push(xtype);
317             //添加监听
318             item.on({
319                 scope: this,
320                 activate: 'onActivate',
321                 destroy: 'onDestroy'
322             });
323         }
324         this.doItemLayoutAdd(item, index);
325         if (!this.isItemsInitializing && item.isInnerItem()) {
326             this.setActiveItem(item);
327         }
328         if (this.initialized) {
329             this.fireEvent('add', this, item, index);
330         }
331     },
332     /**
333     * 移除第一项和最后项之间的所有项(包括最后项)
334     * @return {Ext.Component} 当前活动视图
335     */
336     reset: function (noUp) {
337         return this.pop(this.getInnerItems().length);
338     },
339     //除了指定项,从倒数第二项开始移除
340     popAll: function (xtype) {
341         var me = this,
342         innerItems = this.getInnerItems(),
343         length = innerItems.length - 1,
344         oldXtype,
345         ord,
346         i;
347         this.viewStack = [xtype];
348         for (i = length; i > -1; i--) {
349             /*过滤掉需要显示的视图*/
350             ord = innerItems[i];
351             oldXtype = ord.config.xtype || ord.getItemId();
352             if (i == length) {
353                 me.viewStack.push(oldXtype);
354             } else if (oldXtype != xtype) {
355                 me.remove(ord, true);
356             }
357         }
358     },
359     //返回上一个历史记录
360     onBackButtonTap: function () {
361         this.pop();
362         this.fireEvent('back', this);
363     }
364 });

主视图js:

 1 /*
 2 *主视图,负责视图切换
 3 */
 4 Ext.define('app.view.Main', {
 5     extend: 'ux.CardPanel',
 6     requires: ['app.view.Home', 'Ext.picker.Picker', 'app.view.uitl.MyBar', 'app.view.user.Site'],
 7     xtype: 'main',
 8     config: {
 9         id: 'main',
10         cls: 'cardPanel',
11         backBtn: {
12             iconCls: 'reply',
13             iconMask: true,
14             cls: 'replyBtn'
15         },
16         //items只能配置一项
17         items: [{
18             xtype: 'home'
19         }]
20     }
21 });

子视图js:

 1 Ext.define('app.view.message.List', {
 2     alternateClassName: 'messageList',
 3     extend: 'Ext.List',
 4     xtype: 'messageList',
 5     requires: ['Ext.plugin.ListPaging'],
 6     config: {
 7         cls: 'list',
 8         //标题
 9         title: '校园资讯',
10         //用于控制navBarItems中的css
11         pCls: '',
12         //底部导航栏,直接填写alternateClassName
13         btmBar: 'myBar',
16         //额外的按钮组,只能是按钮组。不能添加其他属性
17         navBarItems: [{
18             itemId: 'mBtn',
19             xtype: 'button',
20             align: 'right',
21             iconMask: true,
22             cls: 'nBg',
23             iconCls: 'search',
24             action: 'show',
25             show: 'messageSearch'
26         }],
27         plugins: [{
28             xclass: 'Ext.plugin.ListPaging'
29         }],
30         itemTpl: '<div class="title">{Title}</div><div class="sm">时间 {Time}&nbsp;&nbsp;&nbsp;&nbsp;发布来源:{Auth}</div><div class="like"><div class="ico comment">0</div></div>',
31         store: 'messageList'
32     }
33 });

2013.9.6

更改CardPanel

优化navBarItems结构,itemId不再必须设置

优化for循环结果

修复popAll方法中ord为全局变量的问题

2013.9.6

更改push方法,可以在传入配置参数(只在第一次创建视图时有效)

2013.10.7

优化代码细节

2013.10.10

更改pop方法,将代码this.setActiveItem(this.getLateViewStack());移动到onBackButtonTap方法中,以解决pop后再push无动画效果的问题

2013.10.18

参照NavigationView大幅度修改代码,去除一些无用代码

2013.10.22

更新push方法,更好的配置自定义参数

移除debug标签,解决cmd压缩后出错的问题。感谢@低碳哥指出

2013.10.23

优化代码,移除了除了back之外的所有自定义事件。如需使用可以考虑用 activate与deactivate事件代替

相关代码:http://www.cnblogs.com/mlzs/p/3382909.html

原文地址:https://www.cnblogs.com/mlzs/p/3294889.html