最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android開發(fā)TextView內(nèi)的文字實(shí)現(xiàn)自動(dòng)換行

 更新時(shí)間:2022年06月11日 10:46:31   作者:最是眼前人  
這篇文章主要為大家介紹了Android開發(fā)TextView內(nèi)的文字實(shí)現(xiàn)自動(dòng)換行,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前言

相信這個(gè)方法Canvas.drawText大家一定不陌生,TextView就是使用它將文字繪制出來(lái)??墒沁@個(gè)方法并沒有文字換行的功能,也就是說(shuō)它只能繪制一行;但是TextView的文字卻是會(huì)自動(dòng)換行,當(dāng)頁(yè)面不足以顯示后面的文字時(shí)(通過(guò)android:breakStrategy屬性可以調(diào)整換行時(shí)機(jī))就會(huì)自動(dòng)換行。查看源碼后發(fā)現(xiàn)TextView是通過(guò)Layout來(lái)幫助測(cè)量文字。

Layout

Layout是一個(gè)抽象類,具體實(shí)現(xiàn)有BoringLayout、StaticLayoutDynamicLayout。 簡(jiǎn)單介紹一下:

  • BoringLayout 無(wú)聊的布局,用于單行文本,如果不確定給定的文字是否滿足可以調(diào)用isBoring方法來(lái)判斷
  • StaticLayout 靜態(tài)布局,顧名思義就是不會(huì)變化的文本。
  • DynamicLayout 動(dòng)態(tài)布局,文字可以被改變。

這里通過(guò)StaticLayout來(lái)介紹一下它們的作用。

構(gòu)造方法:

	val lineSpaceadd = 0.0f //額外的行間距
        val lineSpacemuti = 1.0f//行間距倍數(shù)
        //根據(jù)不同的版本確認(rèn)是否使用Builder
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
            mLayout = StaticLayout.Builder
                .obtain("傳入的String", string的起始坐標(biāo), string的結(jié)尾坐標(biāo), TextPaint(), width)
                .build()
        } else {
        	//傳統(tǒng)構(gòu)造方法
            mLayout = StaticLayout(
                "傳入的String",
                TextPaint(),
                width,
                Layout.Alignment.ALIGN_NORMAL,
                lineSpaceadd,
                lineSpacemuti,
                false
            )
        }

我們可以用它來(lái)干嘛呢

Layout通過(guò)傳入的String和width,來(lái)計(jì)算出每行能顯示的文字?jǐn)?shù)量。所以我們能夠獲取每一行的文字。

	mLayout.lineCount//獲取行數(shù)
        mLayout.getLineStart(0)//獲取第一行在傳入String中的起始位置
        mLayout.getLineEnd(0)//獲取第一行在傳入String中的終止位置
        mLayout.getLineVisibleEnd(2)//獲取指定行的最后可見字符(不計(jì)算空格的文本偏移量)

Layout有一個(gè)draw方法,可以直接把分行的內(nèi)容繪制到view上。

	val canvas = getCanvas()
	mLayout.draw(canvas)//傳入canvas就行啦

拓展

  • 需求

開發(fā)了小說(shuō)的閱讀軟件,我需要將每一章的內(nèi)容分配到每一個(gè)頁(yè)面。我需要獲取到每一頁(yè)能夠顯示的文字?jǐn)?shù)量和文字內(nèi)容。

  • 解決方案

此時(shí)就可以通過(guò)Layout把章節(jié)內(nèi)容分行,然后計(jì)算每一頁(yè)能夠顯示多少行,將每頁(yè)的內(nèi)容傳遞過(guò)去。

  • 如何實(shí)現(xiàn)

簡(jiǎn)單描述一下這個(gè)分頁(yè)工具:

需要傳入章節(jié)的內(nèi)容,因?yàn)橐M(jìn)行分頁(yè),肯定是需要它的。

行間距相關(guān)的兩個(gè)參數(shù)

lineSpaceAdd 額外的行間距,正數(shù)則增加行間距負(fù)數(shù)則減少,默認(rèn)為0.0f。

lineSpaceMutil 行間距倍數(shù),沒有具體的單位,默認(rèn)為1.0f,大于1.0f則增加行距,小于則減少。

這兩個(gè)參數(shù)在小說(shuō)閱讀頁(yè)面還是很重要的。 3. 閱讀頁(yè)面的高度和寬度,通過(guò)寬度使得Layout能夠?qū)?nèi)容分割成行,通過(guò)頁(yè)面高度和行高度就能夠能夠獲取每一頁(yè)能夠顯示的行數(shù)。 4. 行高度lineHeight

如果你是直接傳遞的textview來(lái)計(jì)算的話就是直接textview.getLineHeight()

如果是通過(guò)傳遞textPaint,那么就用這個(gè)計(jì)算

