自定義好看的Toast

corner_bg.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="#8cc3ff"/>
    <corners android:radius="10dp"/>
</shape>

selector_button.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <shape android:shape="rectangle">
            <solid android:color="#33FFFFFF"/>
            <corners android:topRightRadius="2dp" android:bottomRightRadius="2dp"/>
        </shape>
    </item>
    <item android:drawable="@android:color/transparent"/>
</selector>

xtoast_normal.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/corner_bg">

    <TextView
        android:id="@+id/message"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:paddingLeft="24dp"
        android:paddingRight="24dp"
        android:paddingTop="12dp"
        android:paddingBottom="14dp"
        />
</LinearLayout>

xtoast_bottom.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#46ff78">

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/message"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:layout_gravity="center_vertical"
            android:gravity="start"
            android:singleLine="true"
            android:ellipsize="end"
            android:paddingLeft="24dp"
            android:paddingRight="8dp"
            android:paddingTop="14dp"
            android:paddingBottom="12dp"/>

        <View
            android:id="@+id/divider"
            android:layout_width="1dp"
            android:layout_height="match_parent"
            android:layout_marginBottom="8dp"
            android:layout_marginTop="8dp" />

        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:background="@drawable/selector_button"
            android:paddingStart="8dp"
            android:paddingLeft="8dp"
            android:paddingEnd="12dp"
            android:paddingRight="12dp" />

    </LinearLayout>
</LinearLayout>

動畫工具類AnimationUtils

public class AnimationUtils {

    public static final int ANIMATION_DEFAULT = 0X000;
    public static final int ANIMATION_DRAWER = 0x001;
    public static final int ANIMATION_SCALE = 0x002;
    public static final int ANIMATION_PULL = 0X003;

    public static AnimatorSet getShowAnimation(XToast xToast, int animationType){
        switch (animationType){
            case ANIMATION_DRAWER:
                AnimatorSet drawerSet = new AnimatorSet();
                drawerSet.playTogether(
                        ObjectAnimator.ofFloat(xToast.getView(), "translationY", -xToast.getView().getMeasuredHeight(), 0),
                        ObjectAnimator.ofFloat(xToast.getView(), "alpha", 0, 1)
                );
                drawerSet.setDuration(500);
                return drawerSet;

            case ANIMATION_SCALE:
                AnimatorSet scaleSet = new AnimatorSet();
                scaleSet.playTogether(
                        ObjectAnimator.ofFloat(xToast.getView(), "scaleX", 0, 1),
                        ObjectAnimator.ofFloat(xToast.getView(), "scaleY", 0, 1)
                );
                scaleSet.setDuration(500);
                return scaleSet;

            case ANIMATION_PULL:
                AnimatorSet pullSet = new AnimatorSet();
                pullSet.playTogether(
                        ObjectAnimator.ofFloat(xToast.getView(), "translationY", xToast.getView().getMeasuredHeight(), 0),
                        ObjectAnimator.ofFloat(xToast.getView(), "alpha", 0, 1)
                );
                pullSet.setDuration(500);
                return pullSet;

            default:
                AnimatorSet defaultSet = new AnimatorSet();
                defaultSet.play(ObjectAnimator.ofFloat(xToast.getView(), "alpha", 0, 1));
                defaultSet.setDuration(500);
                return defaultSet;
        }
    }

