一個(gè)簡單的基于Leaflet樣式的多圖層安卓地圖應(yīng)用

BULABULA

這是 Mobile Cartography 課程的 project,看DDL還有四天就不慌不慢的花了三個(gè)半天寫了個(gè)差不多屿储,但是因?yàn)樾膽B(tài)爆的太早了導(dǎo)致獲取用戶地理位置的功能一直出現(xiàn)fatal error雖然后來發(fā)現(xiàn)問題很明顯卻還是花了整整一天半才改掉昭灵。就很氣吠裆。就決定來寫這篇文章降降燥。
Map in Colour 的設(shè)計(jì)初衷是希望能給那些喜歡自由的探索一個(gè)城市的少年們一個(gè)較為直觀的烂完,城市內(nèi)功能性POI分布的類別地圖试疙。
無需太多復(fù)雜的功能,我就是想展示抠蚣,那條大街上密布餐館祝旷,而那條大街上全是博物館etc.....
Git地址.

Map in Colour
Map in Colour

主界面UI部分結(jié)構(gòu)介紹

用DrawerLayout+Toolbar實(shí)現(xiàn)。
DrawerLayout 的第一部分子布局既是主視圖嘶窄,第二部分android.support.design.widget.NavigationView則是側(cè)邊欄怀跛。可參考簡書這篇文章柄冲,Android DrawerLayout.
主布局文件activity_maps.xml結(jié)構(gòu)如下:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout>
      <LinearLayout>
       |    <android.support.v7.widget.Toolbar>
       |    <RelativeLayout>
       |     |     <Button>
       |     |     <WebView>
       |     </RelativeLayout>
     </LinearLayout>
     <android.support.design.widget*NavigationView... >
</android.support.v4.widget.DrawerLayout>

在LinerLayout主視圖內(nèi)吻谋,布局從上到下為一個(gè)Toolbar,一個(gè)RelativeLayout /(Button+WebView).
這個(gè)Button是因?yàn)閘eaflet地圖沒有提供好用的用戶位置location API现横,必須要自己寫一個(gè)按鈕來實(shí)現(xiàn)Location+SetMapView的功能. WebView 用來顯示HTML文件.

A WebView is a View that displays web pages. This class is the basis upon which you can roll your own web browser or simply display some online content within your Activity. It uses the WebKit rendering engine to display web pages and includes methods to navigate forward and backward through a history, zoom in and out, perform text searches and more.
Note that, in order for your Activity to access the Internet and load web pages in a WebView, you must add the INTERNET permission to your Android Manifest file as a child of the <manifest> element:
<uses-permission android:name="android.permission.INTERNET" />
By default, a WebView provides no browser-like widgets, does not enable JavaScript and web page errors are ignored. If your goal is only to display some HTML as a part of your UI, this is probably fine; the user won't need to interact with the web page beyond reading it, and the web page won't need to interact with the user. If you actually want a full-blown web browser, then you probably want to invoke the Browser application with a URL Intent rather than show it with a WebView.

所以漓拾,也就是說,用戶是和這個(gè)MapView沒有任何互動(dòng)的. 但是當(dāng)然這個(gè)工程也沒有考慮這個(gè)需求 XD

主界面里Toolbar, DrawerLayout, NavigationView,WebView的初始化

Toolbar

首先戒祠,在主Activity晦攒,MapsActivity.java里初始化Toolbar. 最后一行 myToolbar.inflateMenu 用來關(guān)聯(lián)一個(gè)menu文件夾下的menu布局文件,實(shí)現(xiàn) Toolbar 右側(cè)的下拉菜單.

Toolbar myToolbar = (Toolbar) findViewById(my_toolbar);
myToolbar.setTitle("Map in colour");
myToolbar.setTitleTextColor(Color.WHITE); 
myToolbar.inflateMenu(R.menu.button_clear);

Toolbar右側(cè)下拉菜單布局是放在res/menu文件夾下的button_clear.xml文件.
內(nèi)部有兩個(gè)item得哆,help和info.
點(diǎn)擊Help后啟動(dòng)第二個(gè)Activity來展示圖例說明.
點(diǎn)擊info后在主界面上顯示一段文字(開發(fā)者信息).

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/action_item"
        android:title="@string/menu_item_01"
        app:showAsAction="never" />
    <item
        android:id="@+id/action_item0"
        android:title="@string/menu_item_02"
        app:showAsAction="never" />
</menu>

設(shè)定點(diǎn)擊menu中item的響應(yīng):

myToolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
            public boolean onMenuItemClick(MenuItem item) {
                int menuItemId = item.getItemId();
                if (menuItemId == R.id.action_item) {
                    onClickStartNewActivity();
                } else if (menuItemId == R.id.action_item0) {
                    Toast.makeText(MapsActivity.this , "..........", Toast.LENGTH_LONG).show();
                }
                return true;
            }
        });