fun getLineHeight(): Float {
	//公式很簡(jiǎn)單,也體現(xiàn)出了行間距這兩個(gè)參數(shù)的作用
	return textPaint.textSize * lineSpaceMult + lineSpaceExtra
}

光有這些東西當(dāng)然是不夠的,文字的測(cè)量肯定需要知道文字的字體、字號(hào),在這里只需要傳入一個(gè)TextPaint就可以獲取到這些數(shù)據(jù)了。

具體實(shí)現(xiàn)

PagingTool.kt 我糾結(jié)了很久最后還是用了單例模式,代碼功底不深,有問題歡迎大家指出。

//kotlin中的單例,java的同學(xué)不用納悶
object PagingTool{
    private var width = 0//寬度
    private var height = 0//高度
    private var lineSpaceAdd = 0.0f//額外的行間距
    private var lineSpaceMutil = 1.0f//行間距倍數(shù)
    private var text:String = ""http://文字內(nèi)容
    private var textPaint = TextPaint()
    //對(duì)于畫筆的參數(shù),由于我是把閱讀頁(yè)面的配置保存在數(shù)據(jù)庫(kù)中的,通過(guò)room框架返回LiveData,實(shí)時(shí)更新字體字號(hào);當(dāng)然也可以每次配置變更就手動(dòng)更新一次。
    private lateinit var mLayout:Layout//工具的核心人物,lateinit就是延遲加載的意思,
    //setter
    public fun setHeight(height: Int) {
        this.height = height
    }
    public fun setWidth(width: Int) {
        this.width = width
    }
    public fun setPaint(textPaint:TextPaint){
    	this.textPaint = textPaint
    }
    public fun setLineSpaceAdd(spaceAdd:Float){
    	lineSpaceAdd = spaceAdd
    }
    public fun setLineSpaceMutil(spaceMutil:Float){
    	lineSpaceMutil = spaceMutil
    }
    //計(jì)算行高
    private fun getLineHeight():Int{
    	//上面說(shuō)到的計(jì)算方法
    	return textPaint.textSize*lineSpaceMutil+lineSpaceAdd
        //textView.getLineHeight()
    }
    private fun setText(str:String){
    	text = str
        mLayout = StaticLayout(
                text,
                textPaint,
                width,
                Layout.Alignment.ALIGN_NORMAL,
                lineSpaceAdd,
                lineSpaceMutil,
                false//這個(gè)參數(shù)不用在意
            )
    }
    //分頁(yè)
    public fun paging(str:String):List<String>{
    	setText(str)//設(shè)置內(nèi)容,初始化layout
        //邊界條件,為0就直接返回整個(gè)章節(jié)的內(nèi)容
        if(width == 0 || height == 0)return arrayListOf(str)
        val totalLineCount = mLayout.lineCount//總行數(shù),這個(gè)是layout測(cè)量出來(lái)的
        var pageLineCount = height / getLineHeight() //頁(yè)面高度除以行高度得到頁(yè)面允許繪制的行數(shù)
        if(pageLineCount < 1)pageLineCount = 1//這種情況,只可能出現(xiàn)在文字巨大,大到頁(yè)面高度顯示不下一行文字,那我還是設(shè)置讓他顯示一行,可以刪掉
        var pageCount = totalLineCount / pageLineCount //總行數(shù)除以頁(yè)面允許繪制的行數(shù),得到分頁(yè)數(shù)量
        if (totalLineCount % pageLineCount > 0)//還剩下有幾行,組成最后一頁(yè)
        	pageCount++
        val list = ArrayList<String>()
        //現(xiàn)在就只需要將內(nèi)容按頁(yè)添加到這個(gè)list中
        for(i in 0 until pageCount){
            var temp = (i + 1) * pageLineCount
            temp--
            if (temp >= totalLineCount)
                temp = totalLineCount - 1
            val start = mLayout.getLineStart(i * pageLineCount)
            val end = mLayout.getLineEnd(temp)
            //獲取到每一頁(yè)的起始坐標(biāo),結(jié)尾坐標(biāo)
            val string = text.substring(start, end)
            list.add(string)
        }
        //這個(gè)時(shí)候就已經(jīng)把內(nèi)容分頁(yè)了,list的size就是頁(yè)數(shù)
        return list
    }
}

