丝袜人妻一区二区三区_少妇福利无码视频_亚洲理论片在线观看_一级毛片国产A级片

當(dāng)前位置:首頁 > 教育

textview 自定義控件之可折疊TextView

8月8日,特斯拉汽車(Tesla Motors)首席執(zhí)行官埃隆馬斯克(Elon Musk)發(fā)布推文,提出將特斯拉私有化的想法,震驚了投資者。如果特斯拉真的私有化,這將是同類交易中最大的一筆。馬斯克在推特上說:“首先,最終的決定還沒有最終確定,但這樣做的原因是為了創(chuàng)造更好的環(huán)境,讓特斯拉更好地運(yùn)營?!?/p>

作者簡介

這個(gè)來自zzp2138的投稿分享了自定義可折疊TextView,大家來看看!希望大家喜歡。

zzp2138的博客地址:

https://www.jianshu.com/u/8b4e659ce82c

前言

當(dāng)文本內(nèi)容超過指定的行數(shù)時(shí),將顯示省略號和全文。

上圖效果可以在微博和bilibili上找到。這里我選擇繼承AppCompatTextView實(shí)現(xiàn)。

主體

實(shí)現(xiàn)理念

當(dāng)內(nèi)容超過指定行數(shù)后,計(jì)算最大行數(shù)第一個(gè)(start)和最后一個(gè)字符(end)在整個(gè)字符串里面的位置測量要拼接的內(nèi)容(demo中是... 全文)的寬度計(jì)算跟拼接內(nèi)容寬度相當(dāng)?shù)淖址麄€(gè)數(shù)(num)將整個(gè)字符串從0到(end-num)進(jìn)行截取拼接要顯示的內(nèi)容,設(shè)置點(diǎn)擊事件設(shè)置文字

這里會(huì)有點(diǎn)小問題。提示內(nèi)容緊跟著原文,不在TextView的邊界上。點(diǎn)擊事件用點(diǎn)擊面板設(shè)置。如果文本視圖設(shè)置了點(diǎn)擊事件,它們將與文本視圖本身的點(diǎn)擊事件同時(shí)被觸發(fā)。如果沒有設(shè)置,點(diǎn)擊換句話說,點(diǎn)擊事件不會(huì)傳輸?shù)礁敢晥D,而是被TextView消費(fèi)掉。如下圖:

同時(shí)響應(yīng)點(diǎn)擊事件

單擊事件不能傳遞給父視圖

這是另一種思考方式

前幾步跟上面相同,都是對內(nèi)容進(jìn)行截取,設(shè)置文字文字繪制完畢后,手動(dòng)把提示的內(nèi)容繪制上去添加點(diǎn)擊事件

這個(gè)方法可以保證提示在TextView的邊界上,但是點(diǎn)擊事件需要重寫onTouchEvent()的設(shè)置,有點(diǎn)麻煩。

先說具體實(shí)施的關(guān)鍵步驟:

內(nèi)容截取

SpannableStringBuilder span = NewsAnnablestringbuilder();

int start = layout . getlinestart(mShowMaxLine-1);

intent = layout . GetLineEnd(MsHowMaxLine-1);

if(mTipGravity == END) {

TextPaint paint = getPaint();

string builder builder = NewStringBuilder(ELLIPSize _ END)。追加(" ")。追加(MFoldText);

end-= paint . BreakText(Moriginaltext,start,end,false,paint . MeasureText(builder . ToString()),null);

} else{

end-;

}

當(dāng)內(nèi)容行數(shù)超過最大行數(shù)時(shí),文本將被攔截。布局是TextView的布局,其中g(shù)etLineStart()和getLineEnd()分別獲取該行第一個(gè)和最后一個(gè)字符的位置(這里的位置是從第一個(gè)字符開始計(jì)算的)。breakText()方法計(jì)算要截取的字符數(shù)。

下面是breakText()方法的簡要描述:

參數(shù):

測量的字符串測量開始的位置測量結(jié)束的位置測量方向,true從前往后,false從后往前截取的字符串最大寬度截取字符串實(shí)際寬度

