Android5 Kotlin实现Loading
khwb3940
8年前
<p>之前文章是使用 <strong>Toast</strong> 来替代网络请求时加载的 <strong>Loading</strong> ,本文就自定义实现一个简单的 <strong>Loading</strong> ,当然了,第三方开源库里有很多漂亮的加载库,我这只能算是抛砖引玉:</p> <p>Loading的实现:</p> <h3><strong>Loading 1.0</strong></h3> <p>网上流传的 <strong>Loading</strong> ,大都使用的 <strong>Tween</strong> 的 <strong>RotateAnimation</strong> ,以前的项目中我也是参照网上Demo实现的,这里贴出 <strong>LoadingDialog</strong> 动画实现代码:</p> <p><strong>LoadingDialog:</strong></p> <pre> <code class="language-java">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(); }</code></pre> <p>当然了,这样做能够达到效果,但是,最近在看属性动画,于是在新的版本中,使用了 <strong>Property Animator</strong> 来实现,并使用 <strong>Kotlin</strong> 的特性,对 <strong>Activity</strong> 和 <strong>Fragment</strong> 进行了扩展,方便调用,下面我们来看 <strong>Loading2.0</strong></p> <h3><strong>Loading2.0</strong></h3> <p>首先让我们来看看布局文件 <strong>loading_dialog.xml</strong></p> <pre> <code class="language-java"><?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></code></pre> <p>Const定义了两个常量</p> <pre> <code class="language-java">package com.vslimit.kotlindemo.util /** * Created by vslimit on 16/12/24. */ class Const { companion object { val SHOW = 1 val HIDE = 0 } }</code></pre> <p>现在定义 <strong>LoadingDialog</strong> 的样式</p> <pre> <code class="language-java"><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></code></pre> <p>实现自定义 <strong>LoadingDialog</strong></p> <pre> <code class="language-java">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() } }</code></pre> <p>至此, <strong>LoadingDialog</strong> 已经实现,下面我们来看看在 <strong>Activity</strong> 和 <strong>Fragment</strong> 是如何调用的:</p> <p>在 <strong>BaseActivity</strong> 中定义 <strong>loadingDialog</strong> 并初始化:</p> <pre> <code class="language-java">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) }</code></pre> <p>在包 <strong>extensions</strong> 中实现 <strong>ActivityExtentions.kt</strong> 和 <strong>FragmentExtentions.kt</strong> ,代码如下:</p> <p><strong>ActivityExtentions.kt</strong></p> <pre> <code class="language-java">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)</code></pre> <p>FragmentExtentions.kt</p> <pre> <code class="language-java">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)</code></pre> <p>那么在 <strong>Activity</strong> 和 <strong>Fragment</strong> 中就可以直接使用 <strong>loading(Const.SHOW)</strong> 和 <strong>loading(Const.HIDE)</strong> 来加载和隐藏 <strong>loading</strong></p> <p>下面是在 <strong>VolleyFragment</strong> 中的应用:</p> <pre> <code class="language-java">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) } } }</code></pre> <p>基于Kotlin的 <strong>LoadingDialog</strong> 的已经实现,当然了,如果想美化,可以进一步完善,效果如图:</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/23fc4799e2ec1b38401e087625dc4550.jpg"></p> <p style="text-align:center">LoadingDialog.jpg</p> <p> </p> <p>来自:http://www.jianshu.com/p/ce1e5edc5915</p> <p> </p>