比較Kotlin OR Flutter 誰好, 就像在比較[程序員]和[畫家]誰[唱歌]比較好聽
Kotlin是語言,完美平復了我對Java的恨鐵不成鋼的心情。
Flutter是框架,完美實現了我一套代碼,六端運行的夢想。
程序員
Flutter是和Android一個等級的,它們都是運行在設備上的框架
Kotlin是和Dart一個等級的,它們都是新時代的編程語言
那誰更香? 別問,問就都香。
若是你還在Kotlin和Flutter之間舉棋不定
那我就爲你指條路: 去研究[數據結構和算法分析]
研究到想吐的時候再來選擇,若是仍是在Kotlin和Flutter舉棋不定
那我就爲你指條路: 去研究[數據結構和算法分析]
研究到想吐的時候再來選擇,若是仍是在Kotlin和Flutter舉棋不定
那我就爲你指條路: 去研究[數據結構和算法分析]
研究到想吐的時候再來選擇,若是仍是在Kotlin和Flutter舉棋不定
...
這樣最終你就會成爲一個[數據結構和算法分析]的大師
而這樣的大師擁有同時掌握Kotlin和Flutter的耐力和技術支持
複製代碼
經過本篇想說明: 不是什麼技術好很差,而是你能幹什麼。
就像做文模板、中文漢字你都認識,卻沒法寫出流芳百世的佳做
限制你的並不是是語言/框架自己,而是你的思惟分析和解決問題的能力
算法
王侯將相寧有種乎? 何須貼上好壞的標籤,非爭個天下第一? 香不就好了嗎!
編程
Kotlin | Flutter |
---|---|
![]() |
![]() |
[1] 類經過[class]關鍵字定義,類名[大駝峯]
[2] 構造器關鍵字[constructor],可直接跟在類名後
[3] 繼承經過 : 指定父類
複製代碼
class HandleView constructor(context: Context, attrs: AttributeSet? = null) : View(context, attrs){
}
複製代碼
[1] 經過[var]關鍵字指定變量,
[2] 經過[privite]關鍵字修飾私有權限
[3] 建立對象[不須要] new 關鍵字
[4] 一條語句的末尾[不須要] ;
[5] init代碼塊內能夠盛放數據初始邏輯
[6] 對於對象的get/set方法,可以使用簡寫方式
複製代碼
class HandleView constructor(context: Context, attrs: AttributeSet? = null) : View(context, attrs){
private var paint:Paint = Paint()
init {
paint.color = Color.BLUE
paint.isAntiAlias=true
paint.style=Paint.Style.FILL
}
}
複製代碼
[1] 方法的關鍵字[fun]
[2] 複寫的關鍵字[override]
[3] 入參格式 [名稱:類型 ]
複製代碼
class HandleView constructor(context: Context, attrs: AttributeSet? = null) : View(context, attrs){
//英雄所見...
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
canvas.drawCircle(100f,100f,50f,paint)
}
}
複製代碼
這裏先直接放在
setContentView
裏看下效果canvas
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(HandleView(this))
}
}
複製代碼
以下圖,在移動時會觸發事件,根據事件來處理小圓的座標
當超越區域時,對其進行限定。放手時回到中心瀏覽器
zoneR
:背景區域大小,即限定搖桿的區域
handleR
:搖桿大小centerX,centerY
搖桿中心偏移bash
private var zoneR: Float = 150f
private var handleR: Float = 80f
priate var centerX: Float = 0f
private var centerY: Float = 0f
複製代碼
繪製圓時,移動了一下畫布,將畫布左上角和中心重合微信
[1] 當函數返回值只要一行時,能夠直接用 =
複製代碼
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
canvas.translate(maxR(), maxR())
paint.alpha = 100
canvas.drawCircle(0f, 0f, zoneR, paint)
paint.alpha = 150
canvas.drawCircle(centerX, centerY, handleR, paint)
}
fun maxR():Float = zoneR + handleR
複製代碼
核心就是處理好小圓的圓心在畫布座標系的位置。
分爲在圓內和圓外兩種狀況:
觸點在域內,根據觸點位置肯定搖桿圓心位置
觸點在域外,搖桿圓心位置在域的邊緣遊走數據結構
在parser方法裏,實現經過atan2獲取夾角(圖左)
而後轉化爲一般的座標系(圖左),因爲再根據畫布座標系校訂90°框架
[1] when 用於條件分支,至關於switch
複製代碼
override fun onTouchEvent(event: MotionEvent): Boolean {
when (event.action) {
MotionEvent.ACTION_UP -> reset()
else -> parser(event)
}
invalidate()
return true
}
private fun reset() {
centerX = 0f
centerY = 0f
}
private fun parser(event: MotionEvent) {
centerX = event.x - maxR()
centerY = event.y - maxR()
var rad = atan2(centerX, centerY)
if(centerX<0){
rad += 2*PI.toFloat()
}
val thta = rad- PI.toFloat()/2 //旋轉座標系90度
if (sqrt(centerX * centerX + centerY * centerY) > zoneR) {
centerX = zoneR * cos(thta)
centerY = -zoneR * sin(thta)
}
}
複製代碼
如今數據是在View內部的,須要將它們暴露出去,好比旋轉的角度,位移百分比
Java中設置監聽,還要囉嗦一堆弄接口,校驗回調。
因爲Kotlin函數也是類型,回調起來就so easy數據結構和算法
[1] (rad:Float, offset:Float) -> Unit 表明一種函數類型
複製代碼
lateinit var onHandleListener:(rad:Float, offset:Float) -> Unit
private fun parser(event: MotionEvent) {
//英雄所見...
val len = sqrt(centerX * centerX + centerY * centerY)
onHandleListener(rad,len/zoneR)
}
複製代碼
使用:
[1] Kotlin 的lambda 表達式形式以下
複製代碼
handleView.onHandleListener= {
rad,offset ->
Log.e("MainActivity","角度${rad*180/Math.PI},位移:${offset}")
}
複製代碼
很明顯,移動中須要改變狀態,使用基礎自繼承自StatefulWidget
[1] 類經過[class]關鍵字定義,類名[大駝峯]
[2] 繼承經過 [extends] 指定父類
[3] final 修飾不可變量
[4] 構造函數經過 {this.XXX} 初始化變量,可經過具名傳參
[5] 函數只要一行時,經過 => 簡寫
複製代碼
class HandleWidget extends StatefulWidget {
final double zoneR;
final double handleR;
HandleWidget(
{this.zoneR = 60.0,
this.handleR = 30.0});
@override
_HandleWidgetState createState() => _HandleWidgetState();
}
複製代碼
[1] 覆寫可以使用 @override 註解
[2] get關鍵字XXX,能夠像同樣屬性訪問XXX
[3] 私有包/類/字段 經過_XXX指定
複製代碼
class _HandleWidgetState extends State<HandleWidget> {
double zoneR;
double handleR;
double centerX=0.0;
double centerY=0.0;
@override
void initState() {
zoneR=widget.zoneR;
handleR=widget.handleR;
super.initState();
}
@override
Widget build(BuildContext context) {
return CustomPaint(
painter: _HandleView(zoneR: zoneR, handleR: handleR, centerX: centerX, centerY: centerY)
)
);
}
double get maxR => zoneR + handleR;
}
複製代碼
[1] ..級聯操做,至關於該對象
複製代碼
class _HandleView extends CustomPainter {
var _paint = Paint();
var zoneR;
var handleR;
var centerX;
var centerY;
_HandleView({this.zoneR, this.handleR, this.centerX, this.centerY}) {
_paint
..color = Colors.blue
..style = PaintingStyle.fill
..isAntiAlias = true;
}
double get maxR => zoneR + handleR;
@override
void paint(Canvas canvas, Size size) {
canvas.translate(maxR, maxR);
_paint.color = _paint.color.withAlpha(100);
canvas.drawCircle(Offset(0, 0), zoneR, _paint);
_paint.color = _paint.color.withAlpha(150);
canvas.drawCircle(Offset(centerX, centerY), handleR, _paint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
複製代碼
經過GestureDetector進行嵌套,便可讓任意組件響應事件
@override
Widget build(BuildContext context) {
return GestureDetector(
onPanEnd: (d) => reset(),
onPanUpdate: (d) => parser(d.localPosition),
child: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: CustomPaint(
painter: _HandleView(
zoneR: zoneR,
handleR: handleR,
centerX: centerX,
centerY: centerY),
),
),
);
}
複製代碼
邏輯和上面是一毛同樣的,因此,你悟到了什麼?
reset() {
centerX = 0;
centerY = 0;
setState(() {});
}
parser(Offset offset) {
centerX = offset.dx - maxR;
centerY = offset.dy - maxR;
var rad = atan2(centerX, centerY);
if (centerX < 0) {
rad += 2 * pi;
}
var thta = rad - pi / 2; //旋轉座標系90度
if (sqrt(centerX * centerX + centerY * centerY) > zoneR) {
centerX = zoneR * cos(thta);
centerY = -zoneR * sin(thta);
}
setState(() {});
}
複製代碼
[1] 調用函數對象 Function(double,double) onHandleListener;
複製代碼
class HandleWidget extends StatefulWidget {
final double zoneR;
final double handleR;
final Function(double,double) onHandleListener;
HandleWidget({this.zoneR = 60.0, this.handleR = 30.0,this.onHandleListener});
@override
_HandleWidgetState createState() => _HandleWidgetState();
}
複製代碼
parser(Offset offset) {
//英雄所見...
var len = sqrt(centerX * centerX + centerY * centerY);
if(widget.onHandleListener!=null) widget.onHandleListener(rad,len/zoneR);
setState(() {});
}
複製代碼
兩種實現的核心是什麼?也就那一個解析的過程
若是過程都明白,你管它是Kotlin仍是Flutter,就是js也能夠在瀏覽器上畫出來
你須要學的從不是使用框架/語言的能力
,而是思惟分析
和解決問題
的能力
限制你的並不是是框架/語言,而是你貧瘠的想象力、控制力、創造力
Flutter 能夠用兩天就能上手,Kotlin用一天就能瞭解語法
以後的是你的固有瓶頸,而非框架/語言的問題,知道作什麼是最重要的
好了,若是你還在猶豫,你能夠去研究[數據結構和算法分析]了,吐了再回來。
Kotlin和Dart的語法都很是簡潔。Android自己的View體系比較臃腫,畢竟放在xml裏,溝通起來須要費些勁
Flutter組件出來起來很是靈活,複用很是棒。最好的是屬性能夠很容易修改
Android裏自定義View的屬性挺麻煩,增長、刪除、修改都費勁
Kotlin無可挑剔,除了移動端,Spring運用,還能玩js
Flutter也無可挑剔,UI寫起來很是爽,能夠處理數據,管理狀態,六端同開,前途無量
還在猶豫Flutter移動開發的人,如今Flutter對於桌面的支持,已經遠遠超過了你的想象。
@張風捷特烈 2020.01.21 未允禁轉
個人公衆號:編程之王
聯繫我--郵箱:1981462002@qq.com --微信:zdl1994328
~ END ~