手?jǐn)]的,沒有跑過(guò)大致思路是這樣,也許會(huì)有小bug,大問題應(yīng)該沒有吧,看個(gè)思路就好,更多關(guān)于Android開發(fā)TextView自動(dòng)換行的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Handler與Android多線程詳解

    Handler與Android多線程詳解

    一開始,相信很多人都以為myThread中的run()方法會(huì)在一個(gè)新的線程中運(yùn)行,但事實(shí)并非如此。以下代碼中的handler并沒有調(diào)用線程myThread的start()方法,而是直接調(diào)用了run()方法,這也就意味著實(shí)際上并沒有創(chuàng)建一個(gè)新的線程,只是在當(dāng)前線程中調(diào)用run()方法而已
    2013-10-10
  • Flutter實(shí)現(xiàn)頁(yè)面路由及404路由攔截

    Flutter實(shí)現(xiàn)頁(yè)面路由及404路由攔截

    這篇文章介紹了Flutter實(shí)現(xiàn)頁(yè)面路由及404路由攔截的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2021-11-11
  • 通過(guò)Android trace文件分析死鎖ANR實(shí)例過(guò)程

    通過(guò)Android trace文件分析死鎖ANR實(shí)例過(guò)程

    遇到ANR(Application Not Responding)是比較常見的問題,產(chǎn)生ANR的原因有很多,比如CPU使用過(guò)高、事件沒有得到及時(shí)的響應(yīng)、死鎖等,下面將通過(guò)一次因?yàn)樗梨i導(dǎo)致的ANR問題,來(lái)說(shuō)明如何通過(guò)trace文件分析ANR問題
    2013-06-06
  • Android端部署DeepSeek的詳細(xì)教程

    Android端部署DeepSeek的詳細(xì)教程

    DeepSeek最近幾個(gè)月很火熱,很多產(chǎn)品以及企業(yè)都在接入DeepSeek,比如微信搜索接入,可以搜索公眾號(hào)信息并總結(jié),這個(gè)對(duì)于查一些資料還挺好用,畢竟手機(jī)才是用戶用的最多的,既然談到了手機(jī),那么DeepSeek能否部署于手機(jī)之上呢,本文給大家介紹了android端部署的DeepSeek方法
    2025-03-03
  • Retrofit實(shí)現(xiàn)圖文上傳至服務(wù)器

    Retrofit實(shí)現(xiàn)圖文上傳至服務(wù)器

    本文主要介紹了Retrofit實(shí)現(xiàn)圖文上傳至服務(wù)器的相關(guān)知識(shí)。具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧
    2017-03-03
  • Android 使用XML做動(dòng)畫UI的深入解析

    Android 使用XML做動(dòng)畫UI的深入解析

    在Android應(yīng)用程序,使用動(dòng)畫效果,能帶給用戶更好的感覺。做動(dòng)畫可以通過(guò)XML或Android代碼。本教程中,介紹使用XML來(lái)做動(dòng)畫。在這里,介紹基本的動(dòng)畫,如淡入,淡出,旋轉(zhuǎn)等,需要的朋友可以參考下
    2013-07-07
  • Android個(gè)人中心的頭像上傳,圖片編碼及截取實(shí)例

    Android個(gè)人中心的頭像上傳,圖片編碼及截取實(shí)例

    本篇文章主要介紹了Android個(gè)人中心的頭像上傳,圖片編碼及截取實(shí)例,非常具有實(shí)用價(jià)值,需要的朋友可以參考下。
    2016-12-12
  • 解決android studio卡頓,提升studio運(yùn)行速度的方法

    解決android studio卡頓,提升studio運(yùn)行速度的方法

    這篇文章主要介紹了解決android studio卡頓,提升studio運(yùn)行速度的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-03-03
  • Android設(shè)置TextView首行縮進(jìn)示例代碼

    Android設(shè)置TextView首行縮進(jìn)示例代碼

    使用過(guò)word的都會(huì)知道,在文字排版的時(shí)候經(jīng)常要設(shè)置首行縮進(jìn),這樣才會(huì)使排版更整齊,那么在Android中當(dāng)需要設(shè)置首行縮進(jìn)的時(shí)候該腫么辦呢,下面一起來(lái)看看。
    2016-08-08
  • 常見的8個(gè)Android內(nèi)存泄漏問題及解決方法

    常見的8個(gè)Android內(nèi)存泄漏問題及解決方法

    在Android開發(fā)中,內(nèi)存泄漏是一個(gè)常見的問題,這個(gè)問題可能會(huì)導(dǎo)致應(yīng)用程序變慢、崩潰或者消耗大量的內(nèi)存,最終導(dǎo)致設(shè)備性能下降,本文就給大家總結(jié)一下最常見的8個(gè)Android內(nèi)存泄漏問題及解決方法,需要的朋友可以參考下
    2023-07-07

最新評(píng)論

三亚市| 开鲁县| 临潭县| 轮台县| 彰武县| 西充县| 荔波县| 嘉黎县| 礼泉县| 云霄县| 六安市| 衡南县| 石城县| 克东县| 天全县| 北宁市| 乐平市| 永宁县| 陇南市| 中牟县| 伊川县| 保定市| 莫力| 宁蒗| 磐石市| 扶沟县| 安新县| 葫芦岛市| 故城县| 万山特区| 大埔区| 榆中县| 珲春市| 洪洞县| 通榆县| 房山区| 晋城| 泰宁县| 峨眉山市| 桐柏县| 巨野县|