细碎的玩意·其一

 

有关语法

有关循环

在Kotlin中有十分熟悉的for-in循环,终于不和while功能重复了

可是Kotlin不像py那样直接用range生成range

比如下边这样能得到一个$0≤x≤10$的范围

val range = 0..10 

还有这样能得到$0≤x<10$的范围

val range = 0 until 10 

后面加个step就可以一次想加几次就加几次

val range = 0 until 10 step 2

如果想倒过来就可以像下面这样得到一个$[10, 1]$的区间

val range = 10 downTo 1

怎么说呢,挺好的,就是要适应

有关let

let是个作用域函数……

一般用于给某个对象判空,如果为空就不做那些事了不然会崩,比如

obj?.let {
	println(it.toString())
}

和其它作用域函数一样,it在这个大括号里边表示对象本身

有关try

try是用来看看一段代码在运行时会不会崩掉的,如果真的崩了也不会把整个程序带走

它的完整结构包含trycatchfinally

GPT总结得很好

try {
    // 可能会引发异常的代码
} catch (e: ExceptionType) {
    // 处理异常的代码
} finally {
    // 可选的代码块,不管是否发生异常都会执行
}

一般的e: Exception基本代表所有类型的异常

可以有很多个catch来捕获各种各样的异常,然后做出各种各样的应对方案

有关列表

你可能需要:有关Lambda表达式

kt中初始化列表似乎和别的语言不太一样?

比如我要一个有20个元素的列表,其值均为5,可以这么写

val list = List(20) {5}

有点太神奇了说实话

对可变列表也是一样的

如果想要元素按一定规律变化,可以这么写

val mutableList = MutableList(20) { "Element $it" }

元素的值分别为"Element 0""Element 1"……

然后当然也可以

val mutableList = MutableList(20) { it * 3 }

这样它就是[0, 3, 6, ..., 57]

这就是21世纪的语言吗太强悍了

唯一的问题是,如果想像其他语言一样已知元素创建列表时不能像上面那样

list = [233, 555, 114] # 人家py多方便啊

kt要用listof来创建

val list = listof(233, 555, 114)

这大抵是因为kt里{}的作用太多了罢

说的就是你,Lambda 表达式!

字符串处理

replace接收两个参数,将字符串中的对应字符替换成你想要的,比如

val result = text.replace(Regex("[ /\\\\:*?\"<>|]+"), "_")

方括号中的所有字符都会被替换为下划线,+代表无论几个这些字符连在一起都通通变成一个下划线

如果变成这样,代表这些字符连在一起大于等于两个才会被替换

val result = text.replace(Regex("[ /\\\\:*?\"<>|]{2,}"), "_")

既然能调下限,那也一定能改上限

这种比较新的语言都是这样轮子特别多的吗

有关时间

可以用Java的TimeUnit对时间进行方便的转换

获取现在时间只需要System.currentTimeMillis()获取现在的毫秒时间

通过TimeUnit.原单位.to新单位(数值)就可以方便地得到一个新的单位的时间辣

如果要处理日程之类的东西……说实话用Java的Calendar会比较方便

其它语言特性

kt:孩子们,我也有三引号

有关控件

超多控件,芝士雪豹,并不深但是广

其实就是属性超多啦

如果某个属性拥有多个值,可以在不同的值之间加上|,比如android:layout_gravity="end|bottom"

如果没有特别指定,那在xml中下面的控件会把上面的盖住

还有个东西大大简化了控件的使用,详见有关Binding

有关TextView

textStyle可以决定文字是否加粗或者斜体

