Kotlin项目实战之手机影音---基类抽取、欢迎界面、抽取startactivityandfinish、主界面布局

基类抽取:

在上一次https://www.cnblogs.com/webor2006/p/12612286.html搭建了项目的基本框架,接下来则继续往上磊代码了,先来创建一个每个项目都必有的BaseActivity,这里跟Java的Android差不多的就不多解释了,重点是解释Kotlin相关的:

package com.kotlin.musicplayer.base

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity

/**
 * Activity抽象基类
 */
abstract class BaseActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(getLayoutId())
        initListeners()
        initData()
    }

    protected fun initData() {

    }

    protected fun initListeners() {

    }

    protected abstract fun getLayoutId(): Int
}

其本上写法跟传统的Java差不多,再加上IDE的智能提示,写起来貌似没感到跟Java有太大的区别,之后遇到区别时再解释,对于Toast和Log的输出可以将其也封装到这个Base里,此时anko库就派上用场了,先看一下Toast的用法:

直接调用不就好了,干嘛还要封装一下?因为没有处理线程的问题,所以下面先封装一下它:

这里有个Kotlin的语法来了:

具体原因可以参考:https://www.cnblogs.com/webor2006/p/11498842.html,Kotlin语法规则有一条是这样说的:

而回到咱们这个方法的定义来看:

所以就符合这条规则了,另外看一下这个toast的具体实现:

这里函数的定义又涉及到好几个Kotlin的语法了:它是Context类中的一个扩展方法:

另外这种直接将方法的使用用=号相连是个啥语法呢?

另外这里还用了一个关键字:

它叫内联函数,可以参考https://www.cnblogs.com/webor2006/p/11518592.html

也就是我们在调用内联函数时,并非单纯的函数调用,而是将被调用函数的代码直接嵌在了我们调用处。好接下来再来封装一下BaseFragment:

package com.kotlin.musicplayer.base

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import org.jetbrains.anko.runOnUiThread
import org.jetbrains.anko.toast

/**
 * Fragment基类
 */
abstract class BaseFragment : Fragment() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        initData();
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return initView()
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        initListeners()
        initData()
    }

    protected fun initData() {

    }

    protected fun initListeners() {

    }

    protected fun showToast(msg: String) {
        context?.runOnUiThread { toast(msg) }
    }

    protected abstract fun initView(): View?
}

欢迎界面:

有了基础Activity的封装之后,下面则来首先实现Splash页面,先来回顾一下效果:

其背景图如下:

package com.kotlin.musicplayer.ui.activity

import com.kotlin.musicplayer.R
import com.kotlin.musicplayer.base.BaseActivity

class SplashActivity : BaseActivity() {
    override fun getLayoutId(): Int {
        return R.layout.activity_splash
    }
}

<?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:orientation="vertical">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        android:src="@mipmap/default_splash_bg" />
</LinearLayout>

此时运行看一下:

此时含有状态栏,得将其隐藏掉,所以得定义个全屏的主题:

接下来需要处理动画效果,其实就是让图片先放大一下,然后之后将其缩小成正常大小就可以了,比较简单,默认先在定义图片时将其放大一下:

接下来则需要处理缩小动画,此时需要覆写一下父类的initData()方法:

发现在子类中覆写不了,这时Kotlin的语法就又出来了,在之前也提及过,可以参考https://www.cnblogs.com/webor2006/p/11203903.html,其实要想让子类覆写,必须加个open关键字:

接下来则需要跳到MainActivity了,这里跳转依然可以使用anko库,能大大简化调用代码,使用方式如:

所以咱们使用一下:

此时运行看一下效果:

抽取startactivityandfinish:

对于这句代码可能未来也有需要调用:

所以可以将其提到父类中进行封装一下:

很明显这个抽取是有问题的:

关于泛型这块可以参考:https://www.cnblogs.com/webor2006/p/11296775.html,这里来修改一下:

此时就需要看一下startActivity这个函数的泛型定义了:

这里先不管这么多,先来校仿着定义一下:

 

 

果真是可以了,下面咱们来调用一下:

那么对于reified关健字的作用,可以参考博主:https://www.jianshu.com/p/bbe694b2c0a8,其实也就是要想通过泛型来获取到对应的class就必须加这个关键字,下面咱们举个例子:

此时就需要使用reified修饰并变成内联函数才行:

主界面布局:

接下来则来编写主界面了,它的效果长这样:

 

这里先来搭建一下界面框架,具体逻辑之后再慢慢实现,首先准备布局文件:

<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:background="@color/colorPrimary"
    android:orientation="vertical"
    app:titleTextColor="#fff" />

activity_main.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:orientation="vertical">

    <include layout="@layout/toolbar" />

    <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />
</LinearLayout>

接下来则需要定义底部Tab了,这里使用一个三方的库:https://github.com/roughike/BottomBar

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen>
    <tab
        icon="@mipmap/ic_bottom_home_icon"
        id="@+id/tab_home"
        title="首页" />
    <tab
        icon="@mipmap/ic_bottom_mv_unselect"
        id="@+id/tab_mv"
        title="MV" />
    <tab
        icon="@mipmap/ic_bottom_vlist_unselect"
        id="@+id/tab_vbang"
        title="V榜" />
    <tab
        icon="@mipmap/ic_bottom_mvlist_unselect"
        id="@+id/tab_yuedan"
        title="悦单" />
</PreferenceScreen>

上面的文本直接写在xml中而木有提至strings.xml了,因为是一个练习项目,重点是操练kotlin,这些细节就暂且忽略上,其中涉及到四张小icon,按顺序今次为:

此时运行看一下整体效果:

呃,底部的图标也太大了点吧,跟预期效果相差很多,这里其实就是要针对不同分辨率文件夹弄几套对应的图就可以了,如下:

具体就不多说了,最后再运行:

好,今天Kotlin的项目实战先到这,水滴石穿~~

posted on 2020-04-04 16:43  cexo  阅读(1033)  评论(0编辑  收藏  举报

导航