DrawerLayout

然后是繼續(xù)在Activity 初始化DrawerView以實(shí)現(xiàn)Toolbar左側(cè)的坍縮按鈕和側(cè)邊欄的關(guān)聯(lián).
參考Android開發(fā)指南 ActionBarDrawerToggle
參數(shù)如下:
ActionBarDrawerToggle(Activity activity, DrawerLayout drawerLayout, int drawerImageRes, int openDrawerContentDescRes, int closeDrawerContentDescRes)

初始化如下:

final DrawerLayout mDrawerlayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this,
                mDrawerlayout,
                myToolbar,
                R.string.app_name,
                R.string.app_name
        );
        mDrawerlayout.addDrawerListener(toggle);
        toggle.syncState();

NavigationView

然后是繼續(xù)初始化側(cè)邊欄布局NavigationView.

        final NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.setItemIconTintList(null);

側(cè)邊欄NavigationView由兩部分組成.
在主布局文件activity_maps.xml中可以看到:

<android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        app:headerLayout="@layout/nav_header"
        app:menu="@menu/activity_main_drawer"
        app:itemTextColor="@color/drawer_item"
        app:itemIconTint="@color/drawer_item_tint"
        />

這個(gè) app:headerLayoutapp:menu 分別指定了側(cè)邊欄的頭部分布局脯颜,和頭部分下面的菜單布局。
既贩据,上部圖片區(qū)栋操,和下部列表區(qū)闸餐。
頭部nav_header.xml:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="192dp"
    android:theme="@style/ThemeOverlay.AppCompat.Dark">
    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/colorAccent"
        android:src="@drawable/logopic"
        android:scaleType="centerCrop"/>
</FrameLayout>

菜單部:

<?xml version="1.0" encoding="utf-8"?>
<menu
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item android:title="@string/selectLayer">
        <menu>
            <item
                android:id="@+id/nav_eat"
                android:icon="@drawable/ic_1"
                android:title="@string/eat"/>
             ......         
            <item
                android:id="@+id/nav_wc"
                android:icon="@drawable/ic_8"
                android:title="@string/wc"/>
        </menu>
    </item>
</menu>

為什么結(jié)構(gòu)是item內(nèi)部menu內(nèi)部item呢?
因?yàn)槲蚁M@個(gè)菜單可以多個(gè)item選中矾芙,而不是點(diǎn)選一個(gè)后之前check掉的那個(gè)又被清除了.
而:

Checkable items appear only in submenus or context menus.

然后是設(shè)定點(diǎn)擊menu里面item的響應(yīng):