    public static AnimatorSet getHideAnimation(XToast xToast,int animationType){
        switch (animationType){
            case ANIMATION_DRAWER:
                AnimatorSet drawerSet = new AnimatorSet();
                drawerSet.playTogether(
                        ObjectAnimator.ofFloat(xToast.getView(), "translationY", 0,-xToast.getView().getMeasuredHeight()),
                        ObjectAnimator.ofFloat(xToast.getView(), "alpha", 1, 0)
                );
                drawerSet.setDuration(500);
                return drawerSet;

            case ANIMATION_SCALE:
                AnimatorSet scaleSet = new AnimatorSet();
                scaleSet.playTogether(
                        ObjectAnimator.ofFloat(xToast.getView(),"scaleX",1,0),
                        ObjectAnimator.ofFloat(xToast.getView(),"scaleY",1,0)
                );
                scaleSet.setDuration(500);
                return scaleSet;

            case ANIMATION_PULL:
                AnimatorSet pullSet = new AnimatorSet();
                pullSet.playTogether(
                        ObjectAnimator.ofFloat(xToast.getView(),"translationY",0,xToast.getView().getMeasuredHeight()),
                        ObjectAnimator.ofFloat(xToast.getView(),"alpha",1,0)
                );
                pullSet.setDuration(500);
                return pullSet;

            default:
                AnimatorSet defaultSet = new AnimatorSet();
                defaultSet.play(ObjectAnimator.ofFloat(xToast.getView(), "alpha", 1, 0));
                defaultSet.setDuration(500);
                return defaultSet;
        }
    }

}

Toast類

public class XToast  {
    //general attributes:
    private Context mContext;
    private View mView;
    private ViewGroup mViewGroup;
    private ViewGroup mViewRoot;
    private LayoutInflater mInflater;
    private TextView mTextView;
    private int mTextColor = Color.WHITE;
    private int mTextSize = 20;
    private String message;
    private int mType = XTOAST_TYPE_NORMAL;
    private AnimatorSet mShowAnimatorSet;
    private AnimatorSet mHideAnimatorSet;
    private int mShowAnimationType;
    private int mHideAnimationType;
    private int mDuration;
    private int mBackgroundColor;
    private OnDisappearListener mOnDisappearListener;
    private XToastHandler mXToastHandler;

    //normal type attributes:
    private GradientDrawable mToastBackgound;

    //bottom type attributes:
    private Button mButton;
    private String mButtonText;
    private int mButtonTextSize = 20;
    private int mButtonTextColor = Color.WHITE;
    private OnButtonClickListener mOnClickListener;

    public static final int XTOAST_DURATION_LONG = 3500;
    public static final int XTOAST_DURATION_SHORT = 2000;
    public static final int XTOAST_DURATION_SPECIAL = 5000;

    public static final int XTOAST_TYPE_NORMAL = 1;
    public static final int XTOAST_TYPE_BOTTOM = 2;

    public interface OnDisappearListener{
        void onDisappear(XToast xToast);
    }

    public interface OnButtonClickListener{
        void click(XToast xToast);
    }

    public XToast(Context context)
    {
        this.mContext = context;
        this.mInflater = LayoutInflater.from(context);
    }

    public XToast(Context context,String message,int type)
    {
        this.mContext = context;
        this.message = message;
        this.mType = type;
        this.mInflater = LayoutInflater.from(context);
    }


    public static XToast create(Context context){
        return new XToast(context);
    }

    //create a normal XToast
    public static XToast create(Context context,String message){
        return new XToast(context,message,XTOAST_TYPE_NORMAL);
    }

    public static XToast create(Context context,String message,int type){
        return new XToast(context,message,type);
    }

    public XToast setType(int type){
        this.mType = type;
        return this;
    }

    public XToast setText(int resId){
        this.message = mContext.getString(resId);
        return this;
    }

    public XToast setText(String message){
        this.message = message;
        return this;
    }

    public String getText(){
        return this.message;
    }

    public XToast setTextColor(int color){
        mTextColor = color;
        return this;
    }

    public XToast setTextSize(int size){
        mTextSize = size;
        return this;
    }

    public XToast setBackgroundColor(int color){
        this.mBackgroundColor = color;
        return this;
    }

    public XToast setView(View view){
        this.mView = view;
        return this;
    }

    public View getView(){
        return this.mView;
    }

    public ViewGroup getViewGroup(){
        return this.mViewGroup;
    }

    public ViewGroup getViewRoot(){
        return this.mViewRoot;
    }

    public XToast setDuration(int duration){
        this.mDuration = duration;
        return this;
    }

    public int getDuration(){
        return this.mDuration;
    }

