转于:http://blog.csdn.net/farmer_cc/article/details/19352563
-------------------------------------------------------------------------------------
仿MIUI toast 动画效果实现
本文中涉及两个点比较重要:一是设计一个OvershootInterpolator,并使用开源库实现的动画效果;二是使用自定义的layout ,并通过WindowManager 的addView() 添加,实现类似toast效果,并增加toast 的点击事件回调处理。
1 动画效果
用前文中讲述的动画基础,实现一个toast的动画效果并没有多少困难。就是一个Y 轴的位移动画,并加上一个overshoot 的interpolator插值器。
关心动画效果的同学,直接看这里实现动画效果的代码。
- private static Interpolator mOverShootInter = new OvershootInterpolator();
- animate(textView).translationY(ViewHelper.getTranslationY(textView) - dp2px(ctx, 200)).setDuration(
- 200).setInterpolator(mOverShootInter);
- public static float dp2px(Context cxt, float dp) {
- return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
- cxt.getResources().getDisplayMetrics());
- }
- private static class OvershootInterpolator implements Interpolator {
- @Override
- public float getInterpolation(float input) {
- if (input < 0.5f)
- return (float) (Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
- else
- return 0.5f * (o(input * 2.0f - 2.0f, 4) + 2.0f);
- }
- private float o(float t, float s) {
- return t * t * ((s + 1) * t + s);
- }
- }
其中函数dp2px 是为了不同分辨率屏幕兼容性而计算dp 值到px 的转换。就是写个动画的距离。
类OvershootInterpolator是参考系统的AnticipateOvershootInterpolator 和AccelerateDecelerateInterpolator 插值器使用分段函数拼接而成。插值器的分析和设计可以参考前文《Android 动画animation 深入分析》
2 可点击的toast 的实现。
实现的关键是使用WindowManager 的addView() 动态添加一个自定义的toast view,加入回调接口,在点击事件中回调即可。
- public static final int TOAST_LONG = 5000;
- public static final int TOAST_SHORT = 3000;
- public static void showCustomToast(final Context ctx, CharSequence toastMessage,
- final OnClickListener clickCallback, int duration) {
- final WindowManager windowManager;
- windowManager = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
- final RelativeLayout addedLayout = (RelativeLayout) LayoutInflater.from(ctx).inflate(
- R.layout.custom_toast_view, null);
- RelativeLayout toastHolder = (RelativeLayout) addedLayout.findViewById(R.id.toast_holder);
- toastHolder.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- // TODO Auto-generated method stub
- Toast.makeText(ctx, "toast holder clicked!", Toast.LENGTH_SHORT).show();
- windowManager.removeView(addedLayout);
- }
- });
- final ValueAnimator anim = ValueAnimator.ofInt(0, 1);
- anim.setDuration(duration);
- anim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- try {
- windowManager.removeView(addedLayout);
- } catch (Exception e) {
- // may throw "View not attached to window" exception when
- // "mWindowManager.mView == null" or "mWindowManager.mView.length == 0",
- // that means no view attached to this window
- }
- Toast.makeText(ctx, "custom toast removed!", Toast.LENGTH_SHORT).show();
- }
- });
- anim.start();
- TextView textView = (TextView) addedLayout.findViewById(R.id.toast_text);
- textView.setText(toastMessage);
- textView.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- // TODO Auto-generated method stub
- anim.end();
- if (clickCallback != null) {
- clickCallback.onClick(v);
- }
- Toast.makeText(ctx, "custom toast clicked!", Toast.LENGTH_SHORT).show();
- }
- });
- LayoutParams addedLayoutParams;
- addedLayoutParams = new WindowManager.LayoutParams(LayoutParams.MATCH_PARENT,
- LayoutParams.MATCH_PARENT, LayoutParams.TYPE_PHONE, LayoutParams.FLAG_NOT_FOCUSABLE
- | LayoutParams.FLAG_FULLSCREEN, PixelFormat.TRANSPARENT);
- addedLayoutParams.x = 0;
- addedLayoutParams.y = 0;
- windowManager.addView(addedLayout, addedLayoutParams);
- animate(textView).translationY(ViewHelper.getTranslationY(textView) - dp2px(ctx, 200)).setDuration(
- 200).setInterpolator(mOverShootInter);
- }
3 自定义的iew
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/toast_holder"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical" >
- <TextView
- android:id="@+id/toast_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:layout_centerHorizontal="true"
- android:layout_marginBottom="120dp"
- android:background="@drawable/toast_view_bg"
- android:drawableLeft="@drawable/ic_launcher"
- android:drawablePadding="8dp"
- android:gravity="center"
- android:paddingBottom="6dp"
- android:paddingLeft="8dp"
- android:paddingRight="8dp"
- android:paddingTop="6dp"
- android:text="custom toast"
- android:textColor="@color/grey"
- android:textSize="14sp" />
- </RelativeLayout>