自定义View-带过渡动画的折叠收缩布局
2020-07-27 本文已影响0人
i小灰
简介:
由于界面View.VISIBLE和View.GONE的动画太生硬,所以写了ExpandLayout类来平滑过渡。 基本思路,动态的设置布局的高度。
先上效果图:
- 核心动画效果代码
/**
* 切换动画实现
*/
private void animateToggle(long animationDuration) {
ValueAnimator heightAnimation = isExpand ?
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();
}
使用:
- 布局文件中 (引入自定义View)
<com.p.h.ExpandLayout
android:id="@+id/expandLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFFF00"
android:clickable="true">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="15dp"
android:text="大辉儿: 这里是可收缩布局内部" />
</com.p.h.ExpandLayout>
- java代码中 初始状态是否显示,toggleExpand切换折叠/展开状态
private ExpandLayout mExpandLayout;
public void initExpandView() {
mExpandLayout = (ExpandLayout) findViewById(R.id.expandLayout);
mExpandLayout.initExpand(false);//设定初始化折叠,默认展开
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mExpandLayout.toggleExpand();
}
});
}
下面是全部代码:
- 布局文件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingTop="50dp">
<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="#32CD32"
android:text="点击展开/收缩" />
<com.p.h.ExpandLayout
android:id="@+id/expandLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFFF00"
android:clickable="true">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="15dp"
android:text="大辉儿: 这里是可收缩布局内部" />
</com.p.h.ExpandLayout>
</LinearLayout>
- 自定义View 伸缩布局类:
package com.p.h;
import android.animation.ValueAnimator;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
/**
* Created by : Pan_Hui on
* Time: 2020/07/27 13:14
* 带过渡动画的折叠收缩布局
*/
public class ExpandLayout extends RelativeLayout {
public ExpandLayout(Context context) {
this(context, null);
}
public ExpandLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ExpandLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initView();
}
private View layoutView;
private int viewHeight;
private boolean isExpand;
private long animationDuration;
private boolean lock;
private void initView() {
layoutView = this;
isExpand = true;
animationDuration = 300;
setViewDimensions();
}
/**
* @param isExpand 初始状态是否折叠
*/
public void initExpand(boolean isExpand) {
this.isExpand = isExpand;
setViewDimensions();
}
/**
* 设置动画时间
*
* @param animationDuration 动画时间
*/
public void setAnimationDuration(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();
}
setViewHeight(layoutView, isExpand ? viewHeight : 0);
}
});
}
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 = isExpand ?
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) {
int value = (int) (float) animation.getAnimatedValue();
setViewHeight(layoutView, value);
if (value == viewHeight || value == 0) {
lock = false;
}
}
});
heightAnimation.start();
lock = true;
}
public boolean isExpand() {
return isExpand;
}
/**
* 折叠view
*/
public void collapse() {
isExpand = false;
animateToggle(animationDuration);
}
/**
* 展开view
*/
public void expand() {
isExpand = true;
animateToggle(animationDuration);
}
public void toggleExpand() {
if (lock) {
return;
}
if (isExpand) {
collapse();
} else {
expand();
}
}
}
- MainActivity中绑定使用自定义View
package com.p.h;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
private Button button;
private ExpandLayout mExpandLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button);
//初始化展开View
initExpandView();
}
public void initExpandView() {
mExpandLayout = (ExpandLayout) findViewById(R.id.expandLayout);
//初始状态是否折叠false 否 true 是
mExpandLayout.initExpand(false);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mExpandLayout.toggleExpand();
}
});
}
}
最近有点忙,没时间更新 抱歉~~~