文本伸缩的实现


效果如上,首先是上面的安全信息部分DetailSafeHolder

public class DetailSafeHolder extends BaseHolder<DetailBean> {

    @Bind(R.id.app_detail_safe_iv_arrow)
    ImageView mAppDetailSafeIvArrow;
    @Bind(R.id.app_detail_safe_pic_container)
    LinearLayout mAppDetailSafePicContainer;
    @Bind(R.id.app_detail_safe_des_container)
    LinearLayout mAppDetailSafeDesContainer;
    private View mSafeView;

    private boolean isOpen = false;
    private int mStart;
    private int mEnd;

    @Override
    public void setContent(DetailBean detailBean) {
	//添加几个绿色安全图片
	addPicView(detailBean);
	//添加安全描述信息
	addSafeDes(detailBean);
    }

    @Override
    public View getViewInflate() {
	mSafeView = View.inflate(UiUtil.getContext(), R.layout.item_app_detail_safe, null);
	ButterKnife.bind(this, mSafeView);
	//设置箭头的点击监听事件
	//初始不需要执行伸缩动画
	toggle(false);
	mAppDetailSafeIvArrow.setOnClickListener(new View.OnClickListener() {
	    @Override
	    public void onClick(View v) {
		toggle(true);
	    }
	});
	return mSafeView;
    }

    private void toggle(boolean isAnimator) {
	//首先需要测量安全信息的宽高
	mAppDetailSafeDesContainer.measure(View.MeasureSpec.makeMeasureSpec(
		mAppDetailSafePicContainer.getMeasuredWidth(),
		View.MeasureSpec.EXACTLY), 0);
	//动态定义高度
	int height = mAppDetailSafeDesContainer.getMeasuredHeight();
	if (isAnimator) {
	    //需要执行伸缩动画
	    if (isOpen) {
		//收缩
		mStart = height;
		mEnd = 0;
		//箭头向下动画
		ObjectAnimator animator = ObjectAnimator.ofFloat(mAppDetailSafeIvArrow,"rotation",-180,0);
		animator.setDuration(500);
		animator.start();
	    } else {
		//伸展
		mStart = 0;
		mEnd = height;
		//箭头向上动画
		ObjectAnimator animator = ObjectAnimator.ofFloat(mAppDetailSafeIvArrow,"rotation",0,180);
		animator.setDuration(500);
		animator.start();
	    }
	    //开始动画
	    startAnimation(mStart,mEnd);
	    isOpen = !isOpen;
	} else {
	    //无需伸缩动画
	    ViewGroup.LayoutParams params = mAppDetailSafeDesContainer.getLayoutParams();
	    if (isOpen) {
		//收缩
		params.height = 0;
	    } else {
		//伸展
		params.height = height;
	    }
	    mAppDetailSafeDesContainer.setLayoutParams(params);
	}
    }

    private void startAnimation(int start,int end) {
	ValueAnimator animator = ValueAnimator.ofObject(new FloatEvaluator(),start,end);
	animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
	    @Override
	    public void onAnimationUpdate(ValueAnimator animation) {
		float animatedValue = (float) animation.getAnimatedValue();
		ViewGroup.LayoutParams params = mAppDetailSafeDesContainer.getLayoutParams();
		params.height = (int) animatedValue;
		mAppDetailSafeDesContainer.setLayoutParams(params);
		mAppDetailSafeDesContainer.invalidate();
	    }
	});
	animator.setDuration(500);
	animator.start();
    }

    private void addSafeDes(DetailBean detailBean) {
	for (DetailBean.SafeBean safeBean : detailBean.safe) {
	    LinearLayout desLayout = new LinearLayout(UiUtil.getContext());
	    desLayout.setGravity(Gravity.CENTER);
	    //添加安全描述信息里的图片部分
	    ImageView iv = new ImageView(UiUtil.getContext());
	    String url = Constant.SERVER_IMAGEURL + safeBean.safeDesUrl;
	    Picasso.with(UiUtil.getContext()).load(url).into(iv);
	    desLayout.addView(iv);

	    //添加文字描述信息部分
	    TextView tv = new TextView(UiUtil.getContext());
	    tv.setText(safeBean.safeDes);
	    desLayout.addView(tv);

	    LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
									    ViewGroup.LayoutParams.WRAP_CONTENT);
	    param.leftMargin = 4;
	    //添加到安全信息容器里
	    mAppDetailSafeDesContainer.addView(desLayout,param);
	}
    }

    private void addPicView(DetailBean detailBean) {
	for (DetailBean.SafeBean safeBean : detailBean.safe) {
	    LinearLayout picLayout = new LinearLayout(UiUtil.getContext());
	    picLayout.setGravity(Gravity.CENTER);
	    ImageView picView = new ImageView(UiUtil.getContext());
	    String url = Constant.SERVER_IMAGEURL + safeBean.safeUrl;
	    Picasso.with(UiUtil.getContext()).load(url).into(picView);
	    picLayout.addView(picView);

	    LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
									    ViewGroup.LayoutParams.WRAP_CONTENT);
	    param.leftMargin = 4;
	    mAppDetailSafePicContainer.addView(picLayout, param);
	}
    }
}

