自定义Toast,支持自定义动画,自定义布局

  • Post author:
  • Post category:其他




前言

  • 系统Toast需要申请通知权限,得不到用户授权,系统Toast将无法展示,部分机型(如小米)还需要打开悬浮窗,才能显示系统Toast。
  • 简易的Toast,内容比较简单。



核心思想

  • 自定义Toast,核心思想,得到DecorView(即FrameLayout)的子View。

    即得到通过setContentView(layoutResID)的布局。再此布局上添加自定义的Toast。
activityWeakReference = new WeakReference<>((Activity) context);
mViewGroup = activityWeakReference.get().getWindow().getDecorView().findViewById(android.R.id.content);

此处用的弱引用,防止Activity出现内存泄漏。



创建Toast对象

 public static WbuToast makeToast(Context context, String msg, int duration) {
        WbuToast wbuToast = new WbuToast(context);
        wbuToast.mShowTime = duration;
        wbuToast.msg = msg;
        mToastArrayList.add(wbuToast);
        return wbuToast;
    }

将创建的对象加入对静态LinkedList中。



显示

public void show() {
        if (SHOWING || mToastArrayList.isEmpty()) {
            return;
        }
        if (activityWeakReference.get() == null || activityWeakReference.get().isFinishing()) {
            mToastArrayList.clear();
            return;
        }
        SHOWING = true;
        WbuToast wbuToast = mToastArrayList.getFirst();
        wbuToast.initToastViewGroup();
        wbuToast.mViewGroup.addView(wbuToast.mToastViewGroup);
        wbuToast.mTextView.setText(wbuToast.msg);
        wbuToast.playStartAnimation(wbuToast);
    }
  • 当没有Toast正在显示,从mToastArrayList取出第一个Toast对象进行显示,如果当前Toast所关联的Activity已销毁,则清空缓存链表。



自定义动画

 private void playStartAnimation(WbuToast wbuToast) {
        ObjectAnimator objectAnimatorOut;
        if (wbuToast.mStartObjectAnimators != null && wbuToast.mStartObjectAnimators.length > 0) {
            objectAnimatorOut = ObjectAnimator.ofPropertyValuesHolder(wbuToast.mTextView, mStartObjectAnimators);
        } else {
        	//默认动画
            objectAnimatorOut = ObjectAnimator.ofFloat(wbuToast.mTextView, "alpha", 0, 1);
        }
        objectAnimatorOut.setDuration(mStartDuration);
        objectAnimatorOut.start();
        //开始动画结束后,播放结束动画
        wbuToast.playEndAnimation(wbuToast);
    }
  • 如果没有传入自定义动画,则播放默认的动画。

    自定义动画,需要传入PropertyValuesHolder 数组,可以传null。
public void customToastAnimation(PropertyValuesHolder[] startObjectAnimators, PropertyValuesHolder[] endObjectAnimators, int startDuration, int endDuration) {
        mStartObjectAnimators = startObjectAnimators;
        mEndObjectAnimators = endObjectAnimators;
        mStartDuration = startDuration;
        mEndDuration = endDuration;
    }



自定义布局

 public void customToastLayout(int layoutId, int textId) {
        mToastLayoutId = layoutId;
        mTextViewId = textId;
    }



示例用法之自定义动画

	WbuToast wbuToast = WbuToast.makeToast(MainActivity.this, "fbgh", WbuToast.LENGTH_LONG);
	PropertyValuesHolder holder1 = PropertyValuesHolder.ofFloat("translationX", 0f, 100f);
	PropertyValuesHolder holder2 = PropertyValuesHolder.ofFloat("translationY", 0f, 100f);
	PropertyValuesHolder holder3 = PropertyValuesHolder.ofFloat("rotation", 0f, 360f);
	PropertyValuesHolder holder4 = PropertyValuesHolder.ofFloat("translationX", 100f, 0f);
	PropertyValuesHolder holder5 = PropertyValuesHolder.ofFloat("translationY", 100f, 0f);
	PropertyValuesHolder holder6 = PropertyValuesHolder.ofFloat("rotation", 360f, 0f);
	wbuToast.customToastAnimation(new PropertyValuesHolder[]{holder1, holder2, holder3}, new PropertyValuesHolder[]{holder4, holder5, holder6}, 1000, 1000);
	wbuToast.show();
  • 效果

    Toast之自定义动画

自定义布局比较简单,就不去演示。



全部代码

public class WbuToast {
    public static int LENGTH_LONG = 3500;
    public static int LENGTH_SHORT = 2000;
    private static boolean SHOWING = false;
    private static final LinkedList<WbuToast> mToastArrayList = new LinkedList<>();

