Android5 Kotlin實現Loading
之前文章是使用 Toast 來替代網絡請求時加載的 Loading ,本文就自定義實現一個簡單的 Loading ,當然了,第三方開源庫里有很多漂亮的加載庫,我這只能算是拋磚引玉:
Loading的實現:
Loading 1.0
網上流傳的 Loading ,大都使用的 Tween 的 RotateAnimation ,以前的項目中我也是參照網上Demo實現的,這里貼出 LoadingDialog 動畫實現代碼:
LoadingDialog:
private void initAnim() {
mAnim = new RotateAnimation(0, 360, Animation.RESTART, 0.5f, Animation.RESTART, 0.5f);
mAnim.setDuration(2000);
mAnim.setRepeatCount(Animation.INFINITE);
mAnim.setRepeatMode(Animation.RESTART);
mAnim.setStartTime(Animation.START_ON_FIRST_FRAME);
}
@Override
public void show() {//在要用到的地方調用這個方法
iv_route.startAnimation(mAnim);
// handler.sendEmptyMessage(CHANGE_TITLE_WHAT);
super.show();
}
@Override
public void dismiss() {
mAnim.cancel();
super.dismiss();
}
當然了,這樣做能夠達到效果,但是,最近在看屬性動畫,于是在新的版本中,使用了 Property Animator 來實現,并使用 Kotlin 的特性,對 Activity 和 Fragment 進行了擴展,方便調用,下面我們來看 Loading2.0
Loading2.0
首先讓我們來看看布局文件 loading_dialog.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/transparent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@mipmap/bd"
android:gravity="center">
<ImageView
android:id="@+id/imgIv"
android:layout_gravity="center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:src="@mipmap/progress_round"/>
</RelativeLayout>
</LinearLayout>
Const定義了兩個常量
package com.vslimit.kotlindemo.util
/**
* Created by vslimit on 16/12/24.
*/
class Const {
companion object {
val SHOW = 1
val HIDE = 0
}
}
現在定義 LoadingDialog 的樣式
<style name="CustomDialog" parent="@android:style/Theme.Dialog">
<item name="android:windowFrame">@null</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
<item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item>
</style>
<style name="CustomProgressDialog" parent="@style/CustomDialog">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowNoTitle">true</item>
</style>
實現自定義 LoadingDialog
package com.vslimit.kotlindemo.ui
import android.animation.ObjectAnimator
import android.animation.ValueAnimator
import android.app.Dialog
import android.content.Context
import android.widget.ImageView
import com.vslimit.kotlindemo.R
/**
* Created by vslimit on 16/12/24.
*/
class LoadingDialog(context: Context) : Dialog(context, R.style.CustomProgressDialog) {
private var imgIv: ImageView? = null
init {
setContentView(R.layout.loading_dialog)
imgIv = findViewById(R.id.imgIv) as ImageView
}
private fun initAnim() {
val animator = ObjectAnimator.ofFloat(imgIv, "rotation", 0f, 359f)
animator.repeatCount = ValueAnimator.INFINITE
animator.repeatMode = ValueAnimator.REVERSE
animator.duration = 2000
animator.start()
}
override fun show() {//在要用到的地方調用這個方法
super.show()
initAnim()
}
override fun dismiss() {
super.dismiss()
}
}
至此, LoadingDialog 已經實現,下面我們來看看在 Activity 和 Fragment 是如何調用的:
在 BaseActivity 中定義 loadingDialog 并初始化:
var loadingDialog: LoadingDialog? = null
open var handler: Handler = object : Handler() {
override fun handleMessage(msg: Message) {
//定義一個Handler,用于處理下載線程與UI間通訊
if (!Thread.currentThread().isInterrupted) {
when (msg.what) {
Const.SHOW -> loadingDialog!!.show()//顯示進度對話框
Const.HIDE -> loadingDialog!!.hide()//隱藏進度對話框,不可使用dismiss()、cancel(),否則再次調用show()時,顯示的對話框小圓圈不會動。
}
}
super.handleMessage(msg)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(layoutResourceId)
loadingDialog = LoadingDialog(this)
}
在包 extensions 中實現 ActivityExtentions.kt 和 FragmentExtentions.kt ,代碼如下:
ActivityExtentions.kt
package com.vslimit.kotlindemo.extensions
import com.vslimit.kotlindemo.activity.BaseActivity
/**
* Created by vslimit on 16/12/24.
*/
fun BaseActivity.loading(msg: Int) = handler.sendEmptyMessage(msg)
FragmentExtentions.kt
package com.vslimit.kotlindemo.extensions
import com.vslimit.kotlindemo.activity.BaseActivity
import com.vslimit.kotlindemo.fragment.BaseFragment
import org.jetbrains.anko.support.v4.act
/**
* Created by vslimit on 16/12/24.
*/
fun BaseFragment.loading(msg: Int) = (act as BaseActivity).loading(msg)
那么在 Activity 和 Fragment 中就可以直接使用 loading(Const.SHOW) 和 loading(Const.HIDE) 來加載和隱藏 loading
下面是在 VolleyFragment 中的應用:
fun init() {
if (NetworkUtil.isNetwork(act)) {
val listener = Listener<IPResult> { e, r ->
e?.let { Bus.post(BaseEvent<IPResult>(error = e)) }
r?.let { Bus.post(BaseEvent(response = r)) }
}
val url = "http://ip.taobao.com/service/getIpInfo.php?ip=63.223.108.42"
Log.d("Url:::", "")
App.queue!!.add(listener, url)
//post 調用
//App.queue!!.post(listener, url, hashMapOf("aaa" to "aaa", "bbb" to "bbb"))
loading(Const.SHOW)
} else {
alert("網絡錯誤", "網絡未連接,請檢查網絡")
}
}
fun onEventMainThread(event: BaseEvent<IPResult>) {
val error = event.error
result = event.response
loading(Const.HIDE)
if (error != null) {
toast(error.toString(resources))
} else {
if (result!!.code == Result.SUCCESS) {
async() {
uiThread {
resultTv.text = result!!.data!!.country
}
}
} else {
toast(result!!.code)
}
}
}
基于Kotlin的 LoadingDialog 的已經實現,當然了,如果想美化,可以進一步完善,效果如圖:

LoadingDialog.jpg
來自:http://www.jianshu.com/p/ce1e5edc5915