• 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

  • 相关阅读:
    大话字符串逆序
    Class文件结构全面解析(上)
    怎么把CAT客户端的RootMessageId记录到每条日志中?
    阅读JDK源码后,我有了优化它的冲动!
    CAT客户端如何从Apollo中读取配置?
    Sublime Text 3许可证
    通俗易懂地给女朋友讲:线程池的内部原理
    五分钟后,你将学会在SpringBoot项目中如何集成CAT调用链
    分布式监控CAT服务端的本地部署
    如何优雅的设置线程池的大小?
  • 原文地址:https://www.cnblogs.com/mlzs/p/3294889.html
Copyright © 2020-2023  润新知