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

代码:

 /*
*模仿且改进NavigationView
*返回时自动销毁视图,节约内存
*/
Ext.define('ux.CardPanel', {
extend: 'Ext.Container',
xtype: 'cardPanel',
requires: ['Ext.TitleBar'],
config: {
//顶部导航条
navBar: {
docked: 'top'
},
//布局,type不可更改
layout: {
type: 'card',
animation: {
duration: 300,
easing: 'ease-out',
type: 'slide',
direction: 'left'
}
},
//顶部控件组,在子项中配置
navBarItems: null,
//返回按钮
backBtn: {
align: 'left',
ui: 'back'
},
//返回按钮显示状态,在子项中配置
backHide: false,
//临时cls,在子项中配置
pCls: null,
//底部导航栏、可选格式btmBar:'xtype',在子项中配置
btmBar: null,
//当子项被激活后移除除了指定项之外的项,在子项中配置
nRemove: null
},
//初始化
initialize: function () {
var layout = this.getLayout();
if (layout && !layout.isCard) {
Ext.Logger.error('CardPanel中layout的布局只能是card布局');
}
this.initStatus();
},
//初始化历史记录
initStatus: function () {
if (!this.viewStack) {
//历史记录
this.viewStack = [];
//视图加载状态
this.viewStatus = {};
}
},
//更新返回按钮显示状态
updateBackHide: function (newItem, oldItem) {
var backBtn = this.getBackBtn();
if (newItem) {
backBtn.hide();
} else {
backBtn.show();
}
},
//更新底部导航栏
updateBtmBar: function (newItem, oldItem) {
if (oldItem) {
oldItem = this.down(oldItem);
this.remove(oldItem);
}
if (newItem) {
newItem = Ext.create(newItem);
this.add(newItem);
}
},
//创建导航栏控件组
applyNavBarItems: function (newItems) {
if (!newItems) return false;
var me = this,
navItems = [],
i,
ln;
newItems = Ext.Array.from(newItems);
for (i = 0, ln = newItems.length; i < ln; i++) {
navItems.push(me.factoryItem(newItems[i]));
}
return navItems;
},
//更新导航栏控件组
updateNavBarItems: function (newItem, oldItem) {
var navBar = this.getNavBar();
if (oldItem) {
var i, ln;
for (i = 0, ln = oldItem.length; i < ln; i++) {
navBar.remove(oldItem[i]);
}
}
if (newItem) {
navBar.add(newItem);
}
},
//创建顶部导航栏
applyNavBar: function (config) {
return Ext.factory(config, Ext.TitleBar, this.getNavBar());
},
//更新顶部导航栏
updateNavBar: function (newItem, oldItem) {
if (oldItem) {
this.remove(oldItem);
}
if (newItem) {
this.add(newItem);
}
},
//更新临时cls
updatePCls: function (newItem, oldItem) {
if (oldItem) {
this.removeCls(oldItem);
}
if (newItem) {
this.addCls(newItem);
}
},
//创建返回按钮
applyBackBtn: function (config) {
return Ext.factory(config, Ext.Button, this.getBackBtn());
},
//更新返回按钮
updateBackBtn: function (newItem, oldItem) {
if (oldItem) {
this.getNavBar().remove(oldItem);
}
if (newItem) {
this.getNavBar().add(newItem);
newItem.on({
scope: this,
tap: this.onBackButtonTap
});
}
},
//更新移除
updateNRemove: function (newItem, oldItem) {
var animation = this.getLayout().getAnimation();
if (oldItem) {
//移除动画结束监听
animation.un({
scope: this,
animationend: 'onAnimationend'
});
}
if (newItem) {
//添加动画结束监听
animation.on({
scope: this,
animationend: 'onAnimationend'
});
}
},
/**
* 移除历史记录
* @private
*/
viewStackPop: function (count) {
for (var i = 0; i < count; i++) {
this.viewStack.pop();
}
},
//添加视图
//注意xtype是指alternateClassName
push: function (xtype, params) {
var me = this,
view = this.getActiveItem(),
oldXtype = view && (view.config.xtype || view.getItemId());
/*过滤已经添加的视图*/
if (!this.viewStatus[xtype]) {
params = params || {};
params.itemId = xtype;
view = Ext.create(xtype, params);
this.add(view);
} else if (oldXtype != xtype) {
this.viewStack.push(xtype);
this.setActiveItem(xtype);
}
},
//当动画效果结束时,子项配置了nRemove属性将会激活
onAnimationend: function () {
// console.log('animationend');
this.popAll(this.getNRemove());
},
//项被激活
onActivate: function (view) {
var config = view.config;
// console.log('activate', config.xtype || view.getItemId());
//更新后退按钮
// console.log('setBackHide', this.viewStack);
this.setBackHide(config.backHide || this.viewStack.length == 1);
//更新按钮组
var items = config.navBarItems || false;
this.setNavBarItems(items);
//更新cls
var pCls = config.pCls || false;
this.setPCls(pCls);
//更新标题
var title = config.title || '';
this.getNavBar().setTitle(title);
//更新底部导航栏
var btmBar = config.btmBar || false;
this.setBtmBar(btmBar);
//更新移除
var nRemove = config.nRemove || false;
this.setNRemove(nRemove);
},
//项被销毁
onDestroy: function (view) {
// console.log('onDestroy', view.config.xtype || view.getItemId());
this.viewStatus[view.config.xtype || view.getItemId()] = false;
},
/**
* 不填写参数时,移除当前项,返回到上一项
* 如果参数是数字,则从最后一项开始移除指定数目的项
* 如果参数是string,则移除指定类型的项
* 如果参数是项,则移除传入的项
* 不论参数如何,都会保留一个活动项
* @return {Ext.Component} 当前活动项
*/
pop: function (count) {
if (this.beforePop(count)) {
return this.doPop();
}
},
/**
* @private
*删除指定项
*/
beforePop: function (count) {
var me = this,
innerItems = me.getInnerItems();
if (Ext.isString(count) || Ext.isObject(count)) {
var last = innerItems.length - 1,
i;
for (i = last; i >= 0; i--) {
if ((Ext.isString(count) && Ext.ComponentQuery.is(innerItems[i], count)) || (Ext.isObject(count) && count == innerItems[i])) {
//获得移除项序号
count = last - i;
break;
}
}
if (!Ext.isNumber(count)) {
return false;
}
}
var ln = innerItems.length,
toRemove;
//默认移除一项
if (!Ext.isNumber(count) || count < 1) {
count = 1;
}
//当我们试图移除更多视图时
count = Math.min(count, ln - 1);
if (count) {
this.viewStackPop(count);
//开始移除视图
toRemove = innerItems.splice(-count, count - 1);
for (i = 0; i < toRemove.length; i++) {
this.remove(toRemove[i]);
}
return true;
}
return false;
},
/**
* @private
*移除最后一项
*/
doPop: function () {
var me = this,
innerItems = this.getInnerItems(),
ord = innerItems[innerItems.length - 1];
me.remove(ord);
//触发被移除项的事件
return this.getActiveItem();
},
doResetActiveItem: function (innerIndex) {
var me = this,
innerItems = me.getInnerItems(),
animation = me.getLayout().getAnimation();
if (innerIndex > 0) {
if (animation && animation.isAnimation) {
animation.setReverse(true);
}
me.setActiveItem(innerIndex - 1);
}
},
/**
* @private
*执行移除项,调用remove方法后自动执行
*/
doRemove: function () {
var animation = this.getLayout().getAnimation();
if (animation && animation.isAnimation) {
animation.setReverse(false);
}
this.callParent(arguments);
},
/**
* @private
*执行添加项,调用add方法后自动执行
*/
onItemAdd: function (item, index) {
if (item.isInnerItem()) {
var xtype = item.config.xtype || item.getItemId();
//如果配置了items,会先于initialize执行,所以需要初始化历史纪录
this.initStatus();
this.viewStatus[xtype] = true;
this.viewStack.push(xtype);
//添加监听
item.on({
scope: this,
activate: 'onActivate',
destroy: 'onDestroy'
});
}
this.doItemLayoutAdd(item, index);
if (!this.isItemsInitializing && item.isInnerItem()) {
this.setActiveItem(item);
}
if (this.initialized) {
this.fireEvent('add', this, item, index);
}
},
/**
* 移除第一项和最后项之间的所有项(包括最后项)
* @return {Ext.Component} 当前活动视图
*/
reset: function (noUp) {
return this.pop(this.getInnerItems().length);
},
//除了指定项,从倒数第二项开始移除
popAll: function (xtype) {
var me = this,
innerItems = this.getInnerItems(),
length = innerItems.length - 1,
oldXtype,
ord,
i;
this.viewStack = [xtype];
for (i = length; i > -1; i--) {
/*过滤掉需要显示的视图*/
ord = innerItems[i];
oldXtype = ord.config.xtype || ord.getItemId();
if (i == length) {
me.viewStack.push(oldXtype);
} else if (oldXtype != xtype) {
me.remove(ord, true);
}
}
},
//返回上一个历史记录
onBackButtonTap: function () {
this.pop();
this.fireEvent('back', this);
}
});

