Android-5 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.jpgLoadingDialog的代码详见:https://github.com/vslimit/kotlindemo