扩展视频讲解: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
注:扩展源码以示例为准

扩展源码:

 Ext.define('ux.navigation.View', {
extend: 'Ext.Container',
alternateClassName: 'ux.NavigationView',
xtype: 'uxNavigationView',
requires: ['ux.navigation.Bar'], config: {
baseCls: Ext.baseCSSPrefix + 'navigationview',
navigationBar: {
docked: 'top',
cls: 'navigationBar'
},
defaultBackButtonText: 'Back',
useTitleForBackButtonText: false,
layout: {
type: 'card',
animation: {
duration: 300,
easing: 'ease-out',
type: 'slide',
direction: 'left'
}
},
index: null,
//不推荐使用
menu: null
}, platformConfig: [{
theme: ['Blackberry'],
navigationBar: {
splitNavigation: true
}
}], // @private
initialize: function () {
var me = this,
navBar = me.getNavigationBar(); //监听导航栏返回按钮
if (navBar) {
navBar.on({
back: me.onBackButtonTap,
scope: me
}); me.relayEvents(navBar, 'rightbuttontap'); me.relayEvents(me, {
add: 'push',
remove: 'pop'
});
}
//<debug>
var layout = me.getLayout();
if (layout && !layout.isCard) {
Ext.Logger.error('The base layout for a NavigationView must always be a Card Layout');
}
//</debug>
}, /**
* @private
*/
applyLayout: function (config) {
config = config || {}; return config;
},
//更新标题
setTitle: function (text) {
var me = this,
nav = me.getNavigationBar();
nav.setTitle(text);
nav.backButtonStack[nav.backButtonStack.length - 1].title = text;
},
/*创建其他导航栏*/
applyMenu: function (newItem) {
if (!newItem) {
return false;
}
var me = this;
return me.factoryItem(newItem);
},
/*更新其他导航栏*/
updateMenu: function (newItem, oldItem) {
if (oldItem) {
//console.log('oldItem:', oldItem.getItemId());
this.remove(oldItem);
}
if (newItem) {
//console.log('newItem:', newItem.getItemId());
this.add(newItem);
}
},
//更新index
updateIndex: function (newItem, oldItem) {
var me = this,
animation = this.getLayout().getAnimation(),
event = {
scope: me,
animationend: 'clearItem'
};
//添加监听
if (oldItem) {
//移除动画结束监听
animation.un(event);
}
if (Ext.isNumber(newItem)) {
//添加动画结束监听
animation.on(event);
}
},
//根据index清理多余的项
clearItem: function () {
var me = this,
innerItems = me.getInnerItems(),
length = innerItems.length,
index = me.getIndex();
count = length - index - 1;
toRemove = innerItems.splice(me.getIndex(), count);
//移除子项
for (i = 0; i < toRemove.length; i++) {
me.remove(toRemove[i]);
}
},
/**
* @private
* 点击返回按钮
*/
onBackButtonTap: function () {
this.pop();
this.fireEvent('back', this);
}, push: function (xtype, params) {
var me = this,
view = me.down('#' + xtype);
if (!view) {
params = params || {};
params.itemId = xtype;
view = Ext.create(xtype, params);
me.add(view);
} else if (view != me.getActiveItem()) {
me.pop(xtype);
}
return view;
},
/*移除当前激活项然后添加新的项xtype为null则只移除*/
popAndPush: function (xtype, params) {
this.pop(null, xtype);
if (xtype) {
this.push(xtype, params);
}
},
/**
* 不填写参数时,移除当前项,返回到上一项
* 如果参数是数字,则从最后一项开始移除指定数目的项
* 如果参数是string,则移除指定类型的项
* 如果参数是项,则移除传入的项
* 不论参数如何,都会保留一个活动项
* @return {Ext.Component} 当前活动项
*/
pop: function (count, hide) {
if (this.beforePop(count)) {
return this.doPop(hide);
}
}, /*删除指定项*/
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;
//default to 1 pop
if (!Ext.isNumber(count) || count < 1) {
count = 1;
} //check if we are trying to remove more items than we have
count = Math.min(count, ln - 1); if (count) {
//we need to reset the backButtonStack in the navigation bar
me.getNavigationBar().beforePop(count); //get the items we need to remove from the view and remove theme
toRemove = innerItems.splice(-count, count - 1);
for (i = 0; i < toRemove.length; i++) {
this.remove(toRemove[i]);
} return true;
} return false;
}, /**
* @private
*/
doPop: function (hide) {
var me = this,
innerItems = this.getInnerItems(),
item = innerItems[innerItems.length - 1];
if (hide) {
item.hide();
}
//set the new active item to be the new last item of the stack
me.remove(item); // Hide the backButton
if (innerItems.length < 3 && this.$backButton) {
this.$backButton.hide();
} // Update the title container
if (this.$titleContainer) {
//<debug>
if (!this.$titleContainer.setTitle) {
Ext.Logger.error('You have selected to display a title in a component that does not \
support titles in NavigationView. Please remove the `title` configuration from your \
NavigationView item, or change it to a component that has a `setTitle` method.');
}
//</debug>
var item = innerItems[innerItems.length - 2];
this.$titleContainer.setTitle((item.getTitle) ? item.getTitle() : item.config.title);
} return this.getActiveItem();
}, /**
* 返回上一项
* @return {Mixed} The previous view
*/
getPreviousItem: function () {
var innerItems = this.getInnerItems();
return innerItems[innerItems.length - 2];
}, /**
* Updates the backbutton text accordingly in the {@link #navigationBar}
* @private
*/
updateUseTitleForBackButtonText: function (useTitleForBackButtonText) {
var navigationBar = this.getNavigationBar();
if (navigationBar) {
navigationBar.setUseTitleForBackButtonText(useTitleForBackButtonText);
}
}, /**
* Updates the backbutton text accordingly in the {@link #navigationBar}
* @private
*/
updateDefaultBackButtonText: function (defaultBackButtonText) {
var navigationBar = this.getNavigationBar();
if (navigationBar) {
navigationBar.setDefaultBackButtonText(defaultBackButtonText);
}
}, // @private
applyNavigationBar: function (config) {
if (!config) {
config = {
hidden: true,
docked: 'top'
};
} if (config.title) {
delete config.title;
//<debug>
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.");
//</debug>
} config.view = this;
config.useTitleForBackButtonText = this.getUseTitleForBackButtonText();
//是否分离导航按钮和标题栏
if (config.splitNavigation) {
this.$titleContainer = this.add({
docked: 'top',
xtype: 'titlebar',
ui: 'light',
title: this.$currentTitle || ''
}); var containerConfig = (config.splitNavigation === true) ? {} : config.splitNavigation; this.$backButtonContainer = this.add(Ext.apply({
xtype: 'toolbar',
docked: 'bottom'
},
containerConfig)); this.$backButton = this.$backButtonContainer.add({
xtype: 'button',
text: 'Back',
hidden: true,
ui: 'back'
}); this.$backButton.on({
scope: this,
tap: this.onBackButtonTap
}); config = {
hidden: true,
docked: 'top'
};
} return Ext.factory(config, ux.navigation.Bar, this.getNavigationBar());
}, // @private
updateNavigationBar: function (newNavigationBar, oldNavigationBar) {
if (oldNavigationBar) {
this.remove(oldNavigationBar, true);
} if (newNavigationBar) {
this.add(newNavigationBar);
}
}, /**
* @private
*/
applyActiveItem: function (activeItem, currentActiveItem) {
var me = this,
innerItems = me.getInnerItems(); // 确保项目已初始化
me.getItems(); // 如果没有初始化, 将最后的子项激活
if (!me.initialized) {
activeItem = innerItems.length - 1;
}
//console.log(this.getItems().keys);
return this.callParent([activeItem, currentActiveItem]);
},
/*pop时反转切换动画*/
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);
me.getNavigationBar().onViewRemove(me, innerItems[innerIndex], innerIndex);
}
}, /**
* 移除子项,调用remove方法后自动执行
* @private
*/
doRemove: function () {
var animation = this.getLayout().getAnimation(); if (animation && animation.isAnimation) {
animation.setReverse(false);
} this.callParent(arguments);
}, onActivate: function (view) {
//更新menu
this.setMenu((view.getMenu) ? view.getMenu() : view.config.Menu);
},
/**
* 添加子项,调用add方法后自动执行
* @private
*/
onItemAdd: function (item, index) { // 检测title配置
if (item && item.getDocked() && item.config.title === true) {
this.$titleContainer = item;
}
if (item.isInnerItem()) {
//添加监听,监听视图激活事件
item.on({
scope: this,
activate: 'onActivate'
});
}
this.doItemLayoutAdd(item, index); var navigaitonBar = this.getInitialConfig().navigationBar; if (!this.isItemsInitializing && item.isInnerItem()) { this.setActiveItem(item);
// 更新navigationBar
if (navigaitonBar) {
//强制排序
this.setIndex((item.getIndex) ? item.getIndex() : item.config.index); this.getNavigationBar().onViewAdd(this, item, index);
} // 更新返回按钮
if (this.$backButtonContainer) {
this.$backButton.show();
}
} if (item && item.isInnerItem()) {
// 更新标题
//console.log('更新标题', item);
this.updateTitleContainerTitle((item.getTitle) ? item.getTitle() : item.config.title);
} if (this.initialized) {
this.fireEvent('add', this, item, index);
}
}, /**
* @private
* 更新titleContainer的标题,如果存在
*/
updateTitleContainerTitle: function (title) {
if (this.$titleContainer) {
//<debug>
if (!this.$titleContainer.setTitle) {
Ext.Logger.error('You have selected to display a title in a component that does not \
support titles in NavigationView. Please remove the `title` configuration from your \
NavigationView item, or change it to a component that has a `setTitle` method.');
}
//</debug>
this.$titleContainer.setTitle(title);
} else {
this.$currentTitle = title;
}
}, /**
* 移除第一项和最后项之间的所有项(包括最后项)
* @return {Ext.Component} The view that is now active
*/
reset: function () {
return this.pop(this.getInnerItems().length);
}
});
 /**
* This component is used in {@link Ext.navigation.View} to control animations in the toolbar. You should never need to
* interact with the component directly, unless you are subclassing it.
* @private
* @author Robert Dougan <rob@sencha.com>
*/
Ext.define('ux.navigation.Bar', {
extend: 'Ext.TitleBar', requires: ['Ext.Button', 'Ext.Spacer'], // @private
isToolbar: true, config: {
/**
* @cfg
* @inheritdoc
*/
baseCls: Ext.baseCSSPrefix + 'toolbar',
/**
* @cfg {String} ui
* Style options for Toolbar. Either 'light' or 'dark'.
* @accessor
*/
ui: 'dark', /**
* @cfg {String} title
* The title of the toolbar. You should NEVER set this, it is used internally. You set the title of the
* navigation bar by giving a navigation views children a title configuration.
* @private
* @accessor
*/
title: null, /**
* @cfg
* @hide
* @accessor
*/
defaultType: 'button', /**
* @cfg
* @ignore
* @accessor
*/
layout: {
type: 'hbox'
}, /**
* @cfg {Array/Object} items The child items to add to this NavigationBar. The {@link #cfg-defaultType} of
* a NavigationBar is {@link Ext.Button}, so you do not need to specify an `xtype` if you are adding
* buttons.
*
* You can also give items a `align` configuration which will align the item to the `left` or `right` of
* the NavigationBar.
* @hide
* @accessor
*/ /**
* @cfg {String} defaultBackButtonText
* The text to be displayed on the back button if:
* a) The previous view does not have a title
* b) The {@link #useTitleForBackButtonText} configuration is true.
* @private
* @accessor
*/
defaultBackButtonText: '返回', /**
* @cfg {Object} animation
* @private
* @accessor
*/
animation: {
duration: 300
}, /**
* @cfg {Boolean} useTitleForBackButtonText
* Set to false if you always want to display the {@link #defaultBackButtonText} as the text
* on the back button. True if you want to use the previous views title.
* @private
* @accessor
*/
useTitleForBackButtonText: null, /**
* @cfg {Ext.navigation.View} view A reference to the navigation view this bar is linked to.
* @private
* @accessor
*/
view: null, /**
* @cfg {Boolean} androidAnimation Optionally enable CSS transforms on Android 2
* for NavigationBar animations. Note that this may cause flickering if the
* NavigationBar is hidden.
* @accessor
*/
android2Transforms: false, /**
* @cfg {Ext.Button/Object} backButton The configuration for the back button
* @private
* @accessor
*/
backButton: {
align: 'left',
ui: 'back',
hidden: true
},
/*导航栏临时控件组,在子项中配置*/
tmpItems: null,
/*导航栏临时cls,在子项中配置*/
tmpCls: null,
/*是否隐藏返回按钮,在子项中配置*/
backHide: true
}, platformConfig: [{
theme: ['Blackberry'],
animation: false
}], /**
* @event back
* Fires when the back button was tapped.
* @param {Ext.navigation.Bar} this This bar
*/ constructor: function (config) {
config = config || {}; if (!config.items) {
config.items = [];
} this.backButtonStack = [];
this.activeAnimations = []; this.callParent([config]);
},
/*创建导航栏临时控件组*/
applyTmpItems: 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++) {
var item = newItems[i],
fire = item.fire,
btn = me.factoryItem(item);
if (fire) {
btn.on({
tap: 'onTmpItemTap',
scope: me
});
}
navItems.push(me.factoryItem(btn));
}
return navItems;
},
//临时控件被点击时
onTmpItemTap: function (t) {
var me = this,
view = me.getView().getActiveItem(),
fire = t.fire;
view.fireAction(fire, [me, view, t], 'do' + fire);
},
/*更新导航栏临时控件组*/
updateTmpItems: function (newItem, oldItem) {
if (oldItem) {
var i, ln;
for (i = 0, ln = oldItem.length; i < ln; i++) {
this.remove(oldItem[i]);
}
}
if (newItem) {
this.add(newItem);
}
},
/*更新导航栏临时cls*/
updateTmpCls: function (newItem, oldItem) {
if (oldItem) {
this.removeCls(oldItem);
}
if (newItem) {
this.addCls(newItem);
}
},
/**
* @private
*/
applyBackButton: function (config) {
return Ext.factory(config, Ext.Button, this.getBackButton());
}, /**
* @private
*/
updateBackButton: function (newBackButton, oldBackButton) {
if (oldBackButton) {
this.remove(oldBackButton);
} if (newBackButton) {
this.add(newBackButton); newBackButton.on({
scope: this,
tap: this.onBackButtonTap
});
}
}, onBackButtonTap: function () {
this.fireEvent('back', this);
}, /**
* @private
*/
updateView: function (newView) {
var me = this,
backButton = me.getBackButton(),
innerItems,
i,
backButtonText,
item,
title,
titleText,
bar; me.getItems(); if (newView) {
//update the back button stack with the current inner items of the view
innerItems = newView.getInnerItems();
for (i = 0; i < innerItems.length; i++) {
item = innerItems[i];
title = (item.getTitle) ? item.getTitle() : item.config.title;
bar = (item.getBar) ? item.getBar() : item.config.bar; me.backButtonStack.push({
title: title || '&nbsp;',
bar: bar
});
}
titleText = me.getTitleText(); if (titleText === undefined) {
titleText = '';
} me.setTitle(titleText); backButtonText = me.getBackButtonText();
if (backButtonText) {
backButton.setText(backButtonText);
backButton.show();
}
//更新bar
me.updateBar();
}
}, /**
* @private
*/
onViewAdd: function (view, item) {
var me = this,
backButtonStack = me.backButtonStack,
hasPrevious, title, bar; me.endAnimation(); title = (item.getTitle) ? item.getTitle() : item.config.title;
bar = (item.getBar) ? item.getBar() : item.config.bar;
//移除额外的历史记录
var index = (item.getIndex) ? item.getIndex() : item.config.index;
if (Ext.isNumber(index)) {
var length = view.getInnerItems().length,
count = length - index;
me.beforePop(count);
}
backButtonStack.push({
title: title || '&nbsp;',
bar: bar
}); hasPrevious = backButtonStack.length > 1;
me.doChangeView(view, hasPrevious, false);
}, /**
* @private
*/
onViewRemove: function (view) {
var me = this,
backButtonStack = me.backButtonStack,
hasPrevious; me.endAnimation();
backButtonStack.pop();
hasPrevious = backButtonStack.length > 1; me.doChangeView(view, hasPrevious, true);
}, /**
* @private
*/
doChangeView: function (view, hasPrevious, reverse) {
var me = this,
leftBox = me.leftBox,
leftBoxElement = leftBox.element,
titleComponent = me.titleComponent,
titleElement = titleComponent.element,
backButton = me.getBackButton(),
titleText = me.getTitleText(),
backButtonText = me.getBackButtonText(),
animation = me.getAnimation() && view.getLayout().getAnimation(),
animated = animation && animation.isAnimation && view.isPainted(),
properties,
leftGhost,
titleGhost,
leftProps,
titleProps; if (animated) {
leftGhost = me.createProxy(leftBox.element);
leftBoxElement.setStyle('opacity', '0');
backButton.setText(backButtonText);
backButton[hasPrevious ? 'show' : 'hide'](); titleGhost = me.createProxy(titleComponent.element.getParent());
titleElement.setStyle('opacity', '0');
me.setTitle(titleText); properties = me.measureView(leftGhost, titleGhost, reverse);
leftProps = properties.left;
titleProps = properties.title; me.isAnimating = true;
me.animate(leftBoxElement, leftProps.element);
me.animate(titleElement, titleProps.element,
function () {
titleElement.setLeft(properties.titleLeft);
me.isAnimating = false;
me.refreshTitlePosition();
}); if (Ext.browser.is.AndroidStock2 && !this.getAndroid2Transforms()) {
leftGhost.ghost.destroy();
titleGhost.ghost.destroy();
} else {
me.animate(leftGhost.ghost, leftProps.ghost);
me.animate(titleGhost.ghost, titleProps.ghost,
function () {
leftGhost.ghost.destroy();
titleGhost.ghost.destroy();
});
} } else {
if (hasPrevious) {
backButton.setText(backButtonText);
backButton.show();
} else {
backButton.hide();
}
me.setTitle(titleText);
}
me.updateBar();
},
//更新bar
updateBar: function () {
//更新其他
var bar = this.getBar() || {};
//设置导航栏临时控件组
this.setTmpItems(bar.items);
//设置导航栏临时cls
this.setTmpCls(bar.cls);
//更新返回按钮状态
if (bar.backHide) {
backButton.hide();
}
},
/**
* Calculates and returns the position values needed for the back button when you are pushing a title.
* @private
*/
measureView: function (oldLeft, oldTitle, reverse) {
var me = this,
barElement = me.element,
newLeftElement = me.leftBox.element,
titleElement = me.titleComponent.element,
minOffset = Math.min(barElement.getWidth() / 3, 200),
newLeftWidth = newLeftElement.getWidth(),
barX = barElement.getX(),
barWidth = barElement.getWidth(),
titleX = titleElement.getX(),
titleLeft = titleElement.getLeft(),
titleWidth = titleElement.getWidth(),
oldLeftX = oldLeft.x,
oldLeftWidth = oldLeft.width,
oldLeftLeft = oldLeft.left,
useLeft = Ext.browser.is.AndroidStock2 && !this.getAndroid2Transforms(),
newOffset,
oldOffset,
leftAnims,
titleAnims,
omega,
theta; theta = barX - oldLeftX - oldLeftWidth;
if (reverse) {
newOffset = theta;
oldOffset = Math.min(titleX - oldLeftWidth, minOffset);
} else {
oldOffset = theta;
newOffset = Math.min(titleX - barX, minOffset);
} if (useLeft) {
leftAnims = {
element: {
from: {
left: newOffset,
opacity: 1
},
to: {
left: 0,
opacity: 1
}
}
};
} else {
leftAnims = {
element: {
from: {
transform: {
translateX: newOffset
},
opacity: 0
},
to: {
transform: {
translateX: 0
},
opacity: 1
}
},
ghost: {
to: {
transform: {
translateX: oldOffset
},
opacity: 0
}
}
};
} theta = barX - titleX + newLeftWidth;
if ((oldLeftLeft + titleWidth) > titleX) {
omega = barX - titleX - titleWidth;
} if (reverse) {
titleElement.setLeft(0); oldOffset = barX + barWidth - titleX - titleWidth; if (omega !== undefined) {
newOffset = omega;
} else {
newOffset = theta;
}
} else {
newOffset = barX + barWidth - titleX - titleWidth; if (omega !== undefined) {
oldOffset = omega;
} else {
oldOffset = theta;
} newOffset = Math.max(titleLeft, newOffset);
} if (useLeft) {
titleAnims = {
element: {
from: {
left: newOffset,
opacity: 1
},
to: {
left: titleLeft,
opacity: 1
}
}
};
} else {
titleAnims = {
element: {
from: {
transform: {
translateX: newOffset
},
opacity: 0
},
to: {
transform: {
translateX: titleLeft
},
opacity: 1
}
},
ghost: {
to: {
transform: {
translateX: oldOffset
},
opacity: 0
}
}
};
} return {
left: leftAnims,
title: titleAnims,
titleLeft: titleLeft
};
}, /**
* Helper method used to animate elements.
* You pass it an element, objects for the from and to positions an option onEnd callback called when the animation is over.
* Normally this method is passed configurations returned from the methods such as #measureTitle(true) etc.
* It is called from the #pushLeftBoxAnimated, #pushTitleAnimated, #popBackButtonAnimated and #popTitleAnimated
* methods.
*
* If the current device is Android, it will use top/left to animate.
* If it is anything else, it will use transform.
* @private
*/
animate: function (element, config, callback) {
var me = this,
animation; //reset the left of the element
element.setLeft(0); config = Ext.apply(config, {
element: element,
easing: 'ease-in-out',
duration: me.getAnimation().duration || 250,
preserveEndState: true
}); animation = new Ext.fx.Animation(config);
animation.on('animationend',
function () {
if (callback) {
callback.call(me);
}
},
me); Ext.Animator.run(animation);
me.activeAnimations.push(animation);
}, endAnimation: function () {
var activeAnimations = this.activeAnimations,
animation, i, ln; if (activeAnimations) {
ln = activeAnimations.length;
for (i = 0; i < ln; i++) {
animation = activeAnimations[i];
if (animation.isAnimating) {
animation.stopAnimation();
} else {
animation.destroy();
}
}
this.activeAnimations = [];
}
}, refreshTitlePosition: function () {
if (!this.isAnimating) {
this.callParent();
}
}, /**
* Returns the text needed for the current back button at anytime.
* @private
*/
getBackButtonText: function () {
var text = this.backButtonStack[this.backButtonStack.length - 2],
useTitleForBackButtonText = this.getUseTitleForBackButtonText(); if (!useTitleForBackButtonText) {
if (text) {
text = this.getDefaultBackButtonText();
}
} return text;
}, /**
* Returns the text needed for the current title at anytime.
* @private
*/
getTitleText: function () {
if (this.backButtonStack.length == 0) {
return '';
}
return this.backButtonStack[this.backButtonStack.length - 1].title;
},
getBar: function () {
if (this.backButtonStack.length == 0) {
return false;
}
return this.backButtonStack[this.backButtonStack.length - 1].bar;
},
/**
* Handles removing back button stacks from this bar
* @private
*/
beforePop: function (count) {
count--;
for (var i = 0; i < count; i++) {
this.backButtonStack.pop();
}
}, /**
* 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
* the screen, much like the navigation bar proxy. This means that all animations, pushing, popping etc. all still work when if you hide/show
* this bar at any time.
* @private
*/
doSetHidden: function (hidden) {
if (!hidden) {
this.element.setStyle({
position: 'relative',
top: 'auto',
left: 'auto',
width: 'auto'
});
} else {
this.element.setStyle({
position: 'absolute',
top: '-1000px',
left: '-1000px',
width: this.element.getWidth() + 'px'
});
}
}, /**
* Creates a proxy element of the passed element, and positions it in the same position, using absolute positioning.
* The createNavigationBarProxy method uses this to create proxies of the backButton and the title elements.
* @private
*/
createProxy: function (element) {
var ghost, x, y, left, width; ghost = element.dom.cloneNode(true);
ghost.id = element.id + '-proxy'; //insert it into the toolbar
element.getParent().dom.appendChild(ghost); //set the x/y
ghost = Ext.get(ghost);
x = element.getX();
y = element.getY();
left = element.getLeft();
width = element.getWidth();
ghost.setStyle('position', 'absolute');
ghost.setX(x);
ghost.setY(y);
ghost.setHeight(element.getHeight());
ghost.setWidth(width); return {
x: x,
y: y,
left: left,
width: width,
ghost: ghost
};
}
});