主视图js:

 /*
*主视图,负责视图切换
*/
Ext.define('app.view.Main', {
extend: 'ux.CardPanel',
requires: ['app.view.Home', 'Ext.picker.Picker', 'app.view.uitl.MyBar', 'app.view.user.Site'],
xtype: 'main',
config: {
id: 'main',
cls: 'cardPanel',
backBtn: {
iconCls: 'reply',
iconMask: true,
cls: 'replyBtn'
},
//items只能配置一项
items: [{
xtype: 'home'
}]
}
});

子视图js:

 Ext.define('app.view.message.List', {
alternateClassName: 'messageList',
extend: 'Ext.List',
xtype: 'messageList',
requires: ['Ext.plugin.ListPaging'],
config: {
cls: 'list',
//标题
title: '校园资讯',
//用于控制navBarItems中的css
pCls: '',
//底部导航栏,直接填写alternateClassName
btmBar: 'myBar',
//额外的按钮组,只能是按钮组。不能添加其他属性
navBarItems: [{
itemId: 'mBtn',
xtype: 'button',
align: 'right',
iconMask: true,
cls: 'nBg',
iconCls: 'search',
action: 'show',
show: 'messageSearch'
}],
plugins: [{
xclass: 'Ext.plugin.ListPaging'
}],
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>',
store: 'messageList'
}
});

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

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

  1. sencha touch 扩展官方NavigationView 灵活添加按钮组,导航栏,自由隐藏返回按钮(2014-5-15)

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

  2. ios之自定义导航栏上的返回按钮

    导航栏的按钮,右边的按钮是可以自己随意添加的.但左边的返回按钮怎么定制?你会说,添加一个自己的按钮呗!你可以试试看,这样行不行. 正确的答案是重载UINavigationController类的pus ...

  3. Android自定义组合控件详细示例 (附完整源码)

    在我们平时的Android开发中,有时候原生的控件无法满足我们的需求,或者经常用到几个控件组合在一起来使用.这个时候,我们就可以根据自己的需求创建自定义的控件了,一般通过继承View或其子类来实现. ...

  4. iOS开发UI篇—Quartz2D(自定义UIImageView控件)

    iOS开发UI篇—Quartz2D(自定义UIImageView控件) 一.实现思路 Quartz2D最大的用途在于自定义View(自定义UI控件),当系统的View不能满足我们使用需求的时候,自定义 ...

  5. 安卓自定义组合控件--toolbar

    最近在学习安卓APP的开发,用到了toolbar这个控件, 最开始使用时include layout这种方法,不过感觉封装性不好,就又改成了自定义组合控件的方式. 使用的工具为android stud ...

  6. Android自定义控件之自定义组合控件

    前言: 前两篇介绍了自定义控件的基础原理Android自定义控件之基本原理(一).自定义属性Android自定义控件之自定义属性(二).今天重点介绍一下如何通过自定义组合控件来提高布局的复用,降低开发 ...

  7. asp.net webform 自定义分页控件

    做web开发一直用到分页控件,自己也动手实现了个,使用用户自定义控件. 翻页后数据加载使用委托,将具体实现放在在使用分页控件的页面进行注册. 有图有真相,给个直观的认识: 自定义分页控件前台代码: & ...

  8. arcgis api for js共享干货系列之二自定义Navigation控件样式风格

    arcgis api for js默认的Navigation控件样式风格如下图: 这样的风格不能说不好,各有各的爱好,审美观,这里也不是重点,这里的重点是如何自定义一套自己喜欢的样式风格呢:自己自定义 ...

  9. 论如何在手机端web前端实现自定义原生控件的样式

    手机开发webapp的同学一定遇到过这样问题,如何为丑极了的手机元素应用自定义的样式.首先,要弄清楚为什么要定义手机原生控件的样式,就需要看看手机的那些原生框样式的丑陋摸样: android: ios ...

