Onsen UIを使ってスワイプで切り替えられるタブを実装する

Onsen UIのカルーセルを使って、スワイプで切り替えるタブを作ってみました。

サンプルコード

タブとカルーセル部分はng-repeatで表示するようにしています。

HTML

<ons-navigator var="myNavigator">
	<ons-page>
		<div class="contents">
			<div class="tab-switch">
				<div class="tab-switch_inner" ng-style="tabPoint">
					<div class="tab-switch_item" ng-repeat="belong in belongData.belongs" ng-click="changeTab($index)" ng-class="{active: belong.isActive}">{{belong.name}}</div>
				</div>
			</div>
			<ons-carousel var="tab" swipeable auto-scroll ng-style="tabHeight">
				<ons-carousel-item ng-repeat="belong in belongData.belongs">
					<ons-list>
						<ons-list-header>{{belong.name}}</ons-list-header>
						<ons-list-item ng-repeat="actor in actorData.actors | filter:{ belong: belong.name }">{{actor.name}}</ons-list-item>
					</ons-list>
				</ons-carousel-item>
			</ons-carousel>
		</div>
	</ons-page>
</ons-navigator>

CSS

.contents {
	max-width: 640px;
	margin: 0 auto;
}
.tab-switch {
	overflow-x: auto;
}
.tab-switch_inner {
	display: table;
	position: relative;
}
.tab-switch_item {
	display: table-cell;
	overflow: hidden;
	padding: 5px;
	border-left: #ccc 1px solid;
	white-space: nowrap;
	text-overflow: ellipsis;
	max-width: 100px;
	cursor: pointer;
}
.tab-switch_item.active {
	background: #999;
}
ons-carousel-item {
	height: auto !important;
}

JavaScript

var app = angular.module('app', ['onsen']);
app.controller('app_Ctrl', function($scope, $timeout, $http) {
	$scope.belongData = '';
	$scope.actorData = '';
	$scope.tabHeight = {};

	// jsonデータの取得
	$http.get('belongData.json').success(function(data) {
		// 1番目のタブを選択した状態にする
		data['belongs'][0]['isActive'] = true;
		// 取得したデータを格納
		$scope.belongData = data;

		$timeout(function() {
			// タブの更新
			tab.refresh();
		});
	}).error(function() {
		alert('取得失敗');
	});
	$http.get('actorData.json').success(function(data) {
		// 取得したデータを格納
		$scope.actorData = data;

		$timeout(function() {
			// タブの更新
			tab.refresh();
			// カルーセルの高さを設定
			$scope.tabHeight = {
				height: document.getElementsByTagName('ons-carousel-item')[0].clientHeight + 'px'
			};
		});
	}).error(function() {
		alert('取得失敗');
	});

	// タブをクリックしたとき
	$scope.changeTab = function(index) {
		tab.setActiveCarouselItemIndex(index);
	}

	// タブのスクロール位置の設定
	$scope.tabPoint = {
		left: '0px'
	};

	ons.ready(function() {
		// カルーセルに変更があったとき
		tab.on('postchange', function(e) {
			// タブ部分の移動可能な範囲
			var difference = document.getElementsByClassName('tab-switch_inner')[0].clientWidth - document.getElementsByClassName('tab-switch')[0].clientWidth;
			// タブのスクロール位置
			var scrollPoint = (difference / ($scope.belongData['belongs'].length - 1) * e.activeIndex);

			$timeout(function() {
				// activeの解除と設定
				$scope.belongData['belongs'][e.lastActiveIndex]['isActive'] = false;
				$scope.belongData['belongs'][e.activeIndex]['isActive'] = true;

				// タブのスクロール位置の設定
				$scope.tabPoint = {
					left: -scrollPoint + 'px'
				};

				// タブの高さ変更
				$scope.tabHeight = {
					height: document.getElementsByTagName('ons-carousel-item')[e.activeIndex].clientHeight + 'px'
				};
			});
		});
	});
});

タブとコンテンツ部分の内容はjsonから取得するようにしています。

belongData.json

{
	"belongs": [
		{
			"name": "81プロデュース",
			"isActive": false
		},
		~ 略 ~
		{
			"name": "大沢事務所",
			"isActive": false
		}
	]
}

actorData.json

{
	"actors": [
		{
			"name": "高橋 李依",
			"kana_en": "takahashi rie",
			"kana_jp": "たかはし りえ",
			"birthday": "1994.2.27",
			"belong": "81プロデュース"
		}, 
		~ 略 ~
		{
			"name": "早見 沙織",
			"kana_en": "hayami saori",
			"kana_jp": "はやみ さおり",
			"birthday": "1991.5.29",
			"belong": "アイムエンタープライズ"
		}
	]
}

スワイプで切り替えるタブのデモページ
 

このエントリーをはてなブックマークに追加

関連記事

コメントを残す

メールアドレスが公開されることはありません。
* が付いている欄は必須項目です

CAPTCHA


コメントが承認されるまで時間がかかります。

2024年4月
 123456
78910111213
14151617181920
21222324252627
282930