DetailSafeHolder需要填充的布局文件 item_app_detail_safe.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">

    <!-- 上面部分 -->

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <ImageView
            android:id="@+id/app_detail_safe_iv_arrow"
            android:layout_width="15dp"
            android:layout_height="15dp"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:layout_marginRight="15dp"
            android:src="@drawable/arrow_down"/>

        <!-- 图片容器 -->

        <LinearLayout
            android:id="@+id/app_detail_safe_pic_container"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/app_detail_des_iv_arrow"
            android:orientation="horizontal"
            android:paddingBottom="5dp"
            android:paddingLeft="10dp"
            android:paddingTop="5dp">
        </LinearLayout>
    </RelativeLayout>

    <!-- 下面部分 -->

    <LinearLayout
        android:id="@+id/app_detail_safe_des_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
    </LinearLayout>

</LinearLayout>

下面的描述部分DetailDesHolder部分

public class DetailDesHolder extends BaseHolder<DetailBean> {

    @Bind(R.id.app_detail_des_tv_des)
    TextView mAppDetailDesTvDes;
    @Bind(R.id.app_detail_des_tv_author)
    TextView mAppDetailDesTvAuthor;
    @Bind(R.id.app_detail_des_iv_arrow)
    ImageView mAppDetailDesIvArrow;
    private View mDesView;
    private int mWidth;
    private boolean isOpen = false;
    private int mStart;
    private int mEnd;

    @Override
    public void setContent(DetailBean detailBean) {
	System.out.println("des==" + detailBean.des);
	mAppDetailDesTvDes.setText(detailBean.des);
	mAppDetailDesTvAuthor.setText("作者:" + detailBean.author);
	System.out.println("author==" + detailBean.author);
    }

