當前位置:首頁 > 安卓源碼 > 技術博客 >

Android開發這個View有點酷,填空題View特效走起!

時間:2019-10-12 17:54 來源:互聯網 作者:源碼搜藏 瀏覽: 收藏 挑錯 推薦 打印

一、寫在前面 本文講解的是如何自定義一個填空題控件,實現的方式其實有很多,最重要的是了解其中實現的思路和想法,正所謂條條大路通羅馬嘛。 在Android系統中,我們最常使用的用于展示文字和編輯文字的控件,就是TextView和EditView,這兩個控件基本上已經

一、寫在前面

本文講解的是如何自定義一個填空題控件,實現的方式其實有很多,最重要的是了解其中實現的思路和想法,正所謂條條大路通羅馬嘛。

在Android系統中,我們最常使用的用于展示文字和編輯文字的控件,就是TextView和EditView,這兩個控件基本上已經能夠滿足我們日常大部分開發需求。但是,凡事都有個但是。程序猿基本都會遇到一些比較特殊的需求,而作為一個Android開發者,最常見的特殊需求,就是一個特殊的控件,而這個控件剛好是系統沒有提供的。下面就是一個比較特別的控件,一個可填空的控件。要求可以和普通TextView一樣展示普通的文字,同時又包含可以編輯的部分,類似EditText。如下:Android開發這個View有點酷,填空題View特效走起!

看到這個,第一反應就是,這不合理啊,又是展示,又是可編輯,又是換行,沒辦法實現!結果,被人家甩了一句:那啥,學習強國App里面不就有可以填空答題的嘛!我去,這下尷尬了。如果實現不了,豈不是顯得自己很Low B!不行,無論如何都得做出來。ú拍苎实孟逻@口氣!)

二、尋尋覓覓,不得所需