navigationView.setNavigationItemSelectedListener(newNavigationView.OnNavigationItemSelectedListener() {
       @Override
        public boolean onNavigationItemSelected(MenuItem item) {......}
}

WebView

初始化WebView用來顯示地圖.

 final WebView webView = (WebView) findViewById(webview);
        webView.getSettings().setJavaScriptEnabled(true);
        webView.addJavascriptInterface(this, "javatojs");
        webView.loadUrl("file:///android_asset/map.html");

這里需要在java文件夾下新建一個(gè)asset文件夾用來存放HTML文件.

<!DOCTYPE html>
<html>
<head>
    <title>Custom Map</title>
    <meta charset="utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"/>
    <link rel="stylesheet" />
    <script src="https://unpkg.com/leaflet@1.0.1/dist/leaflet.js"></script>
    <style>......</style>
</head>
<body>
<div id='map'></div>
<script>......</script>
</body>
</html>

script里面為關(guān)鍵內(nèi)容.
先設(shè)定地圖的初始顯示中心和縮放等級(jí):
var map = L.map('map', {center: [51.051877, 13.741517],zoom: 15});

再加入你先設(shè)計(jì)好樣式的底圖圖層鏈接:

var basemap = L.tileLayer('HERE YOUR BASE MAP URL',{
           id: 'mapbox.streets'
       });
    basemap.addTo(map);

接下來是一個(gè)用來傳入獲取到的用戶坐標(biāo)重設(shè)map中心點(diǎn)的功能:

 function relocation(i,j){
     var london = new L.LatLng(i,j);
     map.setView(london, 17);
    }

在這里舍沙,我們需要Mapbox來發(fā)布自定義地圖樣式.

For customizing the style of our Mapbox map, please login in to Mapbox Studio or create an account if you don’t have one yet. After logging in, select the option New style. You can give your style a name and choose if you want to modify an existing Mapbox style or create a completely new one whereas the last option is less comfortable since the new style needs to be build up from the bottom. After clicking Create you can modify the look of all objects in the map up to your needs. Therefore select an object for opening an additional window. The tab Style contains control elements for editing the appearance of the respective object, the tab Select data offers further options, for instance defining a scale range in which the selected object is visible in the map. Furthermore more you can add, hide, duplicate and delete layers.
After creating your own map style, click on the Publish-button in the upper left corner. A pop up window will inform you whether the publishing process was successful. If so, click Preview, develop & use. On the new page scroll down to the section Develop with this style and switch from the Mapbox to the Leaflet option. A Leaflet URL is displayed to you which needs to be copied and used for replacing the URL in the tileLayer-definition in map.html. Now a map with the style you have just created will be displayed in the Android app after re-running it.

Leaflet URL
Leaflet URL

在這個(gè)工程里,我們一共發(fā)布了九個(gè)圖層剔宪,分別是一個(gè)黑底白色label的底圖拂铡,和剩下八個(gè)單獨(dú)色點(diǎn)背景透明的,選擇好了POI類別的圖層.
在script里面接著聲明他們葱绒,并寫8個(gè)添加他們的function感帅,和8個(gè)刪除他們的function :
(好吧小白表示這里代碼冗余也不曉得怎么管了,以后再學(xué)習(xí)處理吧.....)

var layer1 = L.tileLayer('https://api.mapbox.com......',
        {
            id: 'mapbox.streets'
        });
function addlayer1(){
        layer1.addTo(map);
    }
function removelayer1(){
         map.removeLayer(layer1);
    }

到這里地淀,HTML就全部寫完了失球,這八個(gè)add layer的方法和上面提到的側(cè)邊欄NavigationView里面menu的每個(gè)item相對(duì)應(yīng),當(dāng)public boolean onNavigationItemSelected(MenuItem item) {......}觸發(fā)帮毁,在此方法內(nèi)部實(shí)現(xiàn)分別調(diào)用JS里面的function來把圖層添加或移除.

獲得用戶地理位置的方法

首先在Mainifest里添加許可:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

初始化LocationListener实苞,用于捕獲用戶地理位置變更和相應(yīng)的響應(yīng)事件 .

locationListener = new LocationListener() {
            public void onLocationChanged(Location location) {
            }
            public void onProviderDisabled(String provider) {
            }
            public void onProviderEnabled(String provider) {
            }
            public void onStatusChanged(String provider, int status, Bundle extras) {
            }
};

LocationManager獲取系統(tǒng)(定位LOCATION_SERVICE)服務(wù) .
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

然而,在調(diào)用任何LocationManager方法之前烈疚,我們被要求必須先檢查用戶許可.
這里的if就是黔牵,如果檢測(cè)到我們還沒有問用戶申請(qǐng)過許可,就必須在這里先申請(qǐng).

 if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            ActivityCompat.requestPermissions(this, LOCATION_PERMS , 1340);
            return;
        }

一旦當(dāng)我們獲得過了用戶許可爷肝,檢查許可就可以通過猾浦,則跳過if語句,調(diào)用LocationManager方法被允許.

location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
final double latitude = location.getLatitude();
final double longitude = location.getLongitude();

上面提到阶剑,如果許可檢查失敗跃巡,在if里面我們需要向用戶提出許可申請(qǐng).
這里要使用 ActivityCompat.requestPermissions(this, LOCATION_PERMS , 1340) 方法.
根據(jù)安卓開放說明,三個(gè)變量如下:

requestPermissions(Activity activity, String[] permissions, int requestCode)

第二個(gè)變量 String[] permissions 在公共類開頭以被聲明.
final String[] LOCATION_PERMS = {android.Manifest.permission.ACCESS_FINE_LOCATION};
第三個(gè)變量也一樣:
final int LOCATION_REQUEST = 1340;
根據(jù) Android help

一旦 requestPermissions 被調(diào)用牧愁,會(huì)有一個(gè)pop up窗口彈出問用戶申請(qǐng)?jiān)S可.

If your app does not have the requested permissions the user will be presented with UI for accepting them. After the user has accepted or rejected the requested permissions you will receive a callback reporting whether the permissions were granted or not. Your activity has to implement ActivityCompat.OnRequestPermissionsResultCallback and the results of permission requests will be delivered to its onRequestPermissionsResult(int, String[], int[]) method.

當(dāng)我們調(diào)用 requestPermissions 之后素邪, 我們需要重寫 onRequestPermissionsResult 方法,在
OnCreate() 外面. 如果用戶返回結(jié)果是 "accept"猪半,接著即可調(diào)用 LocationManager的 Location updates方法了.

@Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        switch (requestCode){
            case LOCATION_REQUEST:
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
                    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,1000, 0, locationListener);
                    onClickStartNewActivity();//First time start : show second view
                } else {
                    Toast.makeText(this, "Location cannot be obtained due to " + "missing permission.", Toast.LENGTH_LONG).show();
                }
                break;
        }
    }