sencha touch 扩展官方NavigationView 灵活添加按钮组,导航栏,自由隐藏返回按钮(2014-5-15)的更多相关文章

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

    最新版本我将会放在:http://www.cnblogs.com/mlzs/p/3382229.html这里的示例里面,这里不会再做更新 代码: /* *模仿且改进NavigationView *返回 ...

  2. iOS10 的适配问题,你遇到了吗?导航栏标题和返回按钮神奇的消失了

    苹果系统升级后好多应用都发了新版本来适配,今天就来分享一下我的适配历程. 首先是出现的问题: 1.push一个控制器,返回按钮和标题神奇的消失了,打开三维视图(比较坑的是有的版本老到打不开三维视图 ) ...

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

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

  4. Bootstrap框架(基础篇)之按钮,网格,导航栏,下拉菜单

    一,按钮 注意:虽然在Bootstrap框架中使用任何标签元素都可以实现按钮风格,但个人并不建议这样使用,为了避免浏览器兼容性问题,个人强烈建议使用button或a标签来制作按钮. 框架中提供了基础按 ...

  5. iOS -- 隐藏返回按钮

    // 隐藏返回按钮 [self.navigationItem setHidesBackButton:YES];

  6. flutter 隐藏返回按钮 自定义返回按钮

    自定义返回按钮 //改变颜色 Widget build(BuildContext context) { return Scaffold( appBar: AppBar( leading: BackBu ...

  7. sencha touch 扩展篇之使用sass自定义主题样式 (上)使用官方的api修改主题样式

    大家知道,sencha touch是通过我们写的js代码来动态渲染单页面生成一个个div+css的html页面来模拟app应用,那么既然是div+css结构的,我们就可以通过修改css样式来自定义我们 ...

  8. sencha touch 扩展篇之使用sass自定义主题样式 (下)通过css修改官方组件样式以及自定义图标

    上一讲我们讲解了如何使用官方的api来修改主题样式,这讲我们继续讲解sass的样式修改, 编译官方自带的主题包  在生成的项目以及官方sdk的目录下,自带了一些主题sass包,我们也可以通过修改sas ...

  9. Sencha Touch 扩展集合

    https://market.sencha.com/extensions http://try.sencha.com/touch/2.1.0/ http://www.mitchellsimoens.c ...

