mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
feat(platforms): Android and iOS Specific Styles and Transitions
This commit is contained in:
114
test/html/nav.html
Normal file
114
test/html/nav.html
Normal file
@@ -0,0 +1,114 @@
|
||||
<html ng-app="nav">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||
|
||||
<title>navViews and ion-tabs w/ nested navViews</title>
|
||||
|
||||
<link rel="stylesheet" href="../../../../dist/css/ionic.css">
|
||||
<script src="../../../../dist/js/ionic.bundle.js"></script>
|
||||
<script src="dom-trace.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div>
|
||||
<ion-nav-bar class="bar-positive">
|
||||
<ion-nav-back-button class="button-icon" from-title>
|
||||
</ion-nav-back-button>
|
||||
</ion-nav-bar>
|
||||
<ion-nav-view></ion-nav-view>
|
||||
</div>
|
||||
|
||||
<script id="page1.html" type="text/ng-template">
|
||||
<ion-view title="Page 1">
|
||||
<ion-nav-buttons side="right">
|
||||
<button class="button button-icon ion-android-search"></button>
|
||||
<button class="button button-icon ion-android-information"></button>
|
||||
<button class="button button-icon ion-android-share"></button>
|
||||
</ion-nav-buttons>
|
||||
<ion-content padding="true">
|
||||
<ion-list>
|
||||
<div class="item item-divider">
|
||||
Things
|
||||
</div>
|
||||
<ion-item ng-repeat="item in items" href="#/page2">
|
||||
Item {{$index}}
|
||||
</ion-item>
|
||||
<div class="item item-divider">
|
||||
Stuff
|
||||
</div>
|
||||
<ion-item ng-repeat="item in items2" href="#/page2">
|
||||
Item {{$index}}
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
</ion-content>
|
||||
</ion-view>
|
||||
</script>
|
||||
<script id="page2.html" type="text/ng-template">
|
||||
<ion-view title="Page 2">
|
||||
<ion-content padding="true">
|
||||
<a ng-click="goBack()" class="button button-positive">Back</a>
|
||||
<a href="#/page3" class="button button-positive">Page 3</a>
|
||||
</ion-content>
|
||||
</ion-view>
|
||||
</script>
|
||||
<script id="page3.html" type="text/ng-template">
|
||||
<ion-view title="Page 3">
|
||||
<ion-content padding="true">
|
||||
<a ng-click="goBack()" class="button button-positive">Back</a>
|
||||
<a href="#/page1" class="button button-positive">Page 1</a>
|
||||
</ion-content>
|
||||
</ion-view>
|
||||
</script>
|
||||
<script>
|
||||
angular.module('nav', ['ionic'])
|
||||
|
||||
.config(function($stateProvider, $urlRouterProvider) {
|
||||
|
||||
$stateProvider
|
||||
.state('page1', {
|
||||
url: "/page1",
|
||||
templateUrl: "page1.html",
|
||||
controller: 'Page1Ctrl'
|
||||
})
|
||||
.state('page2', {
|
||||
url: "/page2",
|
||||
templateUrl: "page2.html",
|
||||
controller: 'Page2Ctrl'
|
||||
})
|
||||
.state('page3', {
|
||||
url: "/page3",
|
||||
templateUrl: "page3.html",
|
||||
controller: 'Page3Ctrl'
|
||||
})
|
||||
|
||||
$urlRouterProvider.otherwise("/page1");
|
||||
})
|
||||
|
||||
.controller('Page1Ctrl', function($scope) {
|
||||
$scope.items = [];
|
||||
for(var i = 0; i < 4; i++) {
|
||||
$scope.items.push({});
|
||||
}
|
||||
|
||||
$scope.items2 = [];
|
||||
for(var i = 0; i < 4; i++) {
|
||||
$scope.items2.push({});
|
||||
}
|
||||
})
|
||||
|
||||
.controller('Page2Ctrl', function($scope, $ionicNavBarDelegate) {
|
||||
$scope.goBack = function() {
|
||||
$ionicNavBarDelegate.back();
|
||||
};
|
||||
})
|
||||
|
||||
.controller('Page3Ctrl', function($scope, $ionicNavBarDelegate) {
|
||||
$scope.goBack = function() {
|
||||
$ionicNavBarDelegate.back();
|
||||
};
|
||||
})
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -8,130 +8,155 @@
|
||||
|
||||
<link rel="stylesheet" href="../../../../dist/css/ionic.css">
|
||||
<script src="../../../../dist/js/ionic.bundle.js"></script>
|
||||
<link href='http://fonts.googleapis.com/css?family=Roboto:400,100,100italic,300,300italic,400italic,500,500italic,700,700italic,900,900italic' rel='stylesheet' type='text/css'>
|
||||
<style>
|
||||
/**
|
||||
* Some component specific animations
|
||||
*/
|
||||
.nav-title-fade-only:not(.no-animation) .button.back-button {
|
||||
-webkit-transition: all 340ms;
|
||||
-moz-transition: all 340ms;
|
||||
transition: all 340ms;
|
||||
-webkit-transition-timing-function: cubic-bezier(0.4, 0.6, 0.2, 1);
|
||||
-moz-transition-timing-function: cubic-bezier(0.4, 0.6, 0.2, 1);
|
||||
transition-timing-function: cubic-bezier(0.4, 0.6, 0.2, 1);
|
||||
opacity: 1; }
|
||||
.nav-title-fade-only:not(.no-animation) .button.back-button.active, .nav-title-fade-only:not(.no-animation) .button.back-button.activated {
|
||||
opacity: 0.5; }
|
||||
.nav-title-fade-only:not(.no-animation) .button.back-button.ng-hide {
|
||||
opacity: 0; }
|
||||
.nav-title-fade-only:not(.no-animation) .button.back-button.ng-hide-add, .nav-title-fade-only:not(.no-animation) .button.back-button.ng-hide-remove {
|
||||
display: block !important; }
|
||||
.nav-title-fade-only:not(.no-animation) .button.back-button.ng-hide-add {
|
||||
position: absolute; }
|
||||
.nav-title-fade-only > .ng-enter, .nav-title-fade-only.ng-enter, .nav-title-fade-only > .ng-leave, .nav-title-fade-only.ng-leave {
|
||||
-webkit-transition: all 340ms;
|
||||
-moz-transition: all 340ms;
|
||||
transition: all 340ms;
|
||||
-webkit-transition-timing-function: cubic-bezier(0.4, 0.6, 0.2, 1);
|
||||
-moz-transition-timing-function: cubic-bezier(0.4, 0.6, 0.2, 1);
|
||||
transition-timing-function: cubic-bezier(0.4, 0.6, 0.2, 1);
|
||||
opacity: 1; }
|
||||
.nav-title-fade-only > .ng-enter, .nav-title-fade-only.ng-enter {
|
||||
opacity: 0; }
|
||||
.nav-title-fade-only > .ng-enter.ng-enter-active, .nav-title-fade-only.ng-enter.ng-enter-active {
|
||||
opacity: 1; }
|
||||
.nav-title-fade-only > .ng-leave.ng-leave-active, .nav-title-fade-only.ng-leave.ng-leave-active {
|
||||
opacity: 0; }
|
||||
.nav-title-fade-only.reverse > .ng-enter, .nav-title-fade-only.reverse.ng-enter, .nav-title-fade-only.reverse > .ng-leave, .nav-title-fade-only.reverse.ng-leave {
|
||||
-webkit-transition: all 340ms;
|
||||
-moz-transition: all 340ms;
|
||||
transition: all 340ms;
|
||||
-webkit-transition-timing-function: cubic-bezier(0.4, 0.6, 0.2, 1);
|
||||
-moz-transition-timing-function: cubic-bezier(0.4, 0.6, 0.2, 1);
|
||||
transition-timing-function: cubic-bezier(0.4, 0.6, 0.2, 1);
|
||||
opacity: 1; }
|
||||
.nav-title-fade-only.reverse > .ng-enter, .nav-title-fade-only.reverse.ng-enter {
|
||||
opacity: 0; }
|
||||
.nav-title-fade-only.reverse > .ng-enter.ng-enter-active, .nav-title-fade-only.reverse.ng-enter.ng-enter-active {
|
||||
opacity: 1; }
|
||||
.nav-title-fade-only.reverse > .ng-leave.ng-leave-active, .nav-title-fade-only.reverse.ng-leave.ng-leave-active {
|
||||
opacity: 0; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div ng-controller="AppCtrl">
|
||||
<ion-nav-bar class="nav-title-slide-ios7 bar-positive">
|
||||
<ion-nav-back-button class="button-icon icon ion-ios7-arrow-back">
|
||||
Back
|
||||
</ion-nav-back-button>
|
||||
</ion-nav-bar>
|
||||
<ion-nav-view animation="slide-left-right-ios7"></ion-nav-view>
|
||||
<ion-nav-view></ion-nav-view>
|
||||
</div>
|
||||
|
||||
<script id="home.html" type="text/ng-template">
|
||||
<ion-view title="Home">
|
||||
<!--
|
||||
<ion-nav-buttons side="left">
|
||||
<button
|
||||
class="button button-icon icon ion-navicon"
|
||||
menu-toggle="left">
|
||||
</button>
|
||||
</ion-nav-buttons>
|
||||
<ion-nav-buttons side="right">
|
||||
<button
|
||||
class="button button-icon icon ion-close-circled"
|
||||
ng-click="requestClearNotifications()">
|
||||
</button>
|
||||
<button
|
||||
class="button button-icon icon ion-alert-circled"
|
||||
ng-show="$root.showButton">
|
||||
</button>
|
||||
</ion-nav-buttons>
|
||||
-->
|
||||
|
||||
<ion-nav-bar class="bar-positive">
|
||||
<ion-nav-back-button class="button-icon icon ion-ios7-arrow-back">
|
||||
Back
|
||||
</ion-nav-back-button>
|
||||
</ion-nav-bar>
|
||||
<ion-content>
|
||||
<a href="#/friends" class="button button-block button-primary">Friends</a>
|
||||
<div class="list">
|
||||
<a href="#/about" class="button button-block button-primary">Friends</a>
|
||||
<div class="list">
|
||||
|
||||
<label class="item item-input item-select">
|
||||
<div class="input-label">
|
||||
Lightsaber
|
||||
</div>
|
||||
<select>
|
||||
<option>Blue</option>
|
||||
<option selected>Green</option>
|
||||
<option>Red</option>
|
||||
</select>
|
||||
</label>
|
||||
<label class="item item-input item-select">
|
||||
<div class="input-label">
|
||||
Lightsaber
|
||||
</div>
|
||||
<select>
|
||||
<option>Blue</option>
|
||||
<option selected>Green</option>
|
||||
<option>Red</option>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-view>
|
||||
</script>
|
||||
|
||||
<script id="friends.html" type="text/ng-template">
|
||||
<ion-view title="Friends">
|
||||
<!--
|
||||
<ion-nav-buttons side="left">
|
||||
<button
|
||||
class="button button-icon icon ion-navicon"
|
||||
menu-toggle="left">
|
||||
</button>
|
||||
</ion-nav-buttons>
|
||||
<ion-nav-buttons side="right">
|
||||
<button
|
||||
class="button button-icon icon ion-close-circled"
|
||||
ng-click="requestClearNotifications()">
|
||||
</button>
|
||||
<button
|
||||
class="button button-icon icon ion-alert-circled"
|
||||
ng-show="$root.showButton">
|
||||
</button>
|
||||
</ion-nav-buttons>
|
||||
-->
|
||||
|
||||
<ion-nav-bar class="bar-positive">
|
||||
<ion-nav-back-button class="button-icon icon ion-ios7-arrow-back">
|
||||
Back
|
||||
</ion-nav-back-button>
|
||||
</ion-nav-bar>
|
||||
<ion-content>
|
||||
<div class="list">
|
||||
<div class="list">
|
||||
|
||||
<label class="item item-input item-select">
|
||||
<div class="input-label">
|
||||
Lightsaber
|
||||
</div>
|
||||
<select>
|
||||
<option>Blue</option>
|
||||
<option selected>Green</option>
|
||||
<option>Red</option>
|
||||
</select>
|
||||
</label>
|
||||
<label class="item item-input item-select">
|
||||
<div class="input-label">
|
||||
Lightsaber
|
||||
</div>
|
||||
<select>
|
||||
<option>Blue</option>
|
||||
<option selected>Green</option>
|
||||
<option>Red</option>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-view>
|
||||
</script>
|
||||
|
||||
<script id="about.html" type="text/ng-template">
|
||||
<ion-view title="Home">
|
||||
<!--
|
||||
<ion-nav-buttons side="left">
|
||||
<button
|
||||
class="button button-icon icon ion-navicon"
|
||||
menu-toggle="left">
|
||||
</button>
|
||||
</ion-nav-buttons>
|
||||
<ion-nav-buttons side="right">
|
||||
<button
|
||||
class="button button-icon icon ion-close-circled"
|
||||
ng-click="requestClearNotifications()">
|
||||
</button>
|
||||
<button
|
||||
class="button button-icon icon ion-alert-circled"
|
||||
ng-show="$root.showButton">
|
||||
</button>
|
||||
</ion-nav-buttons>
|
||||
-->
|
||||
<ion-tabs
|
||||
class="tabs-icon-only tabs-positive"
|
||||
animation="fade-in-out"
|
||||
controller-changed="onControllerChanged(oldController, oldIndex, newController, newIndex)">
|
||||
|
||||
<ion-content>
|
||||
<h1>About</h1>
|
||||
</ion-content>
|
||||
<ion-tab title="Home" icon="ion-home">
|
||||
<header class="bar bar-header bar-positive">
|
||||
<h1 class="title"><i class="icon ion-android-book"></i> Read Now</h1>
|
||||
</header>
|
||||
<ion-content class="has-header has-subheader" on-refresh="onRefresh()" on-scroll="scroll(scrollTop, scrollLeft)">
|
||||
</ion-content>
|
||||
</ion-tab>
|
||||
<ion-tab title="Friends" icon="ion-search">
|
||||
<header class="bar bar-header bar-positive">
|
||||
<h1 class="title">Friends</h1>
|
||||
</header>
|
||||
<ion-content class="has-header has-subheader" on-refresh="onRefresh()" on-scroll="scroll(scrollTop, scrollLeft)">
|
||||
</ion-content>
|
||||
</ion-tab>
|
||||
<ion-tab title="About" icon="ion-heart">
|
||||
<header class="bar bar-header bar-positive">
|
||||
<h1 class="title">About</h1>
|
||||
</header>
|
||||
<ion-content class="has-header has-subheader" on-refresh="onRefresh()" on-scroll="scroll(scrollTop, scrollLeft)">
|
||||
</ion-content>
|
||||
</ion-tab>
|
||||
</ion-tabs>
|
||||
</ion-view>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
angular.module('navState', ['ionic'])
|
||||
|
||||
|
||||
.config(function($ionicTabsConfig) {
|
||||
$ionicTabsConfig.tabsPosition = '';
|
||||
//$ionicNavBarConfig.transition = 'nav-title-fade-only';
|
||||
})
|
||||
.config(function($stateProvider, $urlRouterProvider) {
|
||||
|
||||
$stateProvider
|
||||
|
||||
@@ -92,7 +92,8 @@ describe('bar directives', function() {
|
||||
function setup(attrs) {
|
||||
var el;
|
||||
ionic.views.HeaderBar = function(opts) {
|
||||
this.opts = opts;
|
||||
this.alignTitle = opts.alignTitle;
|
||||
this.el = opts.el;
|
||||
this.align = jasmine.createSpy('align');
|
||||
};
|
||||
inject(function($compile, $rootScope) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
describe('ionNavBackButton directive', function() {
|
||||
beforeEach(module('ionic'));
|
||||
|
||||
@@ -76,4 +77,29 @@ describe('ionNavBackButton directive', function() {
|
||||
expect(el.scope().$navBack).not.toHaveBeenCalled();
|
||||
expect(el.scope().doSomething).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
describe('ionNavBackButton directive: Platforms', function() {
|
||||
describe('ionNavBackButton directive: iOS Platform', function() {
|
||||
beforeEach(function($provide) {
|
||||
TestUtil.setPlatform('ios');
|
||||
});
|
||||
|
||||
it('Should set default back button icon from ionicNavBarConfig ', inject(function($ionicNavBarConfig) {
|
||||
var el = setup();
|
||||
expect(el.hasClass('ion-ios7-arrow-back')).toBe(true);
|
||||
}));
|
||||
});
|
||||
|
||||
describe('ionNavBackButton directive: Android Platform', function() {
|
||||
beforeEach(function($provide) {
|
||||
TestUtil.setPlatform('android');
|
||||
});
|
||||
|
||||
it('Should set default back button icon from ionicNavBarConfig ', inject(function($ionicNavBarConfig) {
|
||||
var el = setup();
|
||||
expect(el.hasClass('ion-android-arrow-back')).toBe(true);
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -294,4 +294,60 @@ describe('ionNavBar', function() {
|
||||
expect(el.hasClass('reverse')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('platforms', function() {
|
||||
function setup(attrs, content) {
|
||||
var el;
|
||||
inject(function($compile, $rootScope) {
|
||||
el = $compile('<ion-nav-bar '+(attrs||'')+'>'+(content||'')+'</ion-nav-bar>')($rootScope.$new());
|
||||
$rootScope.$apply();
|
||||
});
|
||||
return el;
|
||||
}
|
||||
|
||||
describe('iOS', function() {
|
||||
beforeEach(module('ionic', function($provide) {
|
||||
TestUtil.setPlatform('ios');
|
||||
$provide.constant('$ionicNavBarConfig', {
|
||||
alignTitle: 'center',
|
||||
transition: 'nav-title-slide-ios7',
|
||||
backButtonIcon: 'ion-ios7-arrow-back'
|
||||
});
|
||||
}));
|
||||
|
||||
it('should have correct title align', function() {
|
||||
var el = setup();
|
||||
var controller = el.controller('ionNavBar');
|
||||
expect(controller._headerBarView.alignTitle).toBe('center');
|
||||
});
|
||||
|
||||
it('Should have correct transition', function() {
|
||||
var el = setup();
|
||||
expect(el.hasClass('nav-title-slide-ios7')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Android', function() {
|
||||
beforeEach(module('ionic', function($provide) {
|
||||
TestUtil.setPlatform('android');
|
||||
$provide.constant('$ionicNavBarConfig', {
|
||||
alignTitle: 'left',
|
||||
transition: 'no-animation',
|
||||
backButtonIcon: 'ion-android-back'
|
||||
});
|
||||
}));
|
||||
|
||||
it('should have correct title align', function() {
|
||||
var el = setup();
|
||||
var controller = el.controller('ionNavBar');
|
||||
expect(controller._headerBarView.alignTitle).toBe('left');
|
||||
});
|
||||
|
||||
it('Should have correct transition', function() {
|
||||
var el = setup();
|
||||
// Nav bar titles don't animation by default on Android
|
||||
expect(el.hasClass('no-animation')).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -260,6 +260,35 @@ describe('tabs', function() {
|
||||
var el = setup('', '<div class="content"></div>');
|
||||
expect(el[0].querySelector('.tabs .content')).toBeTruthy();
|
||||
});
|
||||
|
||||
describe('platform Styles', function() {
|
||||
describe('iOS', function() {
|
||||
beforeEach(module('ionic', function($provide) {
|
||||
TestUtil.setPlatform('ios');
|
||||
$provide.constant('$ionicTabsConfig', {
|
||||
type: ''
|
||||
});
|
||||
}));
|
||||
|
||||
it('should set iOS style', function() {
|
||||
var el = setup();
|
||||
expect(el.hasClass('tabs-striped')).not.toBe(true);
|
||||
});
|
||||
});
|
||||
describe('android', function() {
|
||||
beforeEach(module('ionic', function($provide) {
|
||||
TestUtil.setPlatform('android');
|
||||
$provide.constant('$ionicTabsConfig', {
|
||||
type: 'tabs-striped'
|
||||
});
|
||||
}));
|
||||
|
||||
it('should set Android style', function() {
|
||||
var el = setup();
|
||||
expect(el.hasClass('tabs-striped')).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('ionicTab controller', function() {
|
||||
|
||||
Reference in New Issue
Block a user