ionic實現A-Z城市選擇
阿新 • • 發佈:2019-01-05
在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();
});
}
以上是之前的,有位很細心的擼友發現了幾個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();
});
}