原有思路:
-
View.Post() 方式
說明:將處理添加到主線程隊(duì)列中,等待處理,會(huì)有顯示慢的問題,由于View的復(fù)用,當(dāng)列表滑動(dòng)后,就不能正確返回相關(guān)值了.
-
getViewTreeObserver().addOnGlobalLayoutListener()
說明:添加全局View 變化監(jiān)聽,會(huì)被多次調(diào)用,并且在列表滑動(dòng)過程中,跟View.Post() 有相同的問題.
新思路
- onDraw()
- onLayout()
- onMeasure() 中進(jìn)行獲取對(duì)應(yīng)TextView 的getLineCount()
View 的繪制過程為 onMeasure()->onLayout()->onDraw()
所以將處理邏輯放置到 onMeasure()中.
說明:
- 封裝 容器 CommendContainerView,繼承 RelativeLayout
- 重寫 onMeasure()方法,當(dāng) super.onMeasure(widthMeasureSpec, heightMeasureSpec); 執(zhí)行完后, 容器已經(jīng)知道了所有子View 的相關(guān)尺寸, 這個(gè)時(shí)候 可以去進(jìn)行判斷了.并且不會(huì)有延時(shí)問題.
- 進(jìn)行邏輯判斷后,調(diào)用 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 對(duì)子View 再進(jìn)行一次測(cè)量.保證顯示邏輯.
- 針對(duì)于 用戶操作過的 View, 將狀態(tài)進(jìn)行緩存.
下面直接上代碼:
public class CommendContainerView extends RelativeLayout {
private TextView mCommendTextView;
private TextView mCommendFun;
private CommendShowFunListener mListener;
private boolean mFlag = true;
private int mLinesLimit = 1;
private Boolean mShowAll;
private int mPos;
public CommendContainerView(Context context) {
this(context, null);
}
public CommendContainerView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public CommendContainerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(context, attrs, defStyleAttr);
}
//初始化布局~
private void initView(Context context, AttributeSet attrs, int defStyleAttr) {
inflate(context, R.layout.view_commend_container, this);
mCommendTextView = findViewById(R.id.commend_ctv_commend);
mCommendFun = findViewById(R.id.commend_tv_fun);
mCommendFun.setOnClickListener(onClickListener);
}
public void setCommendInfo(CharSequence text, Boolean showAll, int pos) {
mShowAll = showAll;
mPos = pos;
if (null != mShowAll) {
mFlag = true;
mCommendFun.setVisibility(VISIBLE);
if (mShowAll) {
mCommendFun.setText(R.string.desc_shrinkup);
mCommendTextView.setMaxLines(Integer.MAX_VALUE);
} else {
mCommendFun.setText(R.string.desc_spread);
mCommendTextView.setMaxLines(mLinesLimit);
}
mCommendTextView.setText(text);
} else {
mFlag = false;
mCommendFun.setVisibility(GONE);
mCommendTextView.setMaxLines(Integer.MAX_VALUE);
mCommendTextView.setText(text);
}
}
private OnClickListener onClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
mCommendFun.setVisibility(VISIBLE);
mFlag = true;
if (null == mShowAll || !mShowAll) {
mCommendTextView.setMaxLines(Integer.MAX_VALUE);
mCommendFun.setText(R.string.desc_shrinkup);
mShowAll = true;
} else {
mCommendTextView.setMaxLines(mLinesLimit);
mCommendFun.setText(R.string.desc_spread);
mShowAll = false;
}
if (null != mListener) {
mListener.onShowStatusChange(mPos, mShowAll);
}
}
};
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (!mFlag) {
mFlag = true;
if (mCommendTextView.getLineCount() > mLinesLimit) {
//超過行數(shù)~
mCommendFun.setVisibility(VISIBLE);
mCommendFun.setText(R.string.desc_spread);
mCommendTextView.setMaxLines(mLinesLimit);
} else {
mCommendFun.setVisibility(GONE);
mCommendTextView.setMaxLines(Integer.MAX_VALUE);
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
public void setCommendShowFunListener(CommendShowFunListener listener) {
this.mListener = listener;
}
public void setLinesLimit(int limit) {
this.mLinesLimit = limit;
}
interface CommendShowFunListener {
void onShowStatusChange(int pos, boolean showAll);
}
}