本篇主讲ExpandableTextView库,这个开源项目主要用于Item显示文字内容过多,采用点击图标展开收缩的方式来显示。
效果图
个人实现思路
投根据伸缩状态,方向箭控制src变化或者动画旋转
投根据伸缩状态,文字内容改变maxLength或者动态改变控件高度
以上仅为个人猜想,博主还是的看过源码才能清楚具体实现.在看过源码后决定在本篇博客补充一个知识点(了解的自动忽略)
onFinishInflate
1.Activity onCreate(Bundle savedInstanceState)和onFinishInflate(),onCreate是activity的创建回调,一般我们会把setContentView(R.layout.activity_main)放在oncreate方法里面,这个方法主要是将xml布局文件里的控件映射到activity里面。 而View首先会执行构造方法,然后会回调onFinishInflate()方法来完成初始化。所以 onFinishInflate() 回调方法是从XML加载该组件并用它构建界面之后调用的方法。
ExpandableTextView从它构造函数仅发现了解析自定义属性的基本操作,而后在onFinishInflate函数发现有findviewbyid的操作,用于初始化LinearLayout的字控件,并绑定控件点击事件。
onClick方法主要做了三件事:状态存储drawable变化、动画
@Override
public void onClick(View view) {
if (mButton.getVisibility() != View.VISIBLE) {
return;
}
mCollapsed = !mCollapsed;
mButton.setImageDrawable(mCollapsed ? mExpandDrawable : mCollapseDrawable);
if (mCollapsedStatus != null) {
mCollapsedStatus.put(mPosition, mCollapsed);
}
// mark that the animation is in progress
mAnimating = true;
Animation animation;
if (mCollapsed) {
animation = new ExpandCollapseAnimation(this, getHeight(), mCollapsedHeight);
} else {
animation = new ExpandCollapseAnimation(this, getHeight(), getHeight() +
mTextHeightWithMaxLines - mTv.getHeight());
}
animation.setFillAfter(true);
animation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
applyAlphaAnimation(mTv, mAnimAlphaStart);
}
@Override
public void onAnimationEnd(Animation animation) {
// clear animation here to avoid repeated applyTransformation() calls
clearAnimation();
// clear the animation flag
mAnimating = false;
// notify the listener
if (mListener != null) {
mListener.onExpandStateChanged(mTv, !mCollapsed);
}
}
@Override
public void onAnimationRepeat(Animation animation) { }
});
clearAnimation();
startAnimation(animation);
}
动画结束了通过OnExpandStateChangeListener回调出来供我们自己处理,而applyAlphaAnimation方法仅是一个兼容api不同版本的透明动画
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private static void applyAlphaAnimation(View view, float alpha) {
if (isPostHoneycomb()) {
view.setAlpha(alpha);
} else {
AlphaAnimation alphaAnimation = new AlphaAnimation(alpha, alpha);
// make it instant
alphaAnimation.setDuration(0);
alphaAnimation.setFillAfter(true);
view.startAnimation(alphaAnimation);
}
}
ExpandCollapseAnimation内部类真正动画的具体实现代码,通过动态改变weight、height属性重绘实现。
class ExpandCollapseAnimation extends Animation {
//..................................略.............................................
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
final int newHeight = (int)((mEndHeight - mStartHeight) * interpolatedTime + mStartHeight);
mTv.setMaxHeight(newHeight - mMarginBetweenTxtAndBottom);
if (Float.compare(mAnimAlphaStart, 1.0f) != 0) {
applyAlphaAnimation(mTv, mAnimAlphaStart + interpolatedTime * (1.0f - mAnimAlphaStart));
}
mTargetView.getLayoutParams().height = newHeight;
mTargetView.requestLayout();
}
@Override
public boolean willChangeBounds( ) {
return true;
}
}
关于透明动画,如果你运行官方demo可能你肉眼无法看出来,默认duration是在太短,可以通过自定义属性ExpandableTextView_animDuration自己体验一下。
/ The default animation duration /
private static final int DEFAULT_ANIM_DURATION = 300;
由于该开源项目是很久以前的,于是乎发现了一点可以优化拓展的知识点:Compat系列
这个开源项目里的getDrawable方法目前可以完全不用自己再造轮子了,Compat系列的ContextCompat已有这个方法。
诸如此类的方法Compat系列类还有很多需要自己去挖掘。
目前android兼容6.0的动态权限很多流行库也都有用到Compat系列类,如果你还有怀疑可以看看ContextCompat.checkSelfPermission()我就不一一列举,萝卜青菜各有所爱,我喜欢所以我推荐。
至于onMeasure函数的设置maxLength 、mCollapsedHeight计算有兴趣的可以看看比较简单。