效果图:
很多需要实现点击显示和隐藏指定布局的功能,但不带过渡动画的显示和隐藏会显得比较生硬,因此需要自定义一个带过渡动画的控件,代码如下:
1、自定义FoldViewLayout
public class FoldViewLayout extends RelativeLayout {
public FoldViewLayout(Context context) {
this(context, null);
}
public FoldViewLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public FoldViewLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initView();
}
private View layoutView;
private int viewHeight;
private boolean isFold;
private long animationDuration;
//初始化
public void initView() {
layoutView = this;
isFold = true;
animationDuration = 300;
setViewDimensions();
}
//初始状态是否折叠
public void initFold(boolean isFold) {
this.isFold = isFold;
if (!isFold) {
animateToggle(10);
}
}
//设置动画时间
public void setAnimationTime(long animationDuration) {
this.animationDuration = animationDuration;
}
/**
* 获取 subView 的总高度
* View.post() 的 runnable 对象中的方法会在 View 的 measure、layout 等事件后触发
*/
private void setViewDimensions() {
layoutView.post(new Runnable() {
@Override
public void run() {
if (viewHeight <= 0) {
viewHeight = layoutView.getMeasuredHeight();
}
}
});
}
public static void setViewHeight(View view, int height) {
final ViewGroup.LayoutParams params = view.getLayoutParams();
params.height = height;
view.requestLayout();
}
//实现切换动画
private void animateToggle(long animationDuration) {
ValueAnimator heightAnimation = isFold ?
ValueAnimator.ofFloat(0f, viewHeight) : ValueAnimator.ofFloat(viewHeight, 0f);
heightAnimation.setDuration(animationDuration / 2);
heightAnimation.setStartDelay(animationDuration / 2);
heightAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float val = (float) animation.getAnimatedValue();
setViewHeight(layoutView, (int) val);
}
});
heightAnimation.start();
}
//获取当前展开的状态
public boolean isFold() {
return isFold;
}
//折叠view
public void collapse() {
isFold = false;
animateToggle(animationDuration);
}
//展开view
public void expand() {
isFold = true;
animateToggle(animationDuration);
}
//自动判断是否展开收起View
public void toggleExpand() {
if (isFold) {
collapse();
} else {
expand();
}
}
}
2、 在.xml中
FoldViewLayout的子控件有且只能拥有一个布局
<com.example.templateactivity.FoldViewLayout
android:id="@+id/setting_about_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white">
<!--要隐藏的内容-->
<LinearLayout
android:id="@+id/main_linearLayout"
android:layout_width="match_parent"
android:layout_height="300dp"
android:background="@color/colorAccent"
android:orientation="vertical" />
</com.example.templateactivity.FoldViewLayout>
3、代码逻辑
public class MainActivity extends AppCompatActivity {
@BindView(R.id.main_img)
ImageView mainImg;
@BindView(R.id.main_linearLayout)
LinearLayout mainLinearLayout;
@BindView(R.id.setting_about_content)
FoldViewLayout settingAboutContent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
imgClick();
}
private void imgClick() {
mainImg.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (settingAboutContent.isFold()) {
settingAboutContent.setAnimationTime(700);// 设置动画时间
settingAboutContent.toggleExpand();
mainImg.setImageDrawable(ContextCompat.getDrawable(MainActivity.this, R.mipmap.top_arrow));
} else {
settingAboutContent.setAnimationTime(700);
settingAboutContent.toggleExpand();
mainImg.setImageDrawable(ContextCompat.getDrawable(MainActivity.this, R.mipmap.bottom_arrow));
}
}
});
}
}