本篇主讲ExpandableTextView库,这个开源项目主要用于Item显示文字内容过多,采用点击图标展开收缩的方式来显示。

效果图




idea Android 配置_控件



个人实现思路

投根据伸缩状态,方向箭控制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计算有兴趣的可以看看比较简单。