哼,系統沒有的控件,我找個第三方的輪子還不行嗎?我就不信,世界這么大,還有別人沒做好的輪子!于是開啟了“常規操作模式”(Google/GitHub/百度,搜索,復制,粘貼)。果不其然,有的是輪子(ヾ(´A`)ノ゚)。比如這兩個:Android 使用代碼實現一個填空題
Android 基于TextView實現填空題他們有一些共同的特點:

1.基于TextView做文字展示
2.基于SpannableString做文字樣式變化,文字點擊等
3.必須要有一個EditText作為輸入

毫無疑問,這是系統提供的,最簡單方便的定制一個TextView和EditText結合的方法。但是,他們都存在一些問題,比如

1.非嵌入式的輸入,需要在外部提供一個可輸入的EditText
2.雖然是嵌入式的輸入,但是可編輯文字必須要固定長度,不能根據文字長短動態變化

總而言之,就是體驗還是不夠好!無奈之下,萌生了自己造一個輪子的想法。那么,我們就仿造學習強國,定制一個填空題控件唄。

三、拆輪子

既然決定自己造輪子,必然要先分析一下這個輪子,把這個輪子拆開,看看它包含些什么東西。

1.首先,最簡單的功能:顯示文字
2.其次,實現文字點擊,并彈出輸入法
3.再次,接收輸入法輸入
4.最后,光標與文字的輸入和刪除

1. 如何顯示文字?

在定義View中, 顯示文字是一件非常簡單的函數調用,無非就是

canvas.drawText(text, x, y, paint)

但是,如果你想當然的認為這個是一個簡單的事情,那你就大錯特錯了。

1)文字基線

首先,對于y坐標,指的是文字的基線(baseLine),而非文字的top坐標,這個坐標可以近似認為是文字的bottom坐標,但并沒有那么簡單。如下圖:Android開發這個View有點酷,填空題View特效走起!

關于文字的繪制,這篇下面這篇文章講得很透徹,建議不熟悉的同學可以看看自定義控件之繪圖篇( 五):drawText()詳解

2)文字換行

不可避免的問題,文字過長的時候,我們需要對它進行換行顯示,那么我們怎么樣才能知道什么時候需要換行呢?這里就涉及到一個文字寬度計算問題在Android中如何計算文字的寬度呢?如下:

private fun measureTextLength(text: String): Float {
    return mNormalPaint.measureText(text)
}

非常簡單對不對,measureText這個方法,會根據我們設定的文字畫筆中的字體大小,去測量一段文字的寬度,單位是px。需要注意的是,漢字和數字英文的寬度占位是不一樣的。 因此在換行的時候,需要特別關注和處理這兩者的關系。

3)區分普通文字和可編輯文字

既然包含特殊的文字部分,那么我們需要將其標記出來,以便做特殊的處理。這里,我使用了一個標簽<fill style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;">來編輯,舉個例子:</fill>Android開發這個View有點酷,填空題View特效走起!

這樣,經過 String.split(“<fill style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;">“)</fill> 后,就可以把這段文字拆分為多個分段。

2.可編輯字段點擊

我們知道,每個View都可以接收onTouch事件,并且可以監聽到觸摸點的x/y坐標。而在繪制文字的過程中,我們可以將可編輯文字段的坐標信息記錄下來,那么在點擊的時候,就可以判斷有沒有觸摸碰撞,如果有,那么就可以彈出輸入法。Android開發這個View有點酷,填空題View特效走起!

3.接收輸入法輸入

通常,需要一個可輸入文字的控件時,我們很少自己去定義一個控件,而是直接使用EditText,以至于我們幾乎認為只有EditText可以接收輸入法輸入。但是,其實Android每個繼承View的控件都是可以接收輸入的。那么,如何打開這個功能呢?答案就是以下兩個方法:Android開發這個View有點酷,填空題View特效走起!

其中,第一個方法返回true表示,這是一個可編輯控件,可以接收輸入法輸入。第二個方法,則返回一個InputConnection,用于接收輸入?雌饋硎沁@樣的:Android開發這個View有點酷,填空題View特效走起!

最主要的方法是commitText,輸入法輸入時,會通過這個方法將文字傳輸給控件

4.光標
1)繪制

普通的EditText在輸入時,都會有一個光標,用于表示輸入或刪除的位置。繪制光標,只需要一句代碼:

canvas.drawLine(startX, startY, stopX, stopY, paint)

沒錯,就是繪制一條線,通過修改paint的alpha值(0/255),控制線條的顯示和隱藏即可。
關鍵在于,如何確定光標的位置。

2)計算純漢字輸入時的光標位置

還記得上面2點,實現可編輯字段的點擊嗎?當我們檢測到觸摸碰撞的時候,我們就可以根據這個時候觸摸點的x坐標,以及文字的長度去判斷光標的位置。具體如何實現呢?我們從最簡單的情況來實現。假設,輸入的文字都是漢字(前面我們就說過,漢字和數字英文占位是不一樣的)。那么,這時,光標所在漢字的索引 = (觸摸點x坐標 - 被觸摸的編輯字段起始位置的x坐標)/ 單個漢字寬度那么,光標所在實際位置的x坐標就是光標x軸坐標 = (0 至 光標所在漢字的索引)這段文字的長度轉化為代碼即:

mNormalPaint.measureText(text.substring(0, index))

如下圖:
Android開發這個View有點酷,填空題View特效走起!

說明:這里的index,指的是文字在可編輯字段中的位置,也就是光標的位置光標起始位置的y坐標,就是被觸摸的可編輯字段的y坐標。光標結束位置的x坐標和起始位置相同,y坐標則為其實坐標加上文字高度

3)考慮多類型輸入時的光標位置

當輸入的文字包含漢字、英文、數字時,由于英文/數字的占位比漢字小,此時,如果按照漢字的單字來計算光標所在文字的索引,那么此時的索引比實際的索引小。這里就需要一個方法來確認:觸摸點x坐標到可編輯字段起始位置x坐標的這段長度,可以存放多少個文字。我采用的方法如下:我們知道,這段長度,可以放置的最少文字個數,就是漢字的個數。第一步,我們先取最少的漢字個數,并計算文字長度,如果這時,文字的長度沒有超過實際觸摸位置。第二步,取下一個文字,并計算文字總長度,判斷長度有沒有超過實際觸摸位置。重復第二步,直到超過實際觸摸位置。這時,這是實際的文字索引就是:(取到的最后一個文字的索引 - 1)至此,我們就得到出實際的光標位置,以及文字索引了。在此基礎上,根據光標的位置和文字索引,就可以對文字進行輸入和刪除了。具體計算如下圖所示:Android開發這個View有點酷,填空題View特效走起!

四、組裝輪子

經過上面的分解,基本上,我們就已經知道實現輪子的各個步驟,剩下的就是將上面的各個步驟拼接起來就行了。當然,具體的代碼我就不貼了。大家可以自己去看一下源碼,過程并不復雜。自定義控件嘛,每個人去實現的時候,都會有不一樣的做法,比如上面計算光標實際位置的方法,肯定會有不同的更好的方法。所以,了解實現的思想和可借助工具方法即可,沒必要太過較真。最后還一些邊邊角角的小功能,比如自定義一些可配置屬性:文字顏色,字體大小,可編輯字段格式,光標顏色等等;比如根據文字高度,自適應控件高度;比如輸入法的彈出和隱藏……不再細提,具體可看源碼。

五、總結

1.一個復雜的控件往往都可以通過拆解,拆分為一個個簡單的功能。2.從最簡單的功能開始實現,你會更有信心。3.不要放棄,一定有實現的方法。如果沒有,說明你還不夠了解一些基礎屬性,Google之。好了,以上就是給大家介紹的一種定制“填空控件”的思路,當然還有其他的實現方式。僅供大家參考。

Android開發這個View有點酷,填空題View特效走起! 轉載http://www.7937001.live/appboke/44055.html

技術博客閱讀排行

最新文章

彩票777苹果 北京赛车开奖 云南十一选五100期 江西11选5任五遗漏 佳永配资 陕西十一选五任五遗漏号 15选5百分百中奖技巧 北京pk拾赢彩专家 股票跌停还会涨吗 河北排列7 安徽十一选五