    public XToast setAnimation(int animationType){
        this.mShowAnimationType = animationType;
        this.mHideAnimationType = animationType;
        return this;
    }

    public XToast setShowAnimation(int animationType){
        this.mShowAnimationType = animationType;
        return this;
    }

    public AnimatorSet getShowAnimatorSet(){
        return this.mShowAnimatorSet;
    }

    public XToast setHideAnimation(int animationType){
        this.mHideAnimationType = animationType;
        return this;
    }

    public AnimatorSet getHideAnimatorSet(){
        return this.mHideAnimatorSet;
    }

    public XToast setOnDisappearListener(OnDisappearListener onDisappearListener){
        this.mOnDisappearListener = onDisappearListener;
        return this;
    }

    public OnDisappearListener getOnDisappearListener(){
        return this.mOnDisappearListener;
    }

    public XToast setButtonText(String message){
        mButtonText = message;
        return this;
    }

    public XToast setButtonTextColor(int color){
        mButtonTextColor = color;
        return this;
    }

    public XToast setButtonTextSize(int size){
        mButtonTextSize = size;
        return this;
    }

    public XToast setButtonOnClickListener(OnButtonClickListener listener){
        mOnClickListener = listener;
        return this;
    }

    public boolean isShowing() {
        return mView != null && mView.isShown();
    }

    private void dismiss(){
        mXToastHandler.hideToast(this);
    }

    private void initViews() {
        mViewRoot = (ViewGroup) ((Activity)mContext).findViewById(android.R.id.content);

        switch (mType){
            case XTOAST_TYPE_NORMAL:
                initNormalViews();
                break;

            case XTOAST_TYPE_BOTTOM:
                initBottomViews();
                break;

            default:
                break;
        }

        //對mView的大小進行測量
        int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec((1<<30) -1, View.MeasureSpec.AT_MOST);
        int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec((1<<30) -1,View.MeasureSpec.AT_MOST);
        mView.measure(widthMeasureSpec,heightMeasureSpec);

    }

    private void initNormalViews(){
        mViewGroup = new LinearLayout(mContext);
        FrameLayout.LayoutParams mViewGroupParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
        mViewGroupParams.gravity = Gravity.BOTTOM | Gravity.CENTER;
        mViewGroupParams.bottomMargin = 200;
        mViewGroup.setLayoutParams(mViewGroupParams);
        mViewRoot.addView(mViewGroup);

        //如果用戶沒有使用自己的View,那麼使用默認的mView
        if(mView == null){
            mView = mInflater.inflate(R.layout.xtoast_normal,mViewGroup,false);
            mToastBackgound = (GradientDrawable) mView.getBackground();
            mTextView = (TextView) mView.findViewById(R.id.message);
            mTextView.setTextColor(mTextColor);
            mTextView.setTextSize(mTextSize);
            mTextView.setText(message);
            if(mBackgroundColor != 0){
                mToastBackgound.setColor(mBackgroundColor);
            }
        }
    }

    private void initBottomViews(){
        mViewGroup = new LinearLayout(mContext);
        FrameLayout.LayoutParams mViewGroupParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT);
        mViewGroupParams.gravity = Gravity.BOTTOM;
        mViewGroup.setLayoutParams(mViewGroupParams);
        mViewRoot.addView(mViewGroup);