    private String msg;
    private long mShowTime;
    private long mStartDuration;
    private long mEndDuration;
    private int mToastLayoutId;
    private int mTextViewId;
    private TextView mTextView;
    private ViewGroup mToastViewGroup;
    private ViewGroup mViewGroup;
    private FrameLayout.LayoutParams mTextLayoutParams;
    private WeakReference<Activity> activityWeakReference;
    private PropertyValuesHolder[] mStartObjectAnimators;
    private PropertyValuesHolder[] mEndObjectAnimators;


    private WbuToast(Context context) {
        mStartDuration = 300;
        mEndDuration = 300;
        mToastLayoutId = R.layout.toast;
        mTextViewId = R.id.wbu_toast_text_view;
        activityWeakReference = new WeakReference<>((Activity) context);
        mViewGroup = activityWeakReference.get().getWindow().getDecorView().findViewById(android.R.id.content);
    }

    private void initToastViewGroup() {
        mToastViewGroup = (ViewGroup) LayoutInflater.from(activityWeakReference.get()).inflate(mToastLayoutId, mViewGroup, false);
        mTextView = mToastViewGroup.findViewById(mTextViewId);
        if (mTextLayoutParams != null) {
            mTextView.setLayoutParams(mTextLayoutParams);
        }

    }

    public static WbuToast makeToast(Context context, String msg, int duration) {
        WbuToast wbuToast = new WbuToast(context);
        wbuToast.mShowTime = duration;
        wbuToast.msg = msg;
        mToastArrayList.add(wbuToast);
        return wbuToast;
    }

    public void show() {
        if (SHOWING || mToastArrayList.isEmpty()) {
            return;
        }
        if (activityWeakReference.get() == null || activityWeakReference.get().isFinishing()) {
            mToastArrayList.clear();
            return;
        }
        SHOWING = true;
        WbuToast wbuToast = mToastArrayList.getFirst();
        wbuToast.initToastViewGroup();
        wbuToast.mViewGroup.addView(wbuToast.mToastViewGroup);
        wbuToast.mTextView.setText(wbuToast.msg);
        wbuToast.playStartAnimation(wbuToast);

    }

    private void playStartAnimation(WbuToast wbuToast) {
        ObjectAnimator objectAnimatorOut;
        if (wbuToast.mStartObjectAnimators != null && wbuToast.mStartObjectAnimators.length > 0) {
            objectAnimatorOut = ObjectAnimator.ofPropertyValuesHolder(wbuToast.mTextView, mStartObjectAnimators);
        } else {
            objectAnimatorOut = ObjectAnimator.ofFloat(wbuToast.mTextView, "alpha", 0, 1);
        }
        objectAnimatorOut.setDuration(mStartDuration);
        objectAnimatorOut.start();
        wbuToast.playEndAnimation(wbuToast);
    }

    private void playEndAnimation(WbuToast wbuToast) {
        ObjectAnimator objectAnimatorIn;
        if (wbuToast.mEndObjectAnimators != null && wbuToast.mEndObjectAnimators.length > 0) {
            objectAnimatorIn = ObjectAnimator.ofPropertyValuesHolder(wbuToast.mTextView, mEndObjectAnimators);
        } else {
            objectAnimatorIn = ObjectAnimator.ofFloat(wbuToast.mTextView, "alpha", 1, 0);
        }
        objectAnimatorIn.setDuration(mEndDuration);
        objectAnimatorIn.setStartDelay(mShowTime);
        objectAnimatorIn.start();
        objectAnimatorIn.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                if (!mToastArrayList.isEmpty()) {
                    WbuToast wbuToast = mToastArrayList.getFirst();
                    wbuToast.mViewGroup.removeView(wbuToast.mToastViewGroup);
                    mToastArrayList.remove(0);
                    SHOWING = false;
                    show();
                }

            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });

    }

    public void customToastLayout(int layoutId, int textId) {
        mToastLayoutId = layoutId;
        mTextViewId = textId;
    }

    public void customToastPosition(FrameLayout.LayoutParams fl) {
        mTextLayoutParams = fl;
    }

    public void customToastAnimation(PropertyValuesHolder[] startObjectAnimators, PropertyValuesHolder[] endObjectAnimators, int startDuration, int endDuration) {
        mStartObjectAnimators = startObjectAnimators;
        mEndObjectAnimators = endObjectAnimators;
        mStartDuration = startDuration;
        mEndDuration = endDuration;
    }
}



GitHub地址

(https://github.com/android-greenhand/customToast)



版权声明:本文为weixin_45427063原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。