最后,返回要攔截的字符數(shù)。截取內(nèi)容后,對提示文本進(jìn)行處理,并簡要說明以下兩種方法

方法1:直接拼接內(nèi)容,設(shè)置點(diǎn)擊事件

CharSequence elli psize = Moriginaltext . subsequence(0,end);

span . append(ellipsize);

span . append(ELLIPSize _ END);

if(mTipGravity == END) {

span . append(" ");

} else{

span . append(" n ");

}

intlength

if(isExpand) {

span . append(MexpandText);

length = mexpandtext . length();

} else{

span . append(mFoldText);

length = mfoldtext . length();

}

if(mTipClickable) {

span.setSpan(mSpan,span.length() - length,span.length(),Spanned。SPAN _ INCLUSIVE _ EXCLUSIVE

setMovementMethod(Linkmovementmethod . GetInstance());

}

span . set span(NewForeGroundColorspan(MTIPColor),span.length() - length,span.length(),跨區(qū)數(shù)。SPAN _ INCLUSIVE _ EXCLUSIVE

}

super.setText(span,type);

通過SpannableString將文本拼接在截取的內(nèi)容上,并設(shè)置相應(yīng)的點(diǎn)擊事件。

方法二:重寫onDraw()方法繪制提示文本,重寫onTouchEvent()設(shè)置click事件

折疊狀態(tài)

@覆蓋

protectedvoidonDraw(畫布畫布){

super . ondraw(canvas);

if(isOverMaxLine & amp;& amp!isExpand) {

//折疊

if(mTipGravity == END) {

minx = getwidth()-getpaddingslip()-getpaddinglight()-gettextwidth("全文");

maxX = getWidth()-getpadding left()-getpadding right();

minY = getHeight() - (getPaint()。getFontMetrics()。下降- getPaint()。getFontMetrics()。ascent)-getPaddingBottom();

maxY = getHeight()-getPaddingBottom();

Canvas.drawText("全文",minX,

getHeight() - getPaint()。getFontMetrics()。下降- getPaddingBottom(),mPaint);

} else{

minX = GetPaddingLeft();

MaxX = minX+getTextWidth("全文");

minY = getHeight() - (getPaint()。getFontMetrics()。下降- getPaint()。getFontMetrics()。ascent)-getPaddingBottom();

maxY = getHeight()-getPaddingBottom();

Canvas.drawText("全文",minx,getheight ()-getpaint()。getfontmetrics()。depression-getpadding bitmap(),MPa int);

}

}

}

文本截取后,重寫onDraw()方法計(jì)算坐標(biāo),繪制文本。

PS: minx、maxx、miny、maxy四個(gè)值用于后續(xù)的點(diǎn)擊事件,如果不需要可以忽略。這四個(gè)值分別對應(yīng)于提示左上角和右下角的坐標(biāo)。

擴(kuò)展?fàn)顟B(tài)

//文本擴(kuò)展

SpannableStringBuilder span enable = NewsAnnablestringbuilder(Moriginaltext);

