最近我們的產品來了個新的模塊,類似猿題庫一樣,給學生做題提高成績的。
要求如下:
1:支持單選、多選、填空題
2:支持圖片文字混排
3:輸入框有交互,排版精致美觀
4:為了體驗優化,不能使用網頁實現效果
花了兩個禮拜開發優化,效果看起來達到了猿題庫那種圖文、輸入框混排的效果,截圖如下:

因涉及到公司的核心業務,就不分享源碼了,講解下大概實現步驟
1:圖片文字混排
系統的TextView通過ImageGetter就可以原生實現對文本img標簽的支持,從而達到圖文混排的效果。
Html.fromHtml(text, asyncImageGetter, null);
具體實現步驟請參考Github上的一個庫https://github.com/zzhoujay/RichText
2:輸入框混排
如何實現一個自己的TextView,請參考此篇博客http://blog.csdn.net/yellowcath/article/details/27527275
下面是我具體的實現步驟,請在步驟1圖文混排源碼基礎上進行閱讀。
最后的UI結構應該是這樣子的,用輸入框蓋在透明的占位圖上,達到了輸入框混排的效果。
--容器
--圖文混排TextView
--輸入框A
--輸入框B
--輸入框C
2.0:根據題目答案數量,生成對應數量的輸入框,添加到容器中,設置為不可見
2.1:題目中的輸入框標記,通過正則表達式使用圖片Img標簽代替,src設置為:Input標簽+輸入框對應答案ID+該輸入框對應答案文字長度
2.2:在ImageGetter中,發現當前圖片包含Input標簽,則使用一個透明的占位圖代替,寬度為畫筆的文本尺寸*答案長度
2.3:參考本步驟開始給出的代碼地址,稍微加工下就可以拿來實現自己的TextView,用於逐行繪制時,獲取當前的寬度和高度。
2.4:在onDraw事件里,遇到當前繪制的Span是圖片類型,且src包含Input標簽的,獲取當前的高度和左邊距,通過下面代碼獲取圖片的寬度。
imgSpan.getDrawable().getBounds().width()
2.5:用步驟4取到的數據,設置MarginLeft和MarginTop,還有寬度,通過輸入框對應答案ID來找到2.0對應的輸入框,刷新其位置和寬度
3:細節優化
1:填空題的行高比選擇題的要大,為了防止兩行文本框擠在一起。
2:輸入框UI有很多狀態:做題狀態:未獲取焦點沒值、未獲取焦點有值、獲取焦點;校對答案: 答案正確、答案錯誤
3:輸入框超過答案的長度,使用省略號...截取掉超過的文本。
4:圖片、輸入框長度最長為一行,超過圖片等比縮放。
5:圖片添加緩存,加載中給占位圖,加載失敗點擊重試(文本框里的圖片是可以響應點擊事件的,詳情參考步驟1的源碼)
6:某行有大圖的情況下,文本、輸入框垂直居中顯示;反之如果圖片是小圖(數理化公式類型),則垂直居中顯示
7:使用FragmentStatePagerAdapter 代替 FragmentPagerAdapter作為大批量內容頁的適配器。
8:在開始答題的時候,我們已經獲取到了此次所需的題目和答案數據,正則匹配出里面的圖片url,在后台提前下載好到內存中。
后記
一開始遇到圖文輸入框混排,不能用WebView,立刻百度
結果這個需求願意分享的人很少,無奈之下只能自己一步一坑解決了。
下載猿題庫的apk包,反編譯,結果看花眼了也跟蹤不到題庫的相關代碼。
倒是在開啟了布局邊界之后,在仔細觀察猿題庫的題目時,發現填空題很多地方,繪制是重疊的,得出其原理是設置輸入框位置來實現的結論。
還好有上面兩個開源的作品,在次基礎上進行開發,有思路多了。
比較奇怪的是,猿題庫ViewPager頻繁切換的時候,是會有延遲的。
我們這個一旦打開就立刻呈現在用戶面前,圖片加載完成之后,再刷新占位圖,個人覺得這樣過程要好點。
歡迎大家一起交流,有啥疑問的請留言。
