1. 程式人生 > >ionic實現A-Z城市選擇

ionic實現A-Z城市選擇

  在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();
 });
}