用 Kotlin 開發 Android 項目是一種什么樣的感受?(用 DSL 配置自定義 view)

前言

離上一篇文章已經過去了挺長時間,在這期間發生了不少事,比如 Kotlin 火了,比如作者我要回老家領證了2333。

關于 Kotlin 火了這事,我一直覺得這是一門很棒的語言,不火也是。但是既然現在 google 都為它開路了,那么想來今后的發展應該會很不錯。

鑒于 Kotlin 已紅遍大江南北,類似的文章現在也如雨后春筍層出不窮,作者原來的標題【用 Kotlin 開發 Android 是一種什么樣的感受?】似乎也不那么好使了,畢竟很多 Android 開發者都已經開始在嘗試,有的也許淺嘗輒止,有的也許會深入的使用下去,但終究在這個時間段再寫一些很基礎的語法文章,我個人感覺意義不大了。

最近我在用 Kotlin 做一個挺有意思的開源項目,雖然完成度還很低,但也勉強算是五臟俱全。這篇文章就當做是一個引子,來介紹介紹我這個小項目,順便讓初學 Kotlin 的各位了解一下,用這么一門語言,你能做出什么東西來。

DSL

應該有不少小伙伴做過自定義 view,也知道在 Android 中自定義 view 大致分為兩種:

1.繼承于 ViewGroup,將多個 view 組合在一起而形成
2.繼承于 View,在 canvas(畫布)上通過相應 API 繪制而成

因為上東家的各種奇葩需求,本人算是飽受 CustomView Hell 的摧殘,也明白兩種方案各有適用的場合。方案1 相對來說還比較容易上手,基本會布局就會寫,而方案2 則需要一定的學習成本,也需要一定的經驗去處理遇到的各式問題,最后的最后,是寫起來比較繁雜。那么有沒有什么辦法可以讓 canvas 繪制變得更輕松呢?

在接觸過 anko 之后,我才發現原來用代碼布局也可以那么優雅那么簡單。這里不是在給 anko 打廣告(吃瓜群眾:你口是心非),而是想介紹用 anko 布局時的寫法:

verticalLayout {
    textView {
        text = "隨便寫點啥"
        textSize = 20f
    }

    imageView {
        imageResource = R.mipmap.ic_launcher
    }
}

諸如此類代碼,大家應該都很眼熟:

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.3"

    defaultConfig {
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

沒錯,anko 布局和 gradle 的語法很像,除去少量差別,你甚至會覺得這就是同一種語言。這就是我要給大家介紹的 <b>領域特定語言(domain-specific languages,簡稱 DSL)</b>

MagicPen

MagicPen 是我發起的一個用 Kotlin 編寫的用于操作 canvas 來自定義 view 的開源項目。似乎這么說有點模糊?那我們直接上代碼和圖吧

package com.lab.zhangll.magicpen

import android.graphics.Color
import android.graphics.Paint
import android.graphics.PointF
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import com.lab.zhangll.magicpen.lib.*

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(
                magicPen {
                    val line = line {
                        start = PointF(0f, 1000f) // 線條起點
                        end = PointF(1000f, 1000f) // 線條終點
                    }

                    val bigOne = circle {
                        radius = 200f // 圓半徑

                        aboveOf(line) // 在線條上面
                        leftMargin = 500f // 左邊距
                        bottomMargin = 10f // 下邊距

                        paint = Paint().apply { color = Color.RED } // 紅色
                    }

                    text {
                        content = "我是一只小小鳥"
                        paint = Paint().apply { textSize = 40f }
                        centerIn(bigOne)
                    }

                    circle {
                        radius = 50f // 半徑
                        centerIn(bigOne) // 在大圓中間

                        gesture {
                            onClick = { Toast.makeText(this@MainActivity, "clicked", Toast.LENGTH_SHORT).show() } // 點擊時彈框
                            onDragBy = { x, y -> moveBy(x, y) } // 跟著拖動的手指動
                            onRelease = { smoothMoveToOrigin() } // 放手后滑動到原點
                        }
                    }
                }
        )
    }
}

算上package、import 和我有意識的空行,一共50行代碼,我們看看它能實現出什么樣的效果吧

magicPen.gif

相信圖文結合在一起,再加上代碼中的注釋,大家能很輕松的看明白。我像布局似的就做出了這么一個 view。包括線條、圓、文字三種圖形;也包括絕對位置、相對關系;甚至還有點擊事件、拖拽事件和平滑移動動畫。挺精簡的對吧?

可惜的是,目前支持的功能也就這么多了,畢竟這個項目才啟動沒多長時間,還有兩個有意的小伙伴也得在過一段時間之后才能學習 Kotlin 并加入這個項目的開發工作。不過在不久之后,MagicPen 將可以用來創建我能想到的大量自定義 view,請拭目以待。

項目源碼在 https://github.com/neverwoodsS/MagicPen
歡迎各位圍觀與提出不足

PS.這是在下作為單身青年的最后一篇文章

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容