參考:《第一行代碼:Android》第2版——郭霖html
注1:本文爲原創,例子可參考郭前輩著做:《第一行代碼:Android》第2版java
注2:本文不贅述android開發的基本理論,不介紹入門知識,不介紹Android Studio基本安裝,開門見山,直接使用kotlin改寫郭前輩的《第一行代碼:Android》中的部分例子,有機會的話本身作一些新例子出來!android
注3:本文嘗試用Google新官推語言kotlin改寫《第一行代碼:Android》中的案例,偶爾涉及java做爲對比git
注4:開發基於Android Studio 3.0,而且新建項目時勾選「support kotlin」github
14.6 手動更新天氣和切換城市(原書p532)web
不知不覺已經接觸kotlin的第四天了,原書中的最後一個實踐項目「酷歐天氣」也改寫的差很少了,稍後會將源碼上傳至csdn!做爲代碼樣本吧!canvas
雖說如今咱們已經把天氣界面編寫的很是不錯了,不過和市場上的一些天氣軟件的界面比起來,仍然還有必定差距的。(原書p526)api
爲了加載bing.com的每日一圖到本地緩存,咱們須要添加一個外部類庫glide緩存
關於glide:http://blog.csdn.net/fancylovejava/article/details/44747759安全
build.gradle:
dependencies { ...... compile "com.github.bumptech.glide:glide:3.8.0" }
添加glide到gradle,sync一下
<?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="match_parent" android:background="@color/colorPrimary"> <ImageView android:id="@+id/bing_pic_img" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="centerCrop" /> <android.support.v4.widget.DrawerLayout android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v4.widget.SwipeRefreshLayout android:id="@+id/swipe_refresh" android:layout_width="match_parent" android:layout_height="match_parent"> <ScrollView android:id="@+id/weather_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:overScrollMode="never" android:scrollbars="none"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:fitsSystemWindows="true" android:orientation="vertical"> <include layout="@layout/title" /> <include layout="@layout/now" /> <include layout="@layout/forecast" /> <include layout="@layout/aqi" /> <include layout="@layout/suggestion" /> </LinearLayout> </ScrollView> </android.support.v4.widget.SwipeRefreshLayout> <fragment android:id="@+id/choose_area_fragment" android:name="cn.cslg.weatherkotlin.ChooseAreaFragment" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="start" /> </android.support.v4.widget.DrawerLayout> </FrameLayout>
注意:能夠看到新增了一個ImageView,他就是咱們用來放背景的容器,因爲他的外部是一個FrameLayout,因此他和他的兄弟節點的內容會靠左上角停放,那麼這個ImageView將和其餘的內容重疊,造出一種背景的效果
...... class WeatherActivity : AppCompatActivity() { ...... private var bingImg: ImageView? = null ...... override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) //狀態欄透明化 if (Build.VERSION.SDK_INT >= 21) { val v = window.decorView v.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE window.statusBarColor = Color.TRANSPARENT } bingImg = find<ImageView>(R.id.bing_pic_img) ...... } ...... //獲取每日一圖的API private fun loadBingImg() { val url = "http://guolin.tech/api/bing_pic" async { val s = URL(url).readText() uiThread { Glide.with(this@WeatherActivity).load(s).into(bingImg) } } } }
注意:咱們添加了loadBingImg方法,專門加載每日一圖,其中多線程結束後,使用了Glide將圖片在進入ImageView當中變成背景。
咱們還把狀態欄設置爲透明,而且將他變成應用的一部分(應用全屏了),此時狀態欄可能會和下面的內容捱得太近了,須要在xml中設置:fitsSystemWindows="true",空出一段空間來
實現下拉刷新當前選定城市的天氣信息
佈局文件activity_weather.xml上面已經給出最終版本
主要添加了一個SwipeRefreshLayout容器,這個容器可使用下拉刷新功能,將須要刷新的頁面所有包含進去
...... class WeatherActivity : AppCompatActivity() { ...... var swipeRefresh: SwipeRefreshLayout? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_weather) swipeRefresh = find<SwipeRefreshLayout>(R.id.swipe_refresh) swipeRefresh!!.setColorSchemeResources(R.color.colorPrimary) ...... val weatherId = defaultSharedPreferences.getString("weather_id","") weatherLayout!!.visibility = View.INVISIBLE requestWeather(weatherId) swipeRefresh!!.setOnRefreshListener { //刷新當前的城市weather_id requestWeather(defaultSharedPreferences.getString("weather_id","")) } } //從服務器加載天氣信息 fun requestWeather(wid: String) { val url = "http://guolin.tech/api/weather?cityid=" + wid + "&key=" + KEY async { val s = URL(url).readText() uiThread { val weather = Gson().fromJson(s, Weather::class.java) //關閉下拉刷新 swipeRefresh!!.isRefreshing = false Log.d("url",url) Log.d("url",weather.toString()) showWeatherInfo(weather.HeWeather[0]) } } } ...... }
注意:獲取到了SwipeRefreshLayout控件,使用setColorSchemeResources設置了顏色,setOnRefreshListener設置了下拉刷新事件的監聽。
將ChooseAreaFragment這個碎片放到了offcanvas(側滑)當中,實現側滑後選擇其餘城市
在title.xml添加一個顯示offcanvas的按鈕:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" > <Button android:id="@+id/nav_button" android:layout_width="30dp" android:layout_height="30dp" android:layout_alignParentLeft="true" android:layout_centerInParent="true" android:layout_marginLeft="10dp" android:background="@android:drawable/ic_menu_sort_by_size" /> ...... </RelativeLayout>
修改activity_weather.xml(詳見前面的最終佈局)
主要添加了一個DrawerLayout,用於存放兩個直子控件,第一個是主屏幕顯示內容,第二個是側滑內容
修改WeatherActivity.kt:
...... class WeatherActivity : AppCompatActivity() { ...... private var navButton:Button?=null var drawLayout:DrawerLayout?=null ...... override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) ..... drawLayout = find<DrawerLayout>(R.id.drawer_layout) navButton = find<Button>(R.id.nav_button) navButton!!.setOnClickListener{ drawLayout!!.openDrawer(GravityCompat.START) } } ...... }
注意:僅僅是添加了按鈕觸發事件和獲取DrawerLayout的控件
修改:ChooseAreaFragment.kt
...... class ChooseAreaFragment : Fragment() { ...... override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) //列表點擊監聽事件 listView!!.setOnItemClickListener { _, _, position, _ -> when (current_level) { ...... LEVEL_COUNTY -> { selectedCounty = countyList[position] defaultSharedPreferences.edit().putString("weather_id", selectedCounty!!.weather_id).apply() if (activity is MainActivity) { startActivity<WeatherActivity>() activity.finish() //將MainActivity銷燬掉 } else if (activity is WeatherActivity) { val act = activity as WeatherActivity act.drawLayout!!.closeDrawers() act.swipeRefresh!!.isRefreshing = true //顯示下拉刷新 act.requestWeather(selectedCounty!!.weather_id) } } } } ...... } ...... }
注意:在Fragment獲取activity中的控件,kotlin的anko庫能夠直接使用activity,而後調用其它activity裏的屬性,好比swipeRefresh和drawLayout屬性,固然前提是他們是public,不能夠像其餘僅僅在當前類下用的控件那樣設置爲private!
當用戶觸發選擇了城市的事件後,將會去請求服務器的天氣信息,在這以前應該將選擇的城市的weather_id保存到SharedPreferences中,這樣用戶沒必要每次打開app時都要選擇城市,app能夠本身根據上次的選擇請求天氣數據
kotlin中使用is來代替java中的instanceof,能夠用來判斷當前實例所屬類
若是是MainActivity,則進入WeatherActivity中(其實這表示app是用戶第一次打開,尚未選擇過城市)
anko庫提供了startActivity<>方法,直接啓動其餘的活動
anko庫的一些輔助方法:http://www.tuicool.com/articles/VrIjIjq
若是是WeatherActivity則關閉側滑和下拉刷新,當即請求數據去!
至此,就把原書中的「酷歐天氣」的例子使用kotlin語言重寫了
代碼下載:http://download.csdn.net/detail/u014466109/9851378
雖然我在這以前歷來沒有接觸過kotlin語言,甚至聞所未聞(但願不要說我孤陋寡聞,畢竟我在這以前連Android都沒寫過,個人專長算是web)
但此時我想我愛上了kotlin這門現代語言
總結一下相對java開發的一些優勢:
轉載請註明:http://www.cnblogs.com/devilyouwei/p/6901264.html