一個(gè)TextView實(shí)現(xiàn)文本展開(kāi)功能

在一個(gè)列表顯示消息時(shí)帝洪,文本過(guò)多需要進(jìn)行收縮顯示,點(diǎn)擊顯示全部時(shí)在展開(kāi)辩涝!先看下效果圖

文本內(nèi)容我是便輸入的,當(dāng)點(diǎn)擊查看全部時(shí)會(huì)顯示全部?jī)?nèi)容勘天,這邊我是設(shè)置做多顯示三行怔揩!主要一個(gè)類(lèi),如下

```

importandroid.animation.Animator;

importandroid.animation.ValueAnimator;

importandroid.content.Context;

importandroid.content.res.TypedArray;

importandroid.graphics.Bitmap;

importandroid.graphics.BitmapFactory;

importandroid.graphics.Canvas;

importandroid.graphics.Color;

importandroid.graphics.Paint;

importandroid.support.annotation.Nullable;

importandroid.text.Layout;

importandroid.text.SpannableString;

importandroid.text.Spanned;

importandroid.text.StaticLayout;

importandroid.text.TextPaint;

importandroid.text.method.LinkMovementMethod;

importandroid.text.style.ClickableSpan;

importandroid.text.style.ForegroundColorSpan;

importandroid.util.AttributeSet;

importandroid.util.TypedValue;

importandroid.view.View;

importandroid.view.ViewGroup;

importandroid.widget.RelativeLayout;

importandroid.widget.TextView;

importcom.mocoo.ezc.R;

importcom.mocoo.ezc.utils.DensityUtil;

/**

* Created by necer on 2017/4/10.

*/

public classExpandTextViewextendsRelativeLayoutimplementsView.OnClickListener {

privateTextViewmTextView;

privateTextPaintmTextPaint;//textView的畫(huà)筆

private intmTextColor;//顏色

private floatmTextSize;//大小

private intmShowLineNum=3;//顯示的最大行數(shù)

privateBitmapmUpBitmap,mDownBitmap;//指示箭頭

private intbitmapTop;//bitmap距頂部的距離

private intbitmapWith;//bitmap寬

private intbitmaphith;//bitmap寬

privatePaintmPain;//畫(huà)指示箭頭

private intfoldHeight;//折疊后的高度

private inttrueHeight;//真實(shí)高度

private intlineHeight;//Textview行數(shù)行高

private intlineCount;//Textview行數(shù)

privateStringmText;//原始數(shù)據(jù)

privateStringmFoldText;//折疊的數(shù)據(jù)

private booleanisFoldEnable=false;//是否可以折疊

private booleanisFold=true;//是否折疊

private booleanisEnough=true;//最后一行是否能容納箭頭

private booleanisDown;//箭頭指向

private floatbitmapRightOffset;//箭頭距離view右邊的距離

private intmDuration;//動(dòng)畫(huà)時(shí)間,默認(rèn)300

publicExpandTextView(Context context) {

this(context, null);

}

publicExpandTextView(Context context,@NullableAttributeSet attrs) {

this(context,attrs,0);

}

publicExpandTextView(Context context,@NullableAttributeSet attrs, intdefStyleAttr) {

super(context,attrs,defStyleAttr);

TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.ExpandTextview);

mDuration= ta.getInteger(R.styleable.ExpandTextview_duration,300);

bitmapRightOffset= ta.getDimension(R.styleable.ExpandTextview_bitmapRightOffet,DensityUtil.dip2px(getContext(),10));

mTextColor= ta.getColor(R.styleable.ExpandTextview_textColor,Color.parseColor("#000000"));

mTextSize= ta.getDimension(R.styleable.ExpandTextview_textSize,DensityUtil.dip2px(getContext(),14));

mShowLineNum= ta.getInteger(R.styleable.ExpandTextview_showLine,3);

ta.recycle();

mTextView=newTextView(getContext());

mTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX,mTextSize);

mTextView.setTextColor(mTextColor);

mTextPaint=mTextView.getPaint();

addView(mTextView);

mTextView.setOnClickListener(this);

mPain=newPaint();

mPain.setColor(getResources().getColor(R.color.theme_color));

mPain.setTextSize(40f);

mUpBitmap= BitmapFactory.decodeResource(getResources(),R.drawable.abc);

mDownBitmap= BitmapFactory.decodeResource(getResources(),R.drawable.abc);

bitmapWith=mUpBitmap.getWidth();

bitmaphith=mUpBitmap.getHeight();

}

public voidsetText(String text) {

this.mText= text;

post(newRunnable() {

@Override

public voidrun() {

dealText();

}

});

}

//要在post里面進(jìn)行脯丝,不然getWidth()得不到view的寬商膊,就無(wú)法正確得到字符串的行數(shù)

private voiddealText() {

StaticLayout staticLayout =newStaticLayout(mText,mTextPaint,getWidth() - getPaddingLeft() - getPaddingRight(),Layout.Alignment.ALIGN_NORMAL,1.0f,0f, true);

lineCount= staticLayout.getLineCount();

lineHeight= staticLayout.getHeight() /lineCount;

isFoldEnable=lineCount>mShowLineNum;

if(isFoldEnable) {

intstart = staticLayout.getLineStart(mShowLineNum-1);

intend = staticLayout.getLineEnd(mShowLineNum-1);

//獲取最后一行的內(nèi)容

String endText =mText.substring(start,end);

mFoldText=mText.substring(0,start) + endText.substring(0,endText.length() -5) +"···";

intlineWidth = (int) staticLayout.getLineWidth(lineCount-1);

isEnough= getWidth() - lineWidth - getPaddingLeft() - getPaddingRight() > (bitmapWith+bitmapRightOffset);

//能容納真實(shí)高度為textview的高度,不能容納宠进,真實(shí)高度為textview高度+一個(gè)行高晕拆,放箭頭

trueHeight=isEnough? staticLayout.getHeight() : staticLayout.getHeight() +lineHeight;

foldHeight=lineHeight*mShowLineNum;

if(isFold) {

bitmapTop=foldHeight-lineHeight/2;//bitmap開(kāi)始的位置,讓箭頭在一行的中間

String str=mFoldText+"查看全部";

mTextView.setText(getClickableSpan(str,mFoldText));

//此行必須有

mTextView.setMovementMethod(LinkMovementMethod.getInstance());

}else{

bitmapTop=trueHeight-lineHeight/2;

mTextView.setText(mText);

}

}else{

mTextView.setText(mText);

}

}

@Override

protected voidonDraw(Canvas canvas) {

super.onDraw(canvas);

if(!isFoldEnable) {

return;

}

}

public voidstartAnim(intstarHeight, intendHeight,Animator.AnimatorListener animatorListener) {

finalViewGroup.LayoutParams layoutParams =mTextView.getLayoutParams();

ValueAnimator valueAnimator = ValueAnimator.ofInt(starHeight,endHeight);

valueAnimator.addUpdateListener(newValueAnimator.AnimatorUpdateListener() {

@Override

public voidonAnimationUpdate(ValueAnimator valueAnimator) {

layoutParams.height= (int) valueAnimator.getAnimatedValue();

mTextView.setLayoutParams(layoutParams);

bitmapTop= (int) valueAnimator.getAnimatedValue() -lineHeight/2;

}

});

valueAnimator.addListener(animatorListener);

valueAnimator.setDuration(mDuration);

valueAnimator.start();

}

privateSpannableStringgetClickableSpan(String str1,String str2) {

//監(jiān)聽(tīng)器

View.OnClickListener listener =newView.OnClickListener() {

@Override

public voidonClick(View v) {

if(!isFoldEnable) {

return;

}

if(ButtonUtils.isFastClick(mDuration)) {

return;

}

if(isFold) {

isFold=false;

mTextView.setText(mText);

startAnim(foldHeight,trueHeight, newAnimator.AnimatorListener() {

@Override

public voidonAnimationStart(Animator animator) {

isDown=true;

}

@Override

public voidonAnimationEnd(Animator animator) {

}

@Override

public voidonAnimationCancel(Animator animator) {

}

@Override

public voidonAnimationRepeat(Animator animator) {

}

});

}

}

};

SpannableString spanableInfo =newSpannableString(str1);

intstart = str2.length();//超鏈接起始位置

intend = str1.length();//超鏈接結(jié)束位置

//可以為多部分設(shè)置超鏈接

spanableInfo.setSpan(newClickable(listener),start,end,Spanned.SPAN_MARK_MARK);

spanableInfo.setSpan(newForegroundColorSpan(getResources().getColor(R.color.theme_color)),start,end,Spanned.SPAN_MARK_MARK);

returnspanableInfo;

}

@Override

public voidonClick(View view) {

}

classClickableextendsClickableSpanimplementsView.OnClickListener {

private finalView.OnClickListenermListener;

publicClickable(View.OnClickListener listener) {

mListener= listener;

}

@Override

public voidonClick(View view) {

mListener.onClick(view);

}

@Override

public voidupdateDrawState(TextPaint ds) {

super.updateDrawState(ds);

ds.setUnderlineText(false);

}

}

實(shí)現(xiàn)方法主要用超鏈接的方法實(shí)現(xiàn)的,對(duì)“查看全部”這四個(gè)字進(jìn)行監(jiān)聽(tīng)點(diǎn)擊時(shí)材蹬,展開(kāi)全部?jī)?nèi)容

public classButtonUtils {

private static longlastClickTime;

public synchronized static booleanisFastClick(longduration) {

longtime = System.currentTimeMillis();

if(time -lastClickTime< duration) {

return true;

}

lastClickTime= time;

return false;

}

}

```

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末实幕,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子堤器,更是在濱河造成了極大的恐慌昆庇,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,914評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件闸溃,死亡現(xiàn)場(chǎng)離奇詭異整吆,居然都是意外死亡拱撵,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門(mén)表蝙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)拴测,“玉大人,你說(shuō)我怎么就攤上這事府蛇〖鳎” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,531評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵欲诺,是天一觀的道長(zhǎng)抄谐。 經(jīng)常有香客問(wèn)我,道長(zhǎng)扰法,這世上最難降的妖魔是什么蛹含? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,309評(píng)論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮塞颁,結(jié)果婚禮上浦箱,老公的妹妹穿的比我還像新娘。我一直安慰自己祠锣,他們只是感情好酷窥,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著伴网,像睡著了一般蓬推。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上澡腾,一...
    開(kāi)封第一講書(shū)人閱讀 49,730評(píng)論 1 289
  • 那天沸伏,我揣著相機(jī)與錄音,去河邊找鬼动分。 笑死毅糟,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的澜公。 我是一名探鬼主播姆另,決...
    沈念sama閱讀 38,882評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼坟乾!你這毒婦竟也來(lái)了迹辐?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,643評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤甚侣,失蹤者是張志新(化名)和其女友劉穎右核,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體渺绒,經(jīng)...
    沈念sama閱讀 44,095評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了宗兼。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片躏鱼。...
    茶點(diǎn)故事閱讀 38,566評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖殷绍,靈堂內(nèi)的尸體忽然破棺而出染苛,到底是詐尸還是另有隱情,我是刑警寧澤主到,帶...
    沈念sama閱讀 34,253評(píng)論 4 328
  • 正文 年R本政府宣布茶行,位于F島的核電站,受9級(jí)特大地震影響登钥,放射性物質(zhì)發(fā)生泄漏畔师。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評(píng)論 3 312
  • 文/蒙蒙 一牧牢、第九天 我趴在偏房一處隱蔽的房頂上張望看锉。 院中可真熱鬧,春花似錦塔鳍、人聲如沸伯铣。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,715評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)腔寡。三九已至,卻和暖如春掌唾,著一層夾襖步出監(jiān)牢的瞬間放前,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,945評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工郑兴, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留犀斋,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,248評(píng)論 2 360
  • 正文 我出身青樓情连,卻偏偏與公主長(zhǎng)得像叽粹,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子却舀,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容