我们先搞一下动画工具,如果你看我的文章,直接复制往代码里面,也可以试着理解代码的意思,不过不懂也可以照样用。有详尽的注释
缩放工具的功能,可以实现view,dialog,popup,tabLayout文字的缩放动画。
第一步新建接口文件 ScaleViewAnim.java
public interface ScaleViewAnim {
ScaleViewAnim setScaleForPushInAnim(float scaleX, float scaleY);
ScaleViewAnim setScaleForPopOutAnim(float scaleX, float scaleY);
ScaleViewAnim setPushInAnimDuration(int timeInMillis);
ScaleViewAnim setPopOutAnimDuration(int timeInMillis);
ScaleViewAnim setInterpolatorPushIn(AccelerateDecelerateInterpolator interpolatorPushIn);
ScaleViewAnim setInterpolatorPopOut(AccelerateDecelerateInterpolator interpolatorPopOut);
}
第二步继承。ScaleView.java, 注释很详细,如果不看过程,可以直接复制使用。
public class ScaleView implements ScaleViewAnim {
// 属性的初始化
public static final float PUSH_IN_SCALE_X = 0.9f;
public static final float PUSH_IN_SCALE_Y = 0.9f;
public static final float POP_OUT_SCALE_X = 1.1f;
public static final float POP_OUT_SCALE_Y = 1.1f;
public static final int PUSH_IN_ANIM_DURATION = 100;
public static final int POP_OUT_ANIM_DURATION = 100;
public static final AccelerateDecelerateInterpolator DEFAULT_INTERPOLATOR
= new AccelerateDecelerateInterpolator();
private WeakReference<View> view;
private WeakReference<Dialog> dialog;
private WeakReference<PopupWindow> popup;
private WeakReference<TabLayout> tabLayout;
private boolean isTouchInsideView = true;
private float pushInScaleX = PUSH_IN_SCALE_X;
private float pushInScaleY = PUSH_IN_SCALE_Y;
private float popOutScaleX = POP_OUT_SCALE_X;
private float popOutScaleY = POP_OUT_SCALE_Y;
private int pushInAnimDuration = PUSH_IN_ANIM_DURATION;
private int popOutAnimDuration = POP_OUT_ANIM_DURATION;
private AccelerateDecelerateInterpolator pushInInterpolator = DEFAULT_INTERPOLATOR;
private AccelerateDecelerateInterpolator popOutInterpolator = DEFAULT_INTERPOLATOR;
// 这里是执行
private ScaleView(View view) {
this.view = new WeakReference<View>(view);
if (this.view.get() != null) {
//指定点击事件,需要先判断view的
if(!this.view.get().hasOnClickListeners()) {
this.view.get().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
}
}
}
// dialog 初始化
private ScaleView(Dialog dialog) {
this.dialog = new WeakReference<Dialog>(dialog);
}
// popup 初始化
private ScaleView(PopupWindow popup) {
this.popup = new WeakReference<PopupWindow>(popup);
}
// tabLayout 初始化
private ScaleView(TabLayout tabLayout) {
this.tabLayout = new WeakReference<TabLayout>(tabLayout);
}
// 设置view的动画
public static ScaleView addAnimTo(View view) {
ScaleView bounceAnim = new ScaleView(view);
bounceAnim.setAnimToView();
return bounceAnim;
}
// 给dialog添加动画
public static void addAnimTo(Dialog dialog) {
ScaleView bounceAnim = new ScaleView(dialog);
bounceAnim.setAnimToDialog();
}
// 给Popup添加动画
public static void addAnimTo(PopupWindow popupWindow) {
ScaleView bounceAnim = new ScaleView(popupWindow);
bounceAnim.setAnimToPopup();
}
// 给tabLayout添加动画
public static ScaleView addAnimTo(TabLayout tabLayout) {
ScaleView bounceAnim = new ScaleView(tabLayout);
bounceAnim.setAnimToTabLayout();
return bounceAnim;
}
//设置缩放属性
@Override
public ScaleViewAnim setScaleForPushInAnim(float scaleX, float scaleY) {
this.pushInScaleX = scaleX;
this.pushInScaleY = scaleY;
return this;
}
//设置缩放属性
@Override
public ScaleViewAnim setScaleForPopOutAnim(float scaleX, float scaleY) {
this.popOutScaleX = scaleX;
this.popOutScaleY = scaleY;
return this;
}
//初始化设置缩放时间
@Override
public ScaleViewAnim setPushInAnimDuration(int timeInMillis) {
this.pushInAnimDuration = timeInMillis;
return this;
}
//初始化设置缩放时间
@Override
public ScaleViewAnim setPopOutAnimDuration(int timeInMillis) {
this.popOutAnimDuration = timeInMillis;
return this;
}
//初始化设置缩放加速器
@Override
public ScaleViewAnim setInterpolatorPushIn(AccelerateDecelerateInterpolator interpolatorPushIn) {
this.pushInInterpolator = interpolatorPushIn;
return this;
}
//初始化设置缩放加速器
@Override
public ScaleViewAnim setInterpolatorPopOut(AccelerateDecelerateInterpolator interpolatorPopOut) {
this.popOutInterpolator = interpolatorPopOut;
return this;
}
// 给view是设置动画
private void setAnimToView() {
if (view != null) {
//设置view的触摸监听
view.get().setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(final View v, MotionEvent motionEvent) {
int action = motionEvent.getAction();
//按下会执行一个缩放到0.9的动画。
if (action == MotionEvent.ACTION_DOWN) {
isTouchInsideView = true;
startAnimScale(v, pushInScaleX, pushInScaleY, pushInAnimDuration, pushInInterpolator, 0);
//抬起执行两个动画,缩放,放大
} else if (action == MotionEvent.ACTION_UP) {
if (isTouchInsideView) {
v.animate().cancel();
startAnimScale(v, popOutScaleX, popOutScaleY, popOutAnimDuration, popOutInterpolator, 0);
startAnimScale(v, 1f, 1f, popOutAnimDuration, popOutInterpolator, popOutAnimDuration + 1);
return false;
}
//触摸取消,执行放大动画
} else if (action == MotionEvent.ACTION_CANCEL) {
if (isTouchInsideView) {
v.animate().cancel();
startAnimScale(v, 1f, 1f, popOutAnimDuration, DEFAULT_INTERPOLATOR, 0);
}
return true;
//移动到view外面执行放大
} else if (action == MotionEvent.ACTION_MOVE) {
if (isTouchInsideView) {
float currentX = motionEvent.getX();
float currentY = motionEvent.getY();
float currentPosX = currentX + v.getLeft();
float currentPosY = currentY + v.getTop();
float viewLeft = v.getLeft();
float viewTop = v.getTop();
float viewRight = v.getRight();
float viewBottom = v.getBottom();
if (!(currentPosX > viewLeft && currentPosX < viewRight
&& currentPosY > viewTop && currentPosY < viewBottom)) {
isTouchInsideView = false;
v.animate().cancel();
startAnimScale(v, 1f, 1f, popOutAnimDuration, DEFAULT_INTERPOLATOR, 0);
}
return true;
}
}
return false;
}
});
}
}
//这里执行动画。
private void startAnimScale(View view, float scaleX, float scaleY,
int animDuration,
AccelerateDecelerateInterpolator interpolator,
int startDelay) {
// 设置动画属性x,y
ObjectAnimator animX = ObjectAnimator.ofFloat(view, "scaleX", scaleX);
ObjectAnimator animY = ObjectAnimator.ofFloat(view, "scaleY", scaleY);
//animatorSet 执行。
AnimatorSet animatorSet = new AnimatorSet();
animX.setDuration(animDuration); //设置时间
animX.setInterpolator(interpolator); // 默认的加速器
animY.setDuration(animDuration); //设置动画持续的时间
animY.setInterpolator(interpolator); // 默认的加速器
animatorSet.playTogether(animX, animY); // 一起执行动画
animatorSet.setStartDelay(startDelay); //延时开始动画
animatorSet.start(); //开始动画
}
//给Dialog设置动画
private void setAnimToDialog() {
if (dialog.get() != null) {
Window dialogWindow = dialog.get().getWindow();
dialogWindow.setWindowAnimations(R.style.CustomDialogAnimation);
}
}
//给Popup设置动画
private void setAnimToPopup() {
if (popup.get() != null) {
popup.get().setAnimationStyle(R.style.CustomDialogAnimation);
}
}
//给TabLayout设置动画
private void setAnimToTabLayout() {
if (tabLayout.get() != null) {
//给tab里面的view设置动画
for(int i = 0; i < tabLayout.get().getTabCount(); i++) {
final TabLayout.Tab tab = tabLayout.get().getTabAt(i);
View tabView = ((ViewGroup) tabLayout.get().getChildAt(0)).getChildAt(i);
tabView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent motionEvent) {
int action = motionEvent.getAction();
if (action == MotionEvent.ACTION_DOWN) {
isTouchInsideView = true;
startAnimScale(v, pushInScaleX, pushInScaleY, pushInAnimDuration, pushInInterpolator, 0);
return true;
} else if (action == MotionEvent.ACTION_UP) {
if (isTouchInsideView) {
v.animate().cancel();
startAnimScale(v, popOutScaleX, popOutScaleY, popOutAnimDuration, popOutInterpolator, 0);
startAnimScale(v, 1f, 1f, popOutAnimDuration, popOutInterpolator, popOutAnimDuration + 1);
tab.select();
return false;
}
} else if (action == MotionEvent.ACTION_CANCEL) {
if (isTouchInsideView) {
v.animate().cancel();
startAnimScale(v, 1f, 1f, popOutAnimDuration, DEFAULT_INTERPOLATOR, 0);
}
return true;
} else if (action == MotionEvent.ACTION_MOVE) {
if (isTouchInsideView) {
float currentX = motionEvent.getX();
float currentY = motionEvent.getY();
float currentPosX = currentX + v.getLeft();
float currentPosY = currentY + v.getTop();
float viewLeft = v.getLeft();
float viewTop = v.getTop();
float viewRight = v.getRight();
float viewBottom = v.getBottom();
if (!(currentPosX > viewLeft && currentPosX < viewRight
&& currentPosY > viewTop && currentPosY < viewBottom)) {
isTouchInsideView = false;
v.animate().cancel();
startAnimScale(v, 1f, 1f, popOutAnimDuration, DEFAULT_INTERPOLATOR, 0);
}
return true;
}
}
return false;
}
});
}
}
}
}
dialog,和popupwindow 需要用布局文件的方式,所以我额外定义一个文件,用来处理这方面的问题。路径是 res/anim/scale_anim.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true"
android:interpolator="@android:anim/accelerate_decelerate_interpolator">
<scale
android:duration="75"
android:fromXScale="1"
android:fromYScale="1"
android:toXScale="1.1"
android:toYScale="1.1"
android:pivotX="50%"
android:pivotY="50%"
android:fillAfter="true"/>
<scale
android:duration="75"
android:fromXScale="1.1"
android:fromYScale="1.1"
android:startOffset="75"
android:toXScale="0.9803"
android:toYScale="0.9803"
android:pivotX="50%"
android:pivotY="50%"/>
</set>
####然后在style.xml ,定义一个属性
<style name="CustomDialogAnimation">
<item name="android:windowEnterAnimation">@anim/bounce_anim</item>
</style>
第三步开始使用。什么方法,什么作用,代码里面有注释。
普通的View,是这样用的
ScaleView.addAnimTo(holder.listItem)
.setPopOutAnimDuration(150)
.setScaleForPushInAnim(.95f,.9f)
.setScaleForPopOutAnim(1.05f,1.1f);
AlertDialog,是这样的
DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
getActivity().finish();
break;
case DialogInterface.BUTTON_NEGATIVE:
dialog.dismiss();
break;
}
}
};
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("Alert Dialog")
.setMessage("Do you want to exit?")
.setPositiveButton("Yes", dialogClickListener)
.setNegativeButton("No", dialogClickListener);
AlertDialog dialog = builder.create();
//Add animation to alert dialog
ScaleView.addAnimTo(dialog); //Call before showing the dialog
dialog.show();
CustomDialog 是这样的实现的。
首先自定义一个 CustomDialog
public class CustomDialog extends Dialog implements
View.OnClickListener {
public Activity c;
public Dialog d;
public Button yes, no;
public CustomDialog(Activity a) {
super(a);
this.c = a;
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
protected void onStart() {
super.onStart();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.custom_dialog);
yes = (Button) findViewById(R.id.btn_yes);
no = (Button) findViewById(R.id.btn_no);
ScaleView.addAnimTo(yes);
ScaleView.addAnimTo(no);
yes.setOnClickListener(this);
no.setOnClickListener(this);
WindowManager.LayoutParams lp = getWindow().getAttributes();
lp.dimAmount = 0.0F;
getWindow().setAttributes(lp);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_yes:
c.finish();
break;
case R.id.btn_no:
dismiss();
break;
default:
break;
}
dismiss();
}
}
布局文件 custom_dialog.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="300dp"
android:layout_height="230dp"
android:background="#5a7374"
android:padding="8dp"
android:layout_gravity="center">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="Custom Dialog"
android:textAlignment="center"
android:textColor="#ffffff"
android:textStyle="bold"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#bde9f4"
android:layout_marginTop="30dp">
<TextView
android:id="@+id/txt_dia"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="10dp"
android:text="Do you realy want to exit ?"
android:textSize="15dp"
android:textStyle="bold"
android:layout_centerHorizontal="true"
android:paddingTop="45dp"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="horizontal"
android:gravity="bottom"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:paddingBottom="20dp">
<Button
android:id="@+id/btn_no"
android:layout_width="80dp"
android:layout_height="30dp"
android:background="#d21e1e"
android:clickable="true"
android:text="Cancel"
android:textColor="#ffffff"
android:textAllCaps="false"/>
<Button
android:id="@+id/btn_yes"
android:layout_width="80dp"
android:layout_height="30dp"
android:layout_marginLeft="40dp"
android:background="#00bcff"
android:text="Yes"
android:textColor="#ffffff"
android:textAllCaps="false"/>
</LinearLayout>
</RelativeLayout>
</RelativeLayout>
使用
CustomDialog customDialog = new CustomDialog(getActivity());
//Add animation to custom dialog
ScaleView.addAnimTo(customDialog); //Call before showing the dialog
customDialog.show();
PopupWindow 是这样使用的。
首先定义一个 布局文件 custom_popup.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="250dp"
android:layout_height="85dp"
android:background="#5a7374"
android:padding="8dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="Popup window "
android:textAlignment="center"
android:textColor="#ffffff"
android:textStyle="bold"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#bde9f4"
android:layout_marginTop="30dp">
<TextView
android:id="@+id/txt_dia"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="Lorem Ipsum "
android:textSize="15dp"
android:textStyle="bold"
android:layout_centerHorizontal="true"/>
</RelativeLayout>
</RelativeLayout>
使用
PopupWindow popupWindow;
View menuView = getLayoutInflater().inflate(R.layout.custom_popup, null);
popupWindow = new PopupWindow(menuView, LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT, false);
int[] location = new int[2];
view.getLocationOnScreen(location);
popupWindow.setBackgroundDrawable(new BitmapDrawable());
popupWindow.setOutsideTouchable(true);
ScaleView.addAnimTo(popupWindow);
popupWindow.showAtLocation(view, Gravity.CENTER,
0, 0);
TabLayout是这样使用的
//初始化tablayout
final TabLayout tabLayout = findViewById(R.id.tabs);
//给tabLayout添加动画
ScaleView.addAnimTo(tabLayout);
接下来的是,自定义修改TabLayout的选中文字大小
for (int i = 0; i < tabLayout.getTabCount(); i++) {
final TabLayout.Tab tab = tabLayout.getTabAt(i);
View tabView = ((ViewGroup) tabLayout.getChildAt(0)).getChildAt(i);
TextView tabTabText = (TextView) LayoutInflater.from(this).inflate(R.layout.tab_layout, null);
tabTabText.setText("Tab " + (i + 1));
// tabTabText.setCompoundDrawablesWithIntrinsicBounds(0, iconsList[i], 0, 0);
tabLayout.getTabAt(i).setCustomView(tabTabText);
if (tab.isSelected()) {
tabTabText.setTextSize(25.0f);
tabView.setBackgroundColor(Color.parseColor("#404e4e"));
} else {
tabTabText.setTextSize(12.0f);
tabView.setBackgroundColor(Color.parseColor("#5a7374"));
}
}
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
View tabView = ((ViewGroup) tabLayout.getChildAt(0)).getChildAt(tab.getPosition());
tabView.setBackgroundColor(Color.parseColor("#404e4e"));
TextView customView = (TextView) tabLayout.getTabAt(tab.getPosition()).getCustomView();
customView.setTextSize(25.0f);
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
View tabView = ((ViewGroup) tabLayout.getChildAt(0)).getChildAt(tab.getPosition());
tabView.setBackgroundColor(Color.parseColor("#5a7374"));
TextView customView = (TextView) tabLayout.getTabAt(tab.getPosition()).getCustomView();
customView.setTextSize(12.0f);
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});