参考:《第一行代码: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