    @Override
    public View getViewInflate() {
	mDesView = View.inflate(UiUtil.getContext(), R.layout.item_app_detail_des, null);
	ButterKnife.bind(this, mDesView);
	toggle(false);
	mAppDetailDesTvDes.getViewTreeObserver()
			  .addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
			      @Override
			      public void onGlobalLayout() {
				  mWidth = mAppDetailDesTvDes.getMeasuredWidth();
				  mAppDetailDesTvDes.getViewTreeObserver()
						    .removeOnGlobalLayoutListener(this);
			      }
			  });
	mAppDetailDesIvArrow.setOnClickListener(new View.OnClickListener() {
	    @Override
	    public void onClick(View v) {
		toggle(true);
	    }
	});
	return mDesView;
    }

    private void toggle(boolean isAnimator) {
	//首先需要测量描述信息的宽高
	mAppDetailDesTvDes.measure(View.MeasureSpec.makeMeasureSpec(mWidth,
								    View.MeasureSpec.EXACTLY), 0);
	//动态定义高度
	int height = mAppDetailDesTvDes.getMeasuredHeight();
	if (isAnimator) {
	    //需要执行伸缩动画
	    if (isOpen) {
		//收缩
		mStart = height;
		mEnd = get7Height();
		//箭头向下动画
		ObjectAnimator animator = ObjectAnimator.ofFloat(mAppDetailDesIvArrow,
								 "rotation",
								 -180,
								 0);
		animator.setDuration(500);
		animator.start();
	    } else {
		//伸展
		mStart = get7Height();
		mEnd = height;
		//箭头向上动画
		ObjectAnimator animator = ObjectAnimator.ofFloat(mAppDetailDesIvArrow,
								 "rotation",
								 0,
								 180);
		animator.setDuration(500);
		animator.start();
	    }
	    //开始动画
	    startAnimation(mStart, mEnd);
	    isOpen = !isOpen;
	} else {
	    //无需伸缩动画
	    ViewGroup.LayoutParams params = mAppDetailDesTvDes.getLayoutParams();
	    if (isOpen) {
		//收缩
		params.height = 0;
	    } else {
		//伸展
		params.height = height;
	    }
	    mAppDetailDesTvDes.setLayoutParams(params);
	}
    }

    private int get7Height() {
	TextView textView = new TextView(UiUtil.getContext());
	textView.setText(mAppDetailDesTvDes.getText());
	textView.setLines(7);
	textView.measure(View.MeasureSpec.makeMeasureSpec(mWidth, View.MeasureSpec.EXACTLY),0);
	return textView.getMeasuredHeight();
    }

    private void startAnimation(int start, int end) {
	ValueAnimator animator = ValueAnimator.ofObject(new FloatEvaluator(), start, end);
	animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
	    @Override
	    public void onAnimationUpdate(ValueAnimator animation) {
		float animatedValue = (float) animation.getAnimatedValue();
		ViewGroup.LayoutParams params = mAppDetailDesTvDes.getLayoutParams();
		params.height = (int) animatedValue;
		mAppDetailDesTvDes.setLayoutParams(params);
		mAppDetailDesTvDes.invalidate();
	    }
	});

	animator.addListener(new Animator.AnimatorListener() {
	    @Override
	    public void onAnimationStart(Animator animation) {

	    }

	    @Override
	    public void onAnimationEnd(Animator animation) {
		//动画结束时,让ScrollView滚到最下面
		//获取ScrollView
		ViewParent parent = mAppDetailDesTvDes.getParent();
		while (parent != null) {
		    parent = parent.getParent();
		    if (parent != null && parent instanceof ScrollView) {
			//找到了
			ScrollView scrollView = (ScrollView) parent;
			scrollView.fullScroll(View.FOCUS_DOWN);
		    }
		}
	    }

	    @Override
	    public void onAnimationCancel(Animator animation) {

	    }

	    @Override
	    public void onAnimationRepeat(Animator animation) {

	    }
	});
	animator.setDuration(500);
	animator.start();
    }
}

填充 DetailDesHolder的布局文件 item_app_detail_des.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:padding="4dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/white"
        android:orientation="vertical"
        android:padding="5dp">

        <!-- 简介 -->

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:singleLine="true"
            android:text="简介"
            android:textColor="@android:color/black"
            android:textSize="16sp"/>

        <!-- 描述详情区域 -->

        <TextView
            android:id="@+id/app_detail_des_tv_des"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="5dp"
            android:text="内容"
            android:textColor="@android:color/darker_gray"
            android:textSize="14sp"/>

        <!-- 作者区域 -->

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="25dp">

            <TextView
                android:id="@+id/app_detail_des_tv_author"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:text="作者 : "
                android:textColor="@android:color/darker_gray"
                android:textSize="14sp"/>

            <ImageView
                android:id="@+id/app_detail_des_iv_arrow"
                android:layout_width="15dp"
                android:layout_height="15dp"
                android:layout_alignParentRight="true"
                android:layout_centerVertical="true"
                android:src="@drawable/arrow_down"/>
        </RelativeLayout>
    </LinearLayout>

</FrameLayout>

上面的只是文本伸缩部分的代码片段,仅供参考






  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值