先看下效果图:
实现步骤如下:
1.布局文件(条目的标题 和 条目标题对应的内容)
<?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:background="#FFFFFF"
android:orientation="vertical" >
<TextView
android:id="@+id/tv_item_one_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFFFFF"
android:padding="10dip"
android:text="条目一的标题"
android:textSize="16sp" />
<TextView
android:id="@+id/tv_item_one_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFFFFF"
android:paddingLeft="30dip"
android:text="条目一的内容\r\n条目一的内容\r\n条目一的内容\r\n"
android:visibility="gone" />
<TextView
android:id="@+id/tv_item_two_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFFFFF"
android:padding="10dip"
android:text="条目二的标题"
android:textSize="16sp" />
<TextView
android:id="@+id/tv_item_two_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFFFFF"
android:paddingLeft="30dip"
android:text="条目二的内容\r\n条目二的内容\r\n条目二的内容\r\n"
android:visibility="gone" />
<TextView
android:id="@+id/tv_item_three_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFFFFF"
android:padding="10dip"
android:text="条目三的标题"
android:textSize="16sp" />
<TextView
android:id="@+id/tv_item_three_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFFFFF"
android:paddingLeft="30dip"
android:text="条目三的内容\r\n条目三的内容\r\n条目三的内容\r\n"
android:visibility="gone" />
<TextView
android:id="@+id/tv_item_four_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFFFFF"
android:padding="10dip"
android:text="条目四的标题"
android:textSize="16sp" />
<TextView
android:id="@+id/tv_item_four_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFFFFF"
android:paddingLeft="30dip"
android:text="条目四的内容\r\n条目四的内容\r\n条目四的内容\r\n"
android:visibility="gone" />
<TextView
android:id="@+id/tv_item_five_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFFFFF"
android:padding="10dip"
android:text="条目五的标题"
android:textSize="16sp" />
<TextView
android:id="@+id/tv_item_five_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFFFFF"
android:paddingLeft="30dip"
android:text="条目五的内容\r\n条目五的内容\r\n条目五的内容\r\n"
android:visibility="gone" />
</LinearLayout>
实现此动画的前提:
将所有的title和对应的content封装ViewBean中,然后将所有ViewBean放到List中
ViewBean的代码如下:
public class ViewBean {
private View viewTitle;
private View viewLayout;
public View getViewTitle() {
return viewTitle;
}
public void setViewTitle(View viewTitle) {
this.viewTitle = viewTitle;
}
public View getViewLayout() {
return viewLayout;
}
public void setViewLayout(View viewLayout) {
this.viewLayout = viewLayout;
}
}
同时还需要依赖一个类ExpandAnimation (这是牛人们写好的一个类 直接复制去就行了)
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Transformation;
import android.widget.LinearLayout.LayoutParams;
public class ExpandAnimation extends Animation {
private View mAnimatedView;
private LayoutParams mViewLayoutParams;
private int mMarginStart, mMarginEnd;
private boolean mIsVisibleAfter = false;
private boolean mWasEndedAlready = false;
/**
* Initialize the animation
* @param view The layout we want to animate
* @param duration The duration of the animation, in ms
*/
public ExpandAnimation(View view, int duration) {
setDuration(duration);
mAnimatedView = view;
mViewLayoutParams = (LayoutParams) view.getLayoutParams();
// decide to show or hide the view
mIsVisibleAfter = (view.getVisibility() == View.VISIBLE);
mMarginStart = mViewLayoutParams.bottomMargin;
mMarginEnd = (mMarginStart == 0 ? (0- view.getHeight()) : 0);
view.setVisibility(View.VISIBLE);
}
/**
* show current animation status
* @return
*/
public boolean toggle() {
return !mIsVisibleAfter;
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
super.applyTransformation(interpolatedTime, t);
if (interpolatedTime < 1.0f) {
// Calculating the new bottom margin, and setting it
mViewLayoutParams.bottomMargin = mMarginStart
+ (int) ((mMarginEnd - mMarginStart) * interpolatedTime);
// Invalidating the layout, making us seeing the changes we made
mAnimatedView.requestLayout();
// Making sure we didn't run the ending before (it happens!)
} else if (!mWasEndedAlready) {
mViewLayoutParams.bottomMargin = mMarginEnd;
mAnimatedView.requestLayout();
if (mIsVisibleAfter) {
mAnimatedView.setVisibility(View.GONE);
}
mWasEndedAlready = true;
}
}
}
2.主程序代码如下:
public class MainActivity extends Activity {
private TextView tv_title_one, tv_title_two, tv_title_three, tv_title_four, tv_title_five;
private TextView tv_content_one, tv_content_two, tv_content_three, tv_content_four, tv_content_five;
private List<ViewBean> viewList;
private boolean animState = true;
private View lastView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
findViews();
initViews();
}
private void findViews() {
tv_title_one = (TextView) this.findViewById(R.id.tv_item_one_title);
tv_title_two = (TextView) this.findViewById(R.id.tv_item_two_title);
tv_title_three = (TextView) this.findViewById(R.id.tv_item_three_title);
tv_title_four = (TextView) this.findViewById(R.id.tv_item_four_title);
tv_title_five = (TextView) this.findViewById(R.id.tv_item_five_title);
tv_content_one = (TextView) this.findViewById(R.id.tv_item_one_content);
tv_content_two = (TextView) this.findViewById(R.id.tv_item_two_content);
tv_content_three = (TextView) this.findViewById(R.id.tv_item_three_content);
tv_content_four = (TextView) this.findViewById(R.id.tv_item_four_content);
tv_content_five = (TextView) this.findViewById(R.id.tv_item_five_content);
}
private void initViews() {
viewList = new ArrayList<ViewBean>();
//1.将所有的viewTitle和viewLayout封装成ViewBean,并且用list保存
ViewBean bean;
bean = new ViewBean();
bean.setViewTitle(tv_title_one);
bean.setViewLayout(tv_content_one);
viewList.add(bean);
bean = new ViewBean();
bean.setViewTitle(tv_title_two);
bean.setViewLayout(tv_content_two);
viewList.add(bean);
bean = new ViewBean();
bean.setViewTitle(tv_title_three);
bean.setViewLayout(tv_content_three);
viewList.add(bean);
bean = new ViewBean();
bean.setViewTitle(tv_title_four);
bean.setViewLayout(tv_content_four);
viewList.add(bean);
bean = new ViewBean();
bean.setViewTitle(tv_title_five);
bean.setViewLayout(tv_content_five);
viewList.add(bean);
setAnimation(viewList);
}
private void setAnimation(List<ViewBean> viewList) {
for (ViewBean bean : viewList) {
final View viewTitle = bean.getViewTitle();
final View viewLayout = bean.getViewLayout();
viewTitle.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//给title对应的layout执行动画的操作
executeAnimation(viewTitle,viewLayout);
}
});
}
}
private void executeAnimation(View viewTitle, View viewLayout) {
/**
* 执行动画的view如果是隐藏状态,自动展开,展开后将其设置为可见状态
* 执行动画的view如果是可见状态,自动隐藏,隐藏后将其设置为不可见状态。
*/
if (animState) { //表示当前可以执行动画
ExpandAnimation anim = new ExpandAnimation(viewLayout, 300);
boolean toggle = anim.toggle();
if (toggle) {//表示当前动画已经展开
/**
* 如果lastView == null
* 说明之前没有执行过动画
* 如果lastView != null
* 说明执行过动画,再执行动画的时候需要将lastview给收回,收回之后再执行当前的动画
*/
if (lastView == null) {
lastView = viewLayout;
} else {
if (lastView == viewLayout) {
lastView = null;
} else {
executeAnimation(viewTitle, lastView);
lastView = viewLayout;
}
}
} else {//当前动画已经关闭
/**
* 打开第二个动画的时候,需要将上一个viewLayout(lastView)对应的title恢复为正常的状态
*/
for (ViewBean bean : viewList) {
if (lastView == bean.getViewLayout()) {//找到lastView对应的那个viewbean
lastView = null;
}
}
}
viewLayout.startAnimation(anim);
anim.setAnimationListener(animationListener);
} else {
System.out.println("can't play animation");
}
}
Animation.AnimationListener animationListener = new AnimationListener() {
@Override
public void onAnimationEnd(Animation animation) {
animState = true;
}
@Override
public void onAnimationStart(Animation animation) {
animState = false;
}
@Override
public void onAnimationRepeat(Animation animation) {
}
};
}
至此,就可以实现这种比较舒服的过度效果了~(gif图有点卡顿,手机上很流畅)