一、項目簡介
項目地址:https://github.com/zhangtiansimple/FoldTextView
效果圖:
二、技術選型
本項目採用LinearLayout與TextView實現,根據開發者設置的最大行數,計算高度然後設置給LinearLayout,從而實現文本摺疊的功能。
三、具體實現
1.定義子View的佈局
即文字的展示TextView與下方“展開”、“收起”狀態展示的TextView。
<?xml version="1.0" encoding="utf-8"?>
<merge
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:id="@id/tv_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="@id/tv_state"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:padding="8dp"/>
</merge>
2.計算TextView的真實高度
private int getRealTextViewHeight(@NonNull TextView textView) {
int textHeight = textView.getLayout().getLineTop(textView.getLineCount());
int padding = textView.getCompoundPaddingTop() + textView.getCompoundPaddingBottom();
return textHeight + padding;
}
重寫onMeasure
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//如果沒有重新佈局或者此時沒有加入到視圖中 直接默認測量並返回
if (!isReLayout || getVisibility() == View.GONE) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
return;
}
isReLayout = false;
//如果可以顯示的下 則不需要狀態Tv
mStateTv.setVisibility(View.GONE);
mContentTv.setMaxLines(Integer.MAX_VALUE);
//測量
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//如果實際行數小於最大摺疊行數
if (mContentTv.getLineCount() <= mMaxUnfoldLines) {
return;
}
mTextHeightWithMaxLines = getRealTextViewHeight(mContentTv);
if (isFold) {
mContentTv.setMaxLines(mMaxUnfoldLines);
}
mStateTv.setVisibility(View.VISIBLE);
//重新測量
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (isFold) {
mContentTv.post(mRunnable);
mUnfoldHeight = getMeasuredHeight();
}
}
3.自定義屬性
<declare-styleable name="FoldTextView">
<attr name="maxUnfoldLines" format="integer"/>
<attr name="animDuration" format="integer"/>
<attr name="contentTextSize" format="dimension"/>
<attr name="contentTextColor" format="color"/>
<attr name="contentLineSpaceMultiplier" format="float"/>
<attr name="unFoldDrawable" format="reference"/>
<attr name="unFoldText" format="string"/>
<attr name="foldDrawable" format="reference"/>
<attr name="foldText" format="string"/>
<attr name="stateTextColor" format="color"/>
<attr name="stateTvGravity">
<enum name="left" value="0"/>
<enum name="center" value="1"/>
<enum name="right" value="2"/>
</attr>
</declare-styleable>
4.設置展開收起的動畫
public class FoldAnimation extends Animation {
private final View mTargetView;
private final int mStartHeight;
private final int mEndHeight;
private TextView mContentTv;
private int mMarginBetweenTxtAndBottom;
public FoldAnimation(View view, int startHeight, int endHeight, TextView contentTv, int animationDuration, int marginBetweenTxtAndBottom) {
mTargetView = view;
mStartHeight = startHeight;
mEndHeight = endHeight;
mContentTv = contentTv;
mMarginBetweenTxtAndBottom = marginBetweenTxtAndBottom;
setDuration(animationDuration);
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
final int newHeight = (int) ((mEndHeight - mStartHeight) * interpolatedTime + mStartHeight);
mContentTv.setMaxHeight(newHeight - mMarginBetweenTxtAndBottom);
mTargetView.getLayoutParams().height = newHeight;
mTargetView.requestLayout();
}
@Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
}
@Override
public boolean willChangeBounds() {
return true;
}
}
四、總結
以上就是這個工程裏的比較核心的代碼,其他的一些基礎代碼可以在github源碼裏進行查看。
最後灰常感謝看到這裏的小夥伴,相信看到這裏的小夥伴應該對這個項目還是比較感興趣的,如果這個項目中有一些思路或者代碼幫助到了小夥伴,還請給個小小的star作爲鼓勵~