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>