android从一点展开动画,TextView的折叠展开(动画效果)

有时候我们会遇到这样的情况,为了让布局显得更为精简,会对大段的文本(一般用于人物介绍等地方)进行折叠,用户点击展开。通常都带有一个小图标,随着折叠展开来进行翻转。这种效果是怎么展现的呢,老规矩,先上效果图。用的是genymotion模拟器,确实快了很多,只是电脑太渣,占用很多内存。

折叠情况,箭头向下:

0395d8b6d8f841e2bfb1eac6d9b83922.png

展开情况,箭头向上:

847e014e616c6c809f5998e934bcc3b0.png

在这里实现也很简单。直接贴出代码,代码有注释,一看就明白。

activity_main.XML布局文件:

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:paddingLeft="@dimen/activity_horizontal_margin"

android:paddingRight="@dimen/activity_horizontal_margin"

android:paddingTop="@dimen/activity_vertical_margin"

tools:context=".MainActivity">

android:id="@+id/tv_1"

android:text="@string/hello_world"

android:layout_centerHorizontal="true"

android:textSize="30sp"

android:layout_width="match_parent"

android:layout_height="wrap_content" />

android:id="@+id/adjust_text"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_below="@+id/tv_1"

/>

android:id="@+id/turn_over_icon"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:layout_centerInParent="true"

android:layout_below="@id/adjust_text"

android:src="@mipmap/text_ic_expand"

android:visibility="gone"

/>

主要为了展示功能,布局方面简单为主,用了两个textview(helloword和长文本),imageview(箭头)

MainActivity文件:

package com.expandtextview;

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import android.view.Menu;

import android.view.MenuItem;

import android.view.View;

import android.view.animation.Animation;

import android.view.animation.RotateAnimation;

import android.view.animation.Transformation;

import android.widget.ImageView;

import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

private TextView mTextView; //文本域

private ImageView mImageView; //翻转icon

int maxLine=5; //TextView设置默认最大展示行数为5

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mTextView= (TextView) findViewById(R.id.adjust_text);

mImageView= (ImageView) findViewById(R.id.turn_over_icon);

mTextView.setText(getText(R.string.content));//设置文本内容

mTextView.setHeight(mTextView.getLineHeight() * maxLine); //设置默认显示高度

//根据高度来控制是否展示翻转icon

mTextView.post(new Runnable() {

@Override

public void run() {

mImageView.setVisibility(mTextView.getLineCount() > maxLine ? View.VISIBLE : View.GONE);

}

});

mImageView.setOnClickListener(new MyTurnListener()); //翻转监听

}

@Override

public boolean onCreateOptionsMenu(Menu menu) {

// Inflate the menu; this adds items to the action bar if it is present.

getMenuInflater().inflate(R.menu.menu_main, menu);

return true;

}

@Override

public boolean onOptionsItemSelected(MenuItem item) {

// Handle action bar item clicks here. The action bar will

// automatically handle clicks on the Home/Up button, so long

// as you specify a parent activity in AndroidManifest.xml.

int id = item.getItemId();

//noinspection SimplifiableIfStatement

if (id == R.id.action_settings) {

return true;

}

return super.onOptionsItemSelected(item);

}

private class MyTurnListener implements View.OnClickListener {

boolean isExpand; //是否翻转

@Override

public void onClick(View v) {

isExpand=!isExpand;

mTextView.clearAnimation(); //清除动画

final int tempHight;

final int startHight=mTextView.getHeight(); //起始高度

int durationMillis = 200;

if(isExpand){

/**

* 折叠效果,从长文折叠成短文

*/

tempHight = mTextView.getLineHeight() * mTextView.getLineCount() - startHight; //为正值,长文减去短文的高度差

//翻转icon的180度旋转动画

RotateAnimation animation = new RotateAnimation(0, 180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);

animation.setDuration(durationMillis);

animation.setFillAfter(true);

mImageView.startAnimation(animation);

}else {

/**

* 展开效果,从短文展开成长文

*/

tempHight = mTextView.getLineHeight() * maxLine - startHight;//为负值,即短文减去长文的高度差

//翻转icon的180度旋转动画

RotateAnimation animation = new RotateAnimation(180, 0, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);

animation.setDuration(durationMillis);

animation.setFillAfter(true);

mImageView.startAnimation(animation);

}

Animation animation = new Animation() {

//interpolatedTime 为当前动画帧对应的相对时间,值总在0-1之间

protected void applyTransformation(float interpolatedTime, Transformation t) { //根据ImageView旋转动画的百分比来显示textview高度,达到动画效果

mTextView.setHeight((int) (startHight + tempHight * interpolatedTime));//原始长度+高度差*(从0到1的渐变)即表现为动画效果

}

};

animation.setDuration(durationMillis);

mTextView.startAnimation(animation);

}

}

}

这里在重要地方都做了注释讲解,非常直观。

其中mTextView的post方法这么做的原因在于,在OnCreate方法中定义设置的textView不会马上渲染并显示,所以textview的getLineCount()获取到的值一般都为零,因此使用post会在其绘制完成后来对mImageView进行显示控制。

参考stackoverflow 上的讲解how to use getlincount in textview