        mView = mInflater.inflate(R.layout.xtoast_bottom, mViewGroup, false);
        mView.setBackgroundColor(mBackgroundColor != 0 ? mBackgroundColor : 0xFF2F5DFF);
        mTextView = (TextView) mView.findViewById(R.id.message);
        mTextView.setTextColor(mTextColor);
        mTextView.setTextSize(mTextSize);
        mTextView.setText(message);
        mButton = (Button) mView.findViewById(R.id.button);
        mButton.setTextSize(mButtonTextSize);
        mButton.setTextColor(mButtonTextColor);
        mButton.setText(mButtonText);
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dismiss();
                mOnClickListener.click(XToast.this);
            }
        });

        //set the appropriate animation
        mShowAnimationType = AnimationUtils.ANIMATION_PULL;
        mHideAnimationType = AnimationUtils.ANIMATION_PULL;

        //set the show duration.
        setDuration(XTOAST_DURATION_SPECIAL);
    }

    public void show(){

        //準備工作
        initViews();
        if(this.mShowAnimationType == 0)
            this.mShowAnimatorSet = AnimationUtils.getShowAnimation(this,AnimationUtils.ANIMATION_DEFAULT);
        else
            this.mShowAnimatorSet = AnimationUtils.getShowAnimation(this,mShowAnimationType);

        if(this.mHideAnimationType == 0)
            this.mHideAnimatorSet = AnimationUtils.getHideAnimation(this, AnimationUtils.ANIMATION_DEFAULT);
        else
            this.mHideAnimatorSet = AnimationUtils.getHideAnimation(this,mHideAnimationType);

        if(mDuration == 0)
            mDuration = XTOAST_DURATION_SHORT;

        mXToastHandler = XToastHandler.getInstance();
        mXToastHandler.add(this);
    }
}
public class XToastHandler extends Handler {
    private static XToastHandler mToastHandler;
    private final Queue<XToast> mQueue;

    private final static int SHOW_TOAST = 0x123;
    private final static int HIDE_TOAST = 0x456;
    private final static int SHOWNEXT_TOAST = 0X789;

    private XToastHandler(Looper looper)
    {
        super(looper);
        mQueue = new LinkedList<>();
    }

    public synchronized static XToastHandler getInstance()
    {
        if(mToastHandler != null)
            return mToastHandler;
        else{
            mToastHandler = new XToastHandler(Looper.getMainLooper());
            return mToastHandler;
        }
    }

    /**
     *  該方法把XToast添加到消息隊列中
     * @param xToast
     */
    public void add(XToast xToast)
    {
        mQueue.offer(xToast);
        showNextToast();
    }

    public void showNextToast()
    {
        if(mQueue.isEmpty()) return;
        //獲取隊列頭部的XToast
        XToast xToast = mQueue.peek();
        if(!xToast.isShowing()){
            Message message = Message.obtain();
            message.what = SHOW_TOAST;
            message.obj = xToast;
            sendMessage(message);
        }
    }

    @Override
    public void handleMessage(Message msg) {
        XToast xToast = (XToast) msg.obj;
        switch (msg.what)
        {
            case SHOW_TOAST:
                showToast(xToast);
                break;

            case HIDE_TOAST:
                hideToast(xToast);
                break;

            case SHOWNEXT_TOAST:
                showNextToast();
                break;
        }
    }

    public void hideToast(final XToast xToast) {

        if(!xToast.isShowing()){
            mQueue.remove(xToast);
            return;
        }

        if(!mQueue.contains(xToast))
            return;

        AnimatorSet set = xToast.getHideAnimatorSet();
        set.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                //如果動畫結束了,界面中移除mView
                xToast.getViewRoot().removeView(xToast.getViewGroup());
                if (xToast.getOnDisappearListener() != null){
                    xToast.getOnDisappearListener().onDisappear(xToast);
                }

                sendEmptyMessage(SHOWNEXT_TOAST);
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        set.start();
        mQueue.poll();
    }

    private void showToast(XToast xToast) {

        //如果當前有XToast正在展示,直接返回
        if(xToast.isShowing()) return;
        //把mView添加到界面中,實現Toast效果
        xToast.getViewGroup().addView(xToast.getView());
        //獲取動畫效果
        AnimatorSet set = xToast.getShowAnimatorSet();
        set.start();

        Message message = Message.obtain();
        message.what = HIDE_TOAST;
        message.obj = xToast;
        sendMessageDelayed(message,xToast.getDuration());
    }
}

 

使用方式

 XToast.create(this).setText("hello world:)
                .setAnimation(AnimationUtils.ANIMATION_DRAWER)
                .setDuration(XToast.XTOAST_DURATION_SHORT)
                .show();

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章