typeface可以决定文字的类型(只有一些简单的属性

fontFamily可以决定文字的字体——和上一个属性有些相似呢,不过基本什么字体都能支持

paintFlags可以给文字设置下划线删除线,但只能在代码里边赋值,为什么?

像这样就是给它加一条下划线

tipTextView.paintFlags = android.graphics.Paint.UNDERLINE_TEXT_FLAG

STRIKE_THRU_TEXT_FLAG则是添加删除线可是似乎只能同时应用一个属性

我有预感这些属性在别的有文字的控件里边也可以用

类似语言,在不同的values文件夹里能设置它的字体颜色之类的属性,这样就能支持深色模式了

有关EditText

hint是设置提示文本

android:background="@android:color/transparent"

可以让下划线滚蛋

有关Button

使用MaterialButton,更现代化且更易配置!

可以轻松设置边框

有关ImageView

可以用scaleType这个属性来控制图片的缩放方式

比如fitXY是拉伸,centerCrop是保持比例使图片越界填充整个ImageView,centerInside则不会让图片越界,只会尽可能填满

有关SearchView

iconifiedByDefault="false"表示默认情况下展开搜索框

如果想在菜单里面加上搜索,可以添加一个这样的item

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/action_search"
        android:icon="@drawable/ic_search"
        android:title="Search"
        android:showAsAction="ifRoom|collapseActionView"
        android:actionViewClass="androidx.appcompat.widget.SearchView" />
</menu>

在代码中可以用setOnQueryTextListener来监听搜索输入,像下面一样

searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
    override fun onQueryTextSubmit(query: String?): Boolean {
        // 用户提交搜索时触发
        if (query != null) {
            performSearch(query) // 执行搜索逻辑
        }
        return true
    }

    override fun onQueryTextChange(newText: String?): Boolean {
        // 用户每次输入变化时触发
        if (newText != null) {
            updateSearchResults(newText) // 实时更新搜索结果
        }
        return true
    }
})

GPT总结得真好是吧

如果是在菜单里面,就要在 onCreateOptionsMenu 里边初始化了

这玩意还能和 RecyclerView 一起用,实现有趣的效果

有关RecyclerView

需要写适配器的神奇东西

有关Adapter
有关notifyItemChanged

它是Adapter里面的一个方法,可以更新某个项的数据

notifyItemChanged(adapterPosition)

这行代码的意思是更新当前位置的项

执行了这行代码就会让这一项重新绑定一次ViewHolder,从而防止一些奇奇怪怪的bug(比如很多个项共用一个变量)

这样做还能获赠动画效果

有关ViewPager

同样要写适配器的神奇东西,可以实现不同页面之间的滑动切换

现已全面升级为ViewPager2

有关Adapter

下面就是一个GPT写的有关Adapter的示例

class ViewPagerAdapter(activity: FragmentActivity) : FragmentStateAdapter(activity) {

    private val fragments = listOf(
        HomepageFragment(),
        StatsFragment(),
        SettingsFragment()
    )

    override fun getItemCount() = fragments.size

    override fun createFragment(position: Int): Fragment = fragments[position]

}

有关布局

在那些并不智能的布局里(也就是除了ConstraintLayout)都要用一大串layout来决定控件的位置

layout_gravity是用来决定这个控件以哪条边为基准,比如

android:layout_gravity="end|bottom"

这样能让这个控件以右下角为原点

有关ConstraintLayout

这玩意简直是超级神器,太好使了

如果要使一个控件的尺寸随别的控件变化,只要把它的尺寸设为0dp,然后设置这个方向上对其哪个控件(的两条边)就好

杂项

有关MediaPlayer

这玩意有个神奇的特性那就是即使所处的界面关闭了还会继续播放

所以比较方便的做法就是在界面关闭时把播放一起关了

如果播放操作是在ViewModel中写的,那就可以专门准备个MediaPlayer然后每次播放都重新初始化一次,界面关闭也别忘了释放资源

有关Bitmap

Bitmap是个保存了图像信息的对象

可以通过很多方式创建

比如从资源文件

val bitmap = BitmapFactory.decodeResource(context.resources, R.drawable.image) // decode,意为解码

从文件

val file = File("/path/to/image.jpg")
val bitmap = BitmapFactory.decodeFile(file.absolutePath)

从输入流

val inputStream = FileInputStream("image.jpg")
val bitmap = BitmapFactory.decodeStream(inputStream)

还可以生成空白的来画画

Bitmap可以用compress()来把图像压缩成别的格式的文件

有关语言(平时说的那个

一般的语言文件夹格式是

values-zh-CN这样,有language和region两部分

当然region省略也是可以的

如果是自定义语言,可以这样

values-b+zh+ME

有关attachBaseContext

这玩意是更新资源文件的一个方法,接收一个Context然后更新现在的页面

可以用来更新页面语言

有关ContextCompat

这玩意可以获取一个资源的示例,用法是ContextCompat.get啥啥啥(context, id)

这样就能在代码中一遍应用多种不同模式下的资源

不知道该放到哪里的东西

lifecycleScope.launch {
            while (true) {
                delay(10000)
                lifecycleScope.launch(Dispatchers.Main) {
                    reloadFragment(this@HomepageFragment)
                }
            }
        }

this还能这么用?!

有关习惯

一定,一定要记得初始化啊!

特别鸣谢:ChatGPT