随机推荐

  1. iOS7以上: 实现如“日历”的 NavigationBar

    第一步,隐藏导航栏底部的分割线 如何隐藏导航栏底部的分割线(shadow image/ hairline)? navigationBar.clipsToBounds = YES; //隐藏 navig ...

  2. 解决ESXi有虚拟机模版部署的CentOS虚拟机,网卡eth0找不到问题

    1,问题和虚拟机克隆后出现网卡找不到问题类似. 2,修改主机名hostname 修改 /etc/sysconfig/network文件 3,删除/etc/sysconfig/network-scrip ...

  3. UNIX环境编程学习笔记(25)——信号处理进阶学习之 sigaction 函数

    lienhua342014-11-05 sigaction 函数跟 signal 函数一样,用于设置信号处理函数.此函数是用于取代 UNIX 早期版本使用的 signal 函数.UNIX 早期版本的 ...

  4. protected: C++ access control works on per-class basis, not on per-object basis

    一个很简单的问题: //为什么BASE::foo()中可以直接通过p访问val? 看本记录标题,这个问题困扰了很长一段时间,终于解决class BASE {      private:        ...

  5. Specified key was too long; max key length is 1000 bytes问题解决

    今天使用帆软的报表平台管理,进行外接数据库配置,尝试多次一直提示数据导入失败 java的报错 com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorExcep ...

  6. python中的List 和 Tuple

    #-*- coding:UTF-8 -*- classmates=["Michael","Bob","Tracy"] print(class ...

  7. QT编译错误:invalid application of 'sizeof' to incomplete type 'Qt3DRender::QPickEvent'

    执行3D常将中实体的pick操作,结果出现了编译错误:invalid application of 'sizeof' to incomplete type 'Qt3DRender::QPickEven ...

  8. Apache POI HSSF,XSSF和SXSSF的区别

    http://blog.csdn.net/benben_1678/article/details/39989683 写的很好,用SXSSF即可解决大数据量,内存占用过高问题

  9. python concurrent.futures包使用,捕获异常

    concurrent.futures的ThreadPoolExecutor类暴露的api很好用,threading模块抹油提供官方的线程池.和另外一个第三方threadpool包相比,这个可以非阻塞的 ...

  10. python使用pyqt写带界面工具

    上篇介绍的使用python自带tkinter包,来写带界面的工具. 此篇介绍使用pyqt来开发测试工具. tkinter的好处是python官方自带,上手容易(但手写控件复杂),布局和摆放都不直观和容 ...