转载请注明出处:
http://blog.youkuaiyun.com/lishihong108/article/details/53422950
在ionic项目中怎么实现城市选择A-Z字母索引列表呢?效果图如下所示:
可以看到搜索框可以直接过滤搜索对应的城市;右侧点击或滑动对一个的字母,左侧滚动到对应的位置,接下来详细介绍怎么实现。
首先说下布局:
右边的字母栏是绝对定位过去的,通过计算屏幕高度来做适配,保证在任意屏幕的手机上都会均等显示。
html代码如下:
<ion-view view-title="城市选择" style="background:#fff;">
<ion-nav-buttons side="left">
<div style="width:32px;padding-left:2px;" ng-click="$ionicGoBack()">
<i class="icon ion-ios-arrow-left" style="color:#828a99;font-size:32px;line-height:32px;"></i>
</div>
</ion-nav-buttons>
<ion-nav-title>
<form style="width:100%;height:44px;">
<div class="item-input-inset" style="border:0;height:100%;width:100%;">
<div class="item-input-wrapper" style="background-color:#fff;height:32px;border:solid 1px #E1E1E1;width:100%;">
<i class="icon ion-android-search placeholder-icon" style="color: #CCCCCC;font-size:20px;cursor:pointer;"></i>
<input type="search" placeholder="请输入城市名称" style="font-size:14px;color:#262626;height:22px;width:100%;" ng-change="startDot()" ng-model="$parent.cityName">
<i class="ion-close-circled" ng-click="searchEmpty()" style="color: #CCCCCC;display:{{searchEmptyShow ? 'block' : 'none'}};"></i>
</div>
</div>
</form>
</ion-nav-title>
<ion-content scroll="true">
<div style="padding-bottom:120px;">
<div id="city_{{d.iniData}}" style="margin-right:30px;" ng-repeat="d in cityDatas | filter:cityName">
<div class="choose_city_abc" style="font-size: 18px;background:#F5F5F5;padding:8px 10px;">{{d.iniData}}</div>
<div class="choose_city_data">
<div class="choose_city_border" style="padding:7px 0px" ng-repeat="city in d.datas | filter:cityName" ng-click="confirmCity('{{city.zoneCityId}}','{{city.zoneCity}}')">{{city.zoneCity}}</div>
<div class="choose_city_border" style="padding:7px 0px;border-bottom:0;" ng-show="{{d.datas.length==0}}">暂无城市</div>
</div>
</div>
</div>
</ion-content>
<div style="width:28px;text-align:center;position:absolute;right:0;top:{{44+dis_ios}}px;margin:2px 0;color:#458AFF;" >
<div ng-repeat="c in indexs" style="width:100%;height:{{hIndex}}px;" ng-touchmove="mTouch('{{c}}')" ng-touchend="mRelease()" ng-click="mTouch('{{c}}')">
{{c}}
</div>
</div>
<div style="position:fixed;left:47%;top:47%;width:40px;height:40px;background:#ddd;display:flex;justify-content:center;align-items:center;font-size:20px;color:#262626;" ng-show="showMiddle">
{{hint}}
</div>
</ion-view>
用到的css代码如下:
.choose_city_abc{
border-bottom:solid 1px #e1e1e1;
border-right:solid 1px #e1e1e1;
border-top:solid 1px #e1e1e1;
}
.choose_city_border{
border-bottom:solid 1px #e1e1e1;
border-right:solid 1px #e1e1e1;
}
.choose_city_data{
padding-left: 22px;
}
.choose_city_border:nth-last-child(2){
border-bottom:0;
border-right:solid 1px #e1e1e1;
}
controller里面的如下:
$scope.searchEmptyShow=false;//是否显示清除输入的图标
$scope.showMiddle=false; //是否在屏幕中央显示选中的字母索引
$scope.hIndex=($(window).height()-44-4)/26;//右边侧边栏每个字母的高度,是屏幕高度减去标题栏的44,减去页面样式中的margin-top:2px,margin-bottom:2px,再除以26,这样以保证在各个手机屏幕上的字母的距离的均等性
var chars="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$scope.indexs=[];
loadData();
for(var i=0;i<chars.length;i++){
$scope.indexs.push(chars.charAt(i));//获取字母数组
}
$scope.startDot=function(){//判断清除输入框的图标是否显示
if($scope.cityName.length=0 || $scope.cityName==""){
$scope.searchEmptyShow=false;
}else{
$scope.searchEmptyShow=true;
}
};
$scope.searchEmpty=function(){//点击清除输入框的图标的点击事件
$scope.searchEmptyShow=false;
$scope.cityName="";
};
$scope.mTouch=function(c){
$scope.showMiddle=true;
$scope.hint=c;
/*var scroll = document.getElementById("city_"+$scope.hint).offsetTop - $ionicScrollDelegate.getScrollPosition().top;
$ionicScrollDelegate.scrollBy(0,scroll,false); */ //方式一
$location.hash("city_"+$scope.hint);
$ionicScrollDelegate.anchorScroll(true); //方式2
//如果发现左侧不能滚动,把此处的true改成false
};
$scope.mRelease=function(){
$timeout(function(){
$scope.showMiddle=false;
},300);
};
function loadData(){//从本地的一个包含全国各城市的json文件中加载数据
$ionicLoading.show(); $http.get("json/city.json").success(function(data) {
$scope.cityDatas=data.dataList;
$ionicLoading.hide();
});
}
在计算右边滚动位置时候,可以用方式1,计算滚动条滚动位置后,再进行滚动,也可以用方式2,通过描点的方式滚动。
下载地址:http://download.youkuaiyun.com/detail/lishihong108/9718410
以上是之前的,有位很细心的撸友发现了几个bug,现在修改如下:
html代码:
<ion-view view-title="城市选择" style="background:#fff;">
<ion-nav-buttons side="left">
<div style="width:32px;padding-left:2px;" ng-click="$ionicGoBack()">
<i class="icon ion-ios-arrow-left" style="color:#828a99;font-size:32px;line-height:32px;"></i>
</div>
</ion-nav-buttons>
<ion-nav-title>
<form style="width:100%;height:44px;">
<div class="item-input-inset" style="border:0;height:100%;width:100%;">
<div class="item-input-wrapper" style="background-color:#fff;height:32px;border:solid 1px #E1E1E1;width:100%;">
<i class="icon ion-android-search placeholder-icon" style="color: #CCCCCC;font-size:20px;cursor:pointer;"></i>
<input type="search" placeholder="请输入城市名称" style="font-size:14px;color:#262626;height:22px;width:100%;" ng-change="startDot()" ng-model="$parent.cityName">
<i class="ion-close-circled" ng-click="searchEmpty()" style="color: #CCCCCC;display:{{searchEmptyShow ? 'block' : 'none'}};"></i>
</div>
</div>
</form>
</ion-nav-title>
<ion-content>
<div style="padding-bottom:120px;">
<div id="city_{{d.iniData}}" style="margin-right:30px;" ng-repeat="d in cityDatas | filter:cityName">
<div class="choose_city_abc" style="font-size: 18px;background:#F5F5F5;padding:8px 10px;">{{d.iniData}}</div>
<div class="choose_city_data">
<div class="choose_city_border" style="padding:7px 0px" ng-repeat="city in d.datas | filter:cityName" ng-click="confirmCity('{{city.zoneCityId}}','{{city.zoneCity}}')">{{city.zoneCity}}</div>
<div class="choose_city_border" style="padding:7px 0px;border-bottom:0;" ng-show="{{d.datas.length==0}}">暂无城市</div>
</div>
</div>
</div>
</ion-content>
<div ng-touchend="mRelease()" ng-touchmove="mTouch($event)" ng-click="mTouch($event)" style="width:28px;text-align:center;position:absolute;right:0;top:44px;margin:2px 0;color:#458AFF;">
<div ng-repeat="c in indexs" style="width:100%;height:{{hIndex}}px;">
{{c}}
</div>
</div>
<div style="position:fixed;left:47%;top:47%;width:40px;height:40px;background:#ddd;display:flex;justify-content:center;align-items:center;font-size:20px;color:#262626;" ng-show="showMiddle">
{{hint}}
</div>
</ion-view>
主要改变是把事件放在父层div,使边滑动边显示对应位置的字母,并且滚动到对应位置。
css代码未变
controller代码:
$scope.searchEmptyShow=false;//是否显示清除输入的图标
$scope.showMiddle=false; //是否在屏幕中央显示选中的字母索引
$scope.hIndex=(window.screen.height-44-4)/26;//右边侧边栏每个字母的高度,是屏幕高度减去标题栏的44,减去页面样式中的margin-top:2px,margin-bottom:2px,再除以26,这样以保证在各个手机屏幕上的字母的距离的均等性
var chars="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$scope.indexs=[];
loadData();
for(var i=0;i<chars.length;i++){
$scope.indexs.push(chars.charAt(i));//获取字母数组
}
$scope.startDot=function(){//判断清除输入框的图标是否显示
if($scope.cityName.length=0 || $scope.cityName==""){
$scope.searchEmptyShow=false;
}else{
$scope.searchEmptyShow=true;
}
};
$scope.searchEmpty=function(){//点击清除输入框的图标的点击事件
$scope.searchEmptyShow=false;
$scope.cityName="";
};
$scope.mTouch=function(event){
var positionX=event.pageX || event.touches[0].pageX;
var positioinY=event.pageY || event.touches[0].pageY;
var ele = document.elementFromPoint(positionX,positioinY);
if(!ele){
return;
}
var c=ele.innerText;
if(!c || c==" " || c.length!=1){
return;
}
$scope.hint=c;
$scope.showMiddle=true;
var scroll = document.getElementById("city_"+$scope.hint).offsetTop - $ionicScrollDelegate.getScrollPosition().top;
$ionicScrollDelegate.scrollBy(0,scroll,true);
var ele = document.getElementsByTagName("ion-content");
ele[0].style.overflow="auto"; //解决滑动右边的导航字母后,左边不能再滚动的bug,可以试着注释这两句来测试这个问题
};
$scope.mRelease=function(){
$timeout(function(){
$scope.showMiddle=false;
},300);
};
function loadData(){//从本地的一个包含全国各城市的json文件中加载数据
$ionicLoading.show();
$http.get("json/city.json").success(function(data) {
$scope.cityDatas=data.dataList;
$ionicLoading.hide();
});
}