我在這里多寫了一句調(diào)用onClickStartNewActivity()方法來打開第二個(gè)Activity用以刷新主Activity (用戶許可會(huì)被系統(tǒng)記住兔朦,再打開主Activity時(shí) if 檢查就會(huì)通過,if后面的代碼就可以生效了 )

       final String position= "javascript:relocation("+latitude+","+longitude+")";
       final Button button = (Button) findViewById(R.id.locationbutton);
       button.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                webView.loadUrl(position);
                //Toast.makeText(MapsActivity.this , position, Toast.LENGTH_LONG).show();
                // Perform action on click
            }

onClickStartNewActivity()方法如下:

public void onClickStartNewActivity() {
        Intent intent = new Intent(this, LegendActivity.class);
        startActivity(intent);
 }

第二個(gè)Activity就是說明界面. 較為簡單在這里就不細(xì)說了.

應(yīng)用語言自適應(yīng)

所有的系統(tǒng)String都放入資源文件夾內(nèi)的strings.xml內(nèi).

<resources>
    <string name="app_name">Map in colour</string>
    <string name="title_activity_maps">Map in colour</string>
    <string name="title_help">How does it work</string>
    <string name="menu_item_01">Help</string>
    <string name="menu_item_02">Info</string>
    <string name="selectLayer">Select layers</string>
    <string name="eat">Eat&Drink</string>
    <string name="buy">Buy&Buy</string>
    <string name="culture">Art&Culture</string>
    <string name="club">Entertain&Nightlife</string>
    <string name="transport">Come&Go</string>
    <string name="hospital">Hospital&Pharmacy</string>
    <string name="bank">Bank&Exchange</string>
    <string name="wc">Pee&Poo</string>
</resources>

再在res文件夾內(nèi)新建一個(gè)名為values-zh的文件夾. 也放入一個(gè)strings.xml.
但這個(gè)文件設(shè)定為中文.

<resources>
    <string name="app_name">彩色地圖</string>
    <string name="title_activity_maps">彩色地圖</string>
    <string name="title_help">圖層說明</string>
    <string name="menu_item_01">幫助</string>
    <string name="menu_item_02">信息</string>
    <string name="selectLayer">選擇圖層</string>
   <string name="eat">吃吃喝喝</string>
    <string name="buy">買買買</string>
    <string name="culture">藝術(shù)與文化</string>
    <string name="club">酒吧與夜生活</string>
    <string name="transport">交通樞紐</string>
    <string name="hospital">醫(yī)院</string>
    <string name="bank">銀行與貨幣兌換</string>
    <string name="wc">廁所</string>
</resources>

這樣磨确,應(yīng)用就會(huì)根據(jù)系統(tǒng)設(shè)定的語言來自主選擇從哪一個(gè)資源文件內(nèi)選擇string了.

結(jié)尾處的BULABULA

現(xiàn)在的問題是沽甥,POI在小比例尺的視圖中都會(huì)消失不見,這個(gè)scale level能否改變一下乏奥,使得在小比例尺視圖中可以看到全城的概覽就是下一個(gè)需要考慮的問題啦~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末摆舟,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌恨诱,老刑警劉巖媳瞪,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異照宝,居然都是意外死亡蛇受,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門厕鹃,熙熙樓的掌柜王于貴愁眉苦臉地迎上來兢仰,“玉大人,你說我怎么就攤上這事剂碴“呀” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵汗茄,是天一觀的道長秸弛。 經(jīng)常有香客問我铭若,道長洪碳,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任叼屠,我火速辦了婚禮瞳腌,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘镜雨。我一直安慰自己嫂侍,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布荚坞。 她就那樣靜靜地躺著挑宠,像睡著了一般。 火紅的嫁衣襯著肌膚如雪颓影。 梳的紋絲不亂的頭發(fā)上各淀,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音诡挂,去河邊找鬼碎浇。 笑死,一個(gè)胖子當(dāng)著我的面吹牛璃俗,可吹牛的內(nèi)容都是我干的奴璃。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼城豁,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼苟穆!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤雳旅,失蹤者是張志新(化名)和其女友劉穎剖膳,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體岭辣,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡吱晒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了沦童。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片仑濒。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖偷遗,靈堂內(nèi)的尸體忽然破棺而出墩瞳,到底是詐尸還是另有隱情,我是刑警寧澤氏豌,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布喉酌,位于F島的核電站,受9級(jí)特大地震影響泵喘,放射性物質(zhì)發(fā)生泄漏泪电。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一纪铺、第九天 我趴在偏房一處隱蔽的房頂上張望相速。 院中可真熱鬧,春花似錦鲜锚、人聲如沸突诬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽旺隙。三九已至,卻和暖如春骏令,著一層夾襖步出監(jiān)牢的瞬間蔬捷,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來泰國打工伏社, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留抠刺,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓摘昌,卻偏偏與公主長得像速妖,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子聪黎,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容