Kotlin项目实战之手机影音---toolbar处理、设置菜单点击事件处理、设置界面处理
在上一次https://www.cnblogs.com/webor2006/p/12622874.html已经初步对主界面进行了一个框架布局,目前的样子如下:
其主界面的布局文件为:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" 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" /> <com.roughike.bottombar.BottomBar android:id="@+id/bottomBar" android:layout_width="match_parent" android:layout_height="60dp" android:layout_alignParentBottom="true" app:bb_tabXmlResource="@xml/bottombar_tabs" /> </LinearLayout>
下面继续进行功能的实现。
toolbar处理:
修改背景色:
这里先来处理一下toolbar,先回忆一下最终的效果:
首先背景色不对,目前toolbar的背景用的是主题色:
所有这里将修改一下标题栏的主题色既可:
运行:
标题封装:
对于标题是每个界面都会要进行处理的,所以这里有必要对它进行一个封装处理了,这里就学一下在Kotlin中是如何来达到封装的目的的,跟Java的写法还是不太一样的。
这里新建一个封装管理类:
package com.kotlin.musicplayer.utils /** * 标题栏管理类 */ class ToolBarManager { /** * 初始化主界面的toolbar */ fun initMainToolBar() { //TODO } }
然后这里就跟Java不同的地方出来了,看好了,这里面可以定义一个Toolbar的引用:
但是,很明显这个Toolbar的初始化应该交由子类来提供,只有具体的界面才知道是什么样的Toolbar,所以为了不让它报错,可以将它声明成一个接口,此时val的变量就不需要强制初始化而转由子类来进行:
有了Toolbar的引用,接下来咱们就可以在初始化方法中设置一下主界面的标题:
设置标题:
接下来则可以在MainActivity来实现这个接口并对Toolbar进行初始化,具体如下:
此时就需要来初始化val的变量了:
属性重写可以参考:https://www.cnblogs.com/webor2006/p/11203903.html,这里打算用延迟初始化来提高程序的性能,怎么做?
此时看一下lazy函数:
所以为啥咱们调用是这样的:
另外,貌似之前咱们在学习Kotlin语言时还有一个延迟初始化的方式:
那这俩延迟初始化有啥区别呢?可以参考博主:https://www.jianshu.com/p/e2cb4c65d4ff,简单来说是lazyinit只能用到var的变量,而by lazy只能用于val的变量,而关于var和val有啥区别这里就不多说了,最最基础的了,接下来咱们则可以调用初始化方法了,如下:
运行:
另外咱们来打印一下日志,看一下lazy()函数的调用确实是在我们使用了Toolbar之后才执行的么?
运行看一下日志输出:
嗯,确实是!!
增加设置菜单:
接下来还需要给右侧增加一个设置菜单,如下:
其中用到一个图片:
它其实长这样:
此时可以在IDE上预览一下效果:
那此时需要再设置一个属性才行:
此时咱们再运行看一下:
设置菜单点击事件处理:
接下来给菜单增加一个点击事件:
其中这里又得复习一下相关语法了-----对象表达式(Object expression),关于这块可以参考:https://www.cnblogs.com/webor2006/p/11352421.html,关于它的作用可以大致回顾一下:
也就是在Koltin对于匿名内部类是采用对象表达式的形式来代替的,接下来咱们先来处理点击逻辑,这里先打个toast看一下:
在Kotlin中木有switch关键字,这里是用的when关键字,而关于它的用法可以参考:https://www.cnblogs.com/webor2006/p/11186089.html,其中它还简化的写法:
运行看一下:
另外对于这个事件监听代码在IDE上已经有一个标黄的提示了,很明显是有更加优化的写法:
用IDE的向导提示来修改一下,此时代码就精简为:
看一下这个回调接口的定义:
其实还可以进一步精简,这里就涉及到Kotlin调用Java的小细节了,“如果Java接口中只有一个未实现的方法,可以省略接口对象,直接用{}表示未实现的方法”,也就是:
其实这个规则就是Kotlin关于参数是Lambda表达式时直接可以用花括号来进行调用的差不多,回忆一下:
好,逻辑了这么多关于语法的知识,目的就是为了巩固Kotlin的语法,只有这样才会对Kotlin掌握得更加得熟练,接下来则需要点击跳转到一个设置界面,所以下面来准备一下:
package com.kotlin.musicplayer.ui.activity import com.kotlin.musicplayer.R import com.kotlin.musicplayer.base.BaseActivity /** * 设置界面 */ class SettingsActivity : BaseActivity() { override fun getLayoutId(): Int { return R.layout.activity_settings } }
<?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:gravity="center" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="settings" /> </LinearLayout>
然后点击时跳转一下,这里又有一个Koltin的语法出来了:
其中这里获取Class时后面跟了一个.java,原因是我们的每个Activity继承的是一个Java的Activity,而非Kotlin的,如下:
而要获取对应Java的class类就需要用这种语法,关于这块可以参考:https://www.cnblogs.com/webor2006/p/11571472.html,
好,接下来运行看一下设置界面:
设置界面处理:
接下来则来对设置界面进行调整,先展示一下预期的效果图:
标题处理:
先来修改toolbar,照之前主界面的toolbar的写法来:
<?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" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="settings" /> </LinearLayout>
package com.kotlin.musicplayer.ui.activity import androidx.appcompat.widget.Toolbar import com.kotlin.musicplayer.R import com.kotlin.musicplayer.base.BaseActivity import com.kotlin.musicplayer.utils.ToolBarManager import org.jetbrains.anko.find /** * 设置界面 */ class SettingsActivity : BaseActivity(), ToolBarManager { override fun getLayoutId(): Int { return R.layout.activity_settings } override val toolbar by lazy { find<Toolbar>(R.id.toolbar) } override fun initData() { super.initData() initSettingsToolBar() } }
运行看下效果:
设置项处理:
这里采用PreferenceFragment来构造咱们的设置项,所以新建一个Fragment:
package com.kotlin.musicplayer.ui.fragment import android.os.Bundle import android.preference.PreferenceFragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import com.kotlin.musicplayer.R /** * 设置项 */ class SettingsFragment: PreferenceFragment() { override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? { addPreferencesFromResource(R.xml.setting) return super.onCreateView(inflater, container, savedInstanceState) } }
其中配置项是在xml中:
<?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <Preference android:key="clear_cache" android:title="清除缓存" /> <SwitchPreference android:key="push" android:title="推送通知" /> <SwitchPreference android:key="no_wifi" android:title="非wifi下加载图片" /> <Preference android:key="about" android:title="关于" /> </PreferenceScreen>
然后将其声明到Activity布局当中:
运行看一下效果:
使用PreferenceFragment的好处就是对于配置的开关就不需要咱们自己来写了,它里面已经为我们处理好了,下面咱们来读取一下开关状态,看是否能正常的读取出来:
package com.kotlin.musicplayer.ui.activity import android.preference.PreferenceManager import androidx.appcompat.widget.Toolbar import com.kotlin.musicplayer.R import com.kotlin.musicplayer.base.BaseActivity import com.kotlin.musicplayer.utils.ToolBarManager import org.jetbrains.anko.find /** * 设置界面 */ class SettingsActivity : BaseActivity(), ToolBarManager { override fun getLayoutId(): Int { return R.layout.activity_settings } override val toolbar by lazy { find<Toolbar>(R.id.toolbar) } override fun initData() { super.initData() initSettingsToolBar() println("push checked:" + PreferenceManager.getDefaultSharedPreferences(this).getBoolean("push", false)) } }
其中SP的key则是在xml中配置的:
运行一下:
接下来需要处理“关于”的点击事件,简单处理下:
/** * 设置项 */ class SettingsFragment : PreferenceFragment() { override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? { addPreferencesFromResource(R.xml.setting) return super.onCreateView(inflater, container, savedInstanceState) } override fun onPreferenceTreeClick(preferenceScreen: PreferenceScreen?, preference: Preference?): Boolean { val key = preference?.key if ("about".equals(key)) { //点击了关于 activity.startActivity(Intent(activity, AboutActivity::class.java)) } return super.onPreferenceTreeClick(preferenceScreen, preference) } }
package com.kotlin.musicplayer.ui.activity import com.kotlin.musicplayer.R import com.kotlin.musicplayer.base.BaseActivity /** * 关于页面 */ class AboutActivity : BaseActivity() { override fun getLayoutId(): Int { return R.layout.activity_about } }
<?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"> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:text="这是一款免费的Kotlin视频播放器" /> </LinearLayout>
运行: