美文网首页
Android带折叠展开动画的TextView

Android带折叠展开动画的TextView

作者: reaiya | 来源:发表于2019-03-28 20:58 被阅读0次

    先上效果图:


    Video_20190327_023204_64.gif

    继承TextView的AutoFoldTextView

    public class AutoFoldTextView extends android.support.v7.widget.AppCompatTextView {
    
        private final static String TAG = "AutoFoldTextView";
    
        public interface OnFoldListener {
            void onFold(boolean isFolded);
        }
    
        // 折叠状态显示行数
        private int mDefaultLines = 3;
        // 状态(是否是折叠状态)
        private boolean mIsFolded = true;
        // 外部状态监听接口
        private OnFoldListener mOnFoldListener;
        // 折叠时的高度
        private int mFoldHeight;
        // 展开时的高度
        private int mUnFoldHeight;
        // 高度变化的属性动画
        private ObjectAnimator mHeightObjectAnimator;
        // 动画时间
        private int mFoldDuration = 300;
    
        public AutoFoldTextView(Context context) {
            this(context,null);
        }
    
        public AutoFoldTextView(Context context, AttributeSet attrs) {
            this(context, attrs,0);
        }
    
        public AutoFoldTextView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            if(mUnFoldHeight == 0) {
                mUnFoldHeight = getLayout().getLineTop(getLineCount()) + getCompoundPaddingTop() + getCompoundPaddingBottom();
                setMaxLines(mDefaultLines);
                super.onMeasure(widthMeasureSpec, heightMeasureSpec);
                mFoldHeight = getMeasuredHeight();
                Log.d(TAG, "onMeasure() called with: mUnFoldHeight = [" + mUnFoldHeight + "], " +
                        "mFoldHeight = [" + mFoldHeight + "]");
                if (mUnFoldHeight == mFoldHeight) {
                    mIsFolded = false;
                }else{
                    setMaxLines(Integer.MAX_VALUE);
                    setMaxHeight(mFoldHeight);
                }
            }
        }
    
        public void setOnFlodListener(OnFoldListener mOnFoldListener) {
            this.mOnFoldListener = mOnFoldListener;
        }
    
        public void setFoldView(View mFoldView) {
            Log.d(TAG, "setFlodView() called with: mFlodView = [" + mFoldView + "]");
            // 折叠/展开 按钮
            if(!mIsFolded){
                mFoldView.setVisibility(GONE);
            }else {
                mFoldView.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        fold(!mIsFolded);
                    }
                });
            }
        }
    
        /**
         * 折叠/展开
         * @param isFolded true为折叠,false为展开
         */
        private void fold(boolean isFolded) {
            mIsFolded = isFolded;
            if(mHeightObjectAnimator != null && mHeightObjectAnimator.isRunning()){
                mHeightObjectAnimator.cancel();
            }
            if(mIsFolded) {
                mHeightObjectAnimator = ObjectAnimator.ofInt(this, "MaxHeight",
                        mFoldHeight);
            }else{
                mHeightObjectAnimator = ObjectAnimator.ofInt(this, "MaxHeight",
                        mUnFoldHeight);
            }
            mHeightObjectAnimator.setDuration(mFoldDuration);
            mHeightObjectAnimator.addListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animation) {
    
                }
    
                @Override
                public void onAnimationEnd(Animator animation) {
                    notifyListener();
                }
    
                @Override
                public void onAnimationCancel(Animator animation) {
    
                }
    
                @Override
                public void onAnimationRepeat(Animator animation) {
    
                }
            });
            mHeightObjectAnimator.start();
        }
    
        private void notifyListener() {
            if(mOnFoldListener != null){
                mOnFoldListener.onFold(mIsFolded);
            }
        }
    
        public boolean getIsFolded() {
            return mIsFolded;
        }
    
        // for databinding
        public void setIsFolded(boolean mIsFolded) {
            if(mFoldHeight != 0 && mUnFoldHeight != 0) {
                fold(mIsFolded);
            }
        }
    
        public void setFoldDuration(int mFoldDuration) {
            this.mFoldDuration = mFoldDuration;
        }
    
        public void setDefaultLines(int mDefaultLines) {
            this.mDefaultLines = mDefaultLines;
            requestLayout();
        }
    
        @Override
        protected void onDetachedFromWindow() {
            super.onDetachedFromWindow();
            if(mHeightObjectAnimator != null && mHeightObjectAnimator.isRunning()){
                mHeightObjectAnimator.cancel();
                mHeightObjectAnimator.removeAllListeners();
                mHeightObjectAnimator = null;
            }
        }
    }
    

    原理:
    测量的时候测出折叠状态和展开状态的高度,然后用属性动画在之间切换

    写于2019-3-27

    相关文章

      网友评论

          本文标题:Android带折叠展开动画的TextView

          本文链接:https://www.haomeiwen.com/subject/agfhbqtx.html