if(IsShowTiptafterExpand){

Spannable.append("折疊全文");

span enable . set SPan(NewForeGroundColorSPan(MTipColor),span enable . length()-5,span enable . length(),跨區(qū)數(shù)。SPAN _ INCLUSIVE _ EXCLUSIVE

}

super . SetText(span enable,type);

這里的坐標(biāo)計(jì)算比上面稍微復(fù)雜一點(diǎn),這里的提示可能會(huì)換線。

所以要多加一個(gè)變量才能多記錄一個(gè)y值。

intmLineCount = getLineCount();

layout layout = GetLayout();

minx = getpadding foot()+布局。get primary水平(spannable。tostring()。last index of(" closed ")-1);

maxx = getpaddingslip()+layout . getsecondariholizontal(span enable . tostring()。last indexof(" text ")+1);

rect bound = NewRect();

if(mLineCount & gt;originalinecount){

//不在一條線上

layout . getlinebounds(originalinecount-1,bound);

minY = getPaddingTop()+bound . top;

middleY = minY + getPaint()。getFontMetrics()。下降- getPaint()。getFontMetrics()。上升;

maxY = middleY + getPaint()。getFontMetrics()。下降- getPaint()。getFontMetrics()。上升;

} else{

//同一行

layout . getlinebounds(originalinecount-1,bound);

minY = getPaddingTop()+bound . top;

maxY = minY + getPaint()。getFontMetrics()。下降- getPaint()。getFontMetrics()。上升;

}

PS:這里我選擇直接拼接的方法。如果展開狀態(tài)也需要貼邊界,請參考折疊狀態(tài)自行實(shí)現(xiàn)。

最后,重寫onTouchEvent()來設(shè)置點(diǎn)擊事件

@覆蓋

public booleanTouchEvent(MotionEvent事件){

if(mTipClickable) {

switch(event . Getactionmasked()){

caseMotionEvent。動(dòng)作_向下:

click time = system . current timemillis();

if(!isClickable()) {

if(isInRange(event.getX()、event . GetY()){

returntrue

}

}

打破;

caseMotionEvent。操作_取消:

caseMotionEvent。動(dòng)作_向上:

long deltime = system . current timemillis()-點(diǎn)擊time;

點(diǎn)擊時(shí)間= 0L

if(DelTiME & lt;view configuration . gettaptimeout()& amp;& ampis RanGe(event . GetX()、event . GetY()){

isExpand =!isExpand

setText(Moriginaltext);

returntrue

}

打破;

默認(rèn):

打破;

}

}

returnsuper.onTouchEvent(事件);

}

PS: action _ down在這里,我們需要判斷點(diǎn)擊事件是否是在TextView本身設(shè)置的。如果沒有,我們需要人工retrun true,否則點(diǎn)擊事件無法傳輸。如果點(diǎn)擊范圍太小,我們可以自行調(diào)整isInRange方法。

讓我們看看方法1中兩個(gè)問題的原因

我們先來看看TextView的onTouchEvent()方法

privateavotixficfocusableandclickablesettings(){

如果(移動(dòng)!= null|| (mEditor!= null & amp& ampmEditor.mKeyListener!= null)) {

setFocusable(FOCUSABLE);

setClickable(true);

setLongClickable(true);

} else{

setFocusable(FOCUSABLE _ AUTO);

setClickable(false);

setLongClickable(false);

}

}

發(fā)現(xiàn)這里的設(shè)置被更改了,導(dǎo)致了上面的一系列問題。因此,我們還需要在設(shè)置了ClickableSpan之后調(diào)用

setFocusable(false);

setClickable(false);

setLongClickable(false);

這樣,事件就可以傳遞給父視圖

最終效果

總結(jié)

最后附上演示地址。歡迎多交流!

java版本

https://github.com/zzp2138/FoldText_Java

kotlin版本

https://github.com/zzp2138/FoldText_Kotlin

1.《textview 自定義控件之可折疊TextView》援引自互聯(lián)網(wǎng),旨在傳遞更多網(wǎng)絡(luò)信息知識,僅代表作者本人觀點(diǎn),與本網(wǎng)站無關(guān),侵刪請聯(lián)系頁腳下方聯(lián)系方式。

2.《textview 自定義控件之可折疊TextView》僅供讀者參考,本網(wǎng)站未對該內(nèi)容進(jìn)行證實(shí),對其原創(chuàng)性、真實(shí)性、完整性、及時(shí)性不作任何保證。

3.文章轉(zhuǎn)載時(shí)請保留本站內(nèi)容來源地址,http://f99ss.com/jiaoyu/1606223.html

上一篇

卡路里和千焦 脂肪、卡路里、熱量,到底啥關(guān)系?

下一篇

韓國綜藝我們結(jié)婚了 安利5部韓國戀愛綜藝,《我們結(jié)婚了》上榜,你看過哪幾檔?

巴西一托兒所發(fā)生持刀行兇事件致5人死亡 還原事發(fā)經(jīng)過及背后真相!

巴西一托兒所發(fā)生持刀行兇事件致5人死亡 還原事發(fā)經(jīng)過及背后真相!

巴西南部圣卡塔琳娜州一所托兒所當(dāng)?shù)貢r(shí)間5月4日上午發(fā)生一起持刀行兇事件,導(dǎo)致3名幼兒和2名教師死亡,犯罪嫌疑人已被逮捕。當(dāng)?shù)鼐奖硎?,圣卡塔琳娜州紹達(dá)迪斯市一所托兒所的員工和附近居民4日上午報(bào)警說,一名年輕男子闖入該托兒所并持刀行...

男子地鐵上猥褻女乘客 事件詳細(xì)經(jīng)過!

男子地鐵上猥褻女乘客 事件詳細(xì)經(jīng)過!

針對“深圳一男子被指在地鐵車廂猥褻女乘客“一事,5月4日,廣東深圳市公安局公交分局官方微博發(fā)布情況通報(bào)稱,4月30日18時(shí)30分許,張某某在地鐵11號線車廂內(nèi)猥褻一名女乘客,被該女乘客發(fā)現(xiàn)后當(dāng)場斥責(zé),并用手機(jī)拍下視頻后報(bào)警。列車停...

山東景區(qū)游客墜亡翻越護(hù)欄 事件的真相是什么?

山東景區(qū)游客墜亡翻越護(hù)欄 事件的真相是什么?

山東沂蒙山銀座天蒙旅游區(qū)頭條號5月4日發(fā)布情況通報(bào)稱,5月2日13時(shí)許,天蒙景區(qū)發(fā)生一名男性游客墜落事件,景區(qū)第一時(shí)間啟動(dòng)應(yīng)急預(yù)案進(jìn)行救助。經(jīng)查,該男性游客與家人在天蒙山景區(qū)游覽時(shí),其家人手機(jī)掉落游步道護(hù)欄外,該游客不顧景區(qū)安全提...

中歐投資協(xié)定 事件詳情始末介紹!

  • 中歐投資協(xié)定 事件詳情始末介紹!
  • 中歐投資協(xié)定 事件詳情始末介紹!
  • 中歐投資協(xié)定 事件詳情始末介紹!

發(fā)票虛開涉案金額 事件的真相是什么?

5月5日晚間,國家稅務(wù)總局曝光了8起虛開發(fā)票違法典型案例。其中,北京查處了“8·27”增值稅發(fā)票虛開案,涉案金額高達(dá)109億元。為了維護(hù)正常的經(jīng)濟(jì)稅收秩序,在國家稅務(wù)總局統(tǒng)一部署下,各地稅務(wù)部門聯(lián)合公安等部門重拳出擊,在開展打擊虛...

疫苗加強(qiáng)針 事件詳情始末介紹!

疫苗加強(qiáng)針 事件詳情始末介紹!

當(dāng)?shù)貢r(shí)間5日,英國疫苗大臣扎哈維在接受當(dāng)?shù)孛襟w采訪時(shí)表示,英國公共衛(wèi)生系統(tǒng)可能將從9月份開始為民眾注射疫苗加強(qiáng)針。但是現(xiàn)在還沒有決定注射哪種疫苗,以及從哪個(gè)年齡段開始注射。此外,英國政府將再撥款約2930萬英鎊,建立新的病毒檢測實(shí)...

韓國娛樂圈事件 2019韓國娛樂圈十大事件之首非它莫屬,甚至是韓流發(fā)展史之最!

  • 韓國娛樂圈事件 2019韓國娛樂圈十大事件之首非它莫屬,甚至是韓流發(fā)展史之最!
  • 韓國娛樂圈事件 2019韓國娛樂圈十大事件之首非它莫屬,甚至是韓流發(fā)展史之最!
  • 韓國娛樂圈事件 2019韓國娛樂圈十大事件之首非它莫屬,甚至是韓流發(fā)展史之最!

中國未解之謎詭異事件 中國未解之謎至今未解的有哪些

  • 中國未解之謎詭異事件 中國未解之謎至今未解的有哪些
  • 中國未解之謎詭異事件 中國未解之謎至今未解的有哪些
  • 中國未解之謎詭異事件 中國未解之謎至今未解的有哪些