随机推荐

  1. Mysql:This version of MySQL doesn’t yet support ‘LIMIT & IN/ALL/ANY/SOME 错误解决

    From: http://blog.chinaunix.net/uid-22414998-id-2945656.html This version of MySQL doesn’t yet suppo ...

  2. 令人惊叹的HTML5动画及源码分析下载

    HTML5非常酷,利用HTML5制作动画简直让我们忘记了这世界上还有flash的存在.今天我们要分享的一些HTML5动画都还不错,有些动画设计还是挺别出心裁的.另外,每一款HTML5动画都提供源代码下 ...

  3. python2除法保留小数部分

    转载:http://www.cnblogs.com/yhleng/p/9223944.html 1.python2和python3除法的最大区别: python2: print 500/1000 py ...

  4. linux cfs调度器

    在抽象模型中vruntime决定了进程被调度的先后顺序,在真实模型中决定被调度的先后顺序的参数是由函数entity_key决定的.   static inline s64 entity_key(str ...

  5. 设计模式之初识IoC/DI(六)

    本篇和大家一起学习IoC和DI即控制反转和依赖注入. 当然听上去这词语非常的专业,真不知道是怎么组出来的,看上去难归看上去难,但稍微理解一下也就这么回事了. 首先我们要明白IoC/DI干嘛用的,不然别 ...

  6. springmvc表单验证

    http://blog.csdn.net/daryl715/article/details/1645880 http://blog.csdn.net/shuwei003/article/details ...

  7. Fade out transition effect using CSS3

    摘要: css3已经被应用到很多网站了,对于创建动态交互的网站是非常有益的.今天就分享一个使用transition实现的鼠标悬停淡阴淡出的效果. 代码: <!DOCTYPE html> & ...

  8. kendo-ui表单验证

    摘要: 表单验证是每一个项目必不可少的,他能够帮助我们过滤不正确的用户输入,保证系统数据正确.例如下面这样: kendo-ui也有自己的表单验证方法,下面就分享下kendo-ui的表单验证方式. 基本 ...

  9. VS2017 Pro未能找到路径“……\bin\roslyn\csc.exe”的解决方案

    VS2017改用roslyn编译的,新的roslyn编译器,支持c# 6.0语法.它放到bin里面去是为了支持asp.net应用的动态编译. 它是通过nuget的包Microsoft.CodeDom. ...

  10. SpringMVC由浅入深day01_12参数绑定(12.1参数绑定过程_12.2默认支持的类型_12.3简单类型)

    12 参数绑定 处理器适配器在执行Handler之前需要把http请求的key/value数据绑定到Handler方法形参数上. 注解适配器对RequestMapping标记的方法进行适配,对方法中的 ...