android自定义Toast的显示时间与消失

来源:互联网 发布:中国经济现状 知乎 编辑:程序博客网 时间:2024/05/21 10:21

最近项目里面需要一个Toast可以实现自由控制显示的时间,但是android原生态的Toast显示时间只有Length与Short两种,不能够满足项目的需求。在网上查找了下实现方式,发现那些实现方法不怎么好,自己特意从android源码里面把系统的Toast独立出来,自定义一个自己的Toast类,实现了项目需求,并且在最后提供一个例子,介绍该Toast的使用方法。具体代码如下:

Toast.java:

      import android.content.Context;
     import android.content.res.Resources;
     import android.graphics.PixelFormat;
     import android.os.Handler;
     import android.util.Log;
     import android.view.Gravity;
     import android.view.LayoutInflater;
     import android.view.View;
     import android.view.WindowManager;
     import android.widget.TextView;
     public class Toast {
         static final String TAG = "Toast";
         static final boolean localLOGV = false;
         public static final int LENGTH_SHORT = 0;  
         public static final int LENGTH_LONG = 1;
         final Context mContext;
         final TN mTN;
         View mNextView;
         public Toast(Context context) {
             mContext = context;
             mTN = new TN();
             mTN.mY = context.getResources().getDimensionPixelSize(R.dimen.toast_y_offset);
         }    
        public void show() {
             if (mNextView == null) {
                 throw new RuntimeException("setView must have been called");
             }
             TN tn = mTN;
             tn.mNextView = mNextView;
             mTN.show();


         }
         public boolean isShowing(){
         return mTN.mIsShowing;
         }
         public void cancel() {
             mTN.hide();
         }
    
         public void setView(View view) {
             mNextView = view;
         }
         public View getView() {
             return mNextView;
         }


        

    public void setMargin(float horizontalMargin, float verticalMargin) {
        mTN.mHorizontalMargin = horizontalMargin;
        mTN.mVerticalMargin = verticalMargin;
    }


    public float getHorizontalMargin() {
        return mTN.mHorizontalMargin;
    }
    public float getVerticalMargin() {
        return mTN.mVerticalMargin;
    }


    public void setGravity(int gravity, int xOffset, int yOffset) {
        mTN.mGravity = gravity;
        mTN.mX = xOffset;
        mTN.mY = yOffset;
    }
    
    public int getGravity() {
        return mTN.mGravity;
    }
    
    public int getXOffset() {
        return mTN.mX;
    }  
    public int getYOffset() {
        return mTN.mY;
    }  
    public static Toast makeText(Context context, CharSequence text) {
        Toast result = new Toast(context);


        LayoutInflater inflate = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View v = inflate.inflate(R.layout.transient_notification, null);
        TextView tv = (TextView)v.findViewById(R.id.message);
        tv.setText(text);
        
        result.mNextView = v;
        return result;
    }


    public static Toast makeText(Context context, int resId)throws Resources.NotFoundException {
        return makeText(context, context.getResources().getText(resId));
    }


    public void setText(int resId) {
        setText(mContext.getText(resId));
    }
    
    public void setText(CharSequence s) {
        if (mNextView == null) {
            throw new RuntimeException("This Toast was not created with Toast.makeText()");
        }
        TextView tv = (TextView) mNextView.findViewById(R.id.message);
        if (tv == null) {
            throw new RuntimeException("This Toast was not created with Toast.makeText()");
        }
        tv.setText(s);
    }


    private static class TN {
    public boolean mIsShowing=false;
        final Runnable mShow = new Runnable() {
            @Override
            public void run() {
                handleShow();
                mIsShowing=true;
            }
        };


        final Runnable mHide = new Runnable() {
            @Override
            public void run() {
                handleHide();
                // Don't do this in handleHide() because it is also invoked by handleShow()
                mIsShowing=false;
                mNextView = null;
            }
        };


        private final WindowManager.LayoutParams mParams = new WindowManager.LayoutParams();
        final Handler mHandler = new Handler();    


        int mGravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
        int mX, mY;
        float mHorizontalMargin;
        float mVerticalMargin;


       
        View mView;
        View mNextView;


        WindowManager mWM;


        TN() {
            final WindowManager.LayoutParams params = mParams;
            params.height = WindowManager.LayoutParams.WRAP_CONTENT;
            params.width = WindowManager.LayoutParams.WRAP_CONTENT;
            params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                    | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                    | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
            params.format = PixelFormat.TRANSLUCENT;
           // params.format = PixelFormat.OPAQUE;
            params.windowAnimations = R.style.Animation_Toast;
            params.type = WindowManager.LayoutParams.TYPE_TOAST;
            params.setTitle("Toast");
        }
      
        public void show() {
            if (localLOGV) Log.v(TAG, "SHOW: " + this);
            mHandler.post(mShow);
        }
        public void hide() {
            if (localLOGV) Log.v(TAG, "HIDE: " + this);
            mHandler.post(mHide);
        }


        public void handleShow() {
            if (mView != mNextView) {
                handleHide();
                mView = mNextView;
                mWM = (WindowManager)mView.getContext().getApplicationContext()
                        .getSystemService(Context.WINDOW_SERVICE);
                final int gravity = mGravity;
                mParams.gravity = gravity;
                if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.FILL_HORIZONTAL) {
                    mParams.horizontalWeight = 1.0f;
                }
                if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.FILL_VERTICAL) {
                    mParams.verticalWeight = 1.0f;
                }
                mParams.x = mX;
                mParams.y = mY;
                mParams.verticalMargin = mVerticalMargin;
                mParams.horizontalMargin = mHorizontalMargin;
                if (mView.getParent() != null) {
                    if (localLOGV) Log.v(TAG, "REMOVE! " + mView + " in " + this);
                    mWM.removeView(mView);
                }
                if (localLOGV) Log.v(TAG, "ADD! " + mView + " in " + this);
                mWM.addView(mView, mParams);
            }
        }


        public void handleHide() {
            if (localLOGV) Log.v(TAG, "HANDLE HIDE: " + this + " mView=" + mView);
            if (mView != null) {
                // note: checking parent() just to make sure the view has
                // been added...  i have seen cases where we get here when
                // the view isn't yet added, so let's try not to crash.
                if (mView.getParent() != null) {
                    if (localLOGV) Log.v(TAG, "REMOVE! " + mView + " in " + this);
                    mWM.removeView(mView);
                }


                mView = null;
            }
        }
    }
}

Toast.java类结束

下面是该类引用的一些资源文件:

 1布局文件/res/layout/transient_notification.xml,代码如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@drawable/toast_frame"
    >
    <TextView
        android:id="@+id/message"
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:layout_gravity="center_horizontal"
        android:textAppearance="@style/small"
        android:textColor="@color/bright_foreground_dark"
        android:shadowColor="#BB000000"
        android:shadowRadius="2.75"
        />


</LinearLayout>

2动画文件/res/anim,里面有两个动画文件

 (1)    toast_enter.xml,代码如下:

        <?xml version="1.0" encoding="utf-8"?>
       <alpha xmlns:android="http://schemas.android.com/apk/res/android"
        android:interpolator="@android:interpolator/decelerate_quad"
        android:fromAlpha="0.0" android:toAlpha="1.0"
        android:duration="@android:integer/config_longAnimTime" />

(2)  toast_exit.xml,代码如下:

       <?xml version="1.0" encoding="utf-8"?>
        <alpha xmlns:android="http://schemas.android.com/apk/res/android"
        android:interpolator="@android:interpolator/decelerate_quad"
        android:fromAlpha="0.0" android:toAlpha="1.0"
        android:duration="@android:integer/config_longAnimTime" />

3 Toast Y轴的偏移量/res/values/dimens.xml,代码如下:

       <dimen name="toast_y_offset">64dip</dimen>

4 Toast的Style设置/res/values/styles.xml,代码如下:

       <style name="Animation" />
     <style name="Animation.Toast">
        <item name="android:windowEnterAnimation">@anim/toast_enter</item>
        <item name="android:windowExitAnimation">@anim/toast_exit</item>-->
    </style>

5布局中的背景图片toast_frame在图片上传哪里,第一次使用博客,不晓得传成功没有,

  如果没有成功,可以自己找一个图片作为背景。系统图片是.9.png的图片。

6 例子:   

   Toast toast;
   Handler mHandler=new Handler(){


@Override
public void handleMessage(Message msg) {
switch(msg.what){
case 0:
toast=Toast.makeText(context,"自己写的toast,可以自由控制显示时间");
toast.show();
break;
case 1:
if(toast!=null){
toast.cancel();
}
break;
default:
break;
}
}
  
   };

        mHandler.sendEmptyMessage(0);
new Thread(){
public void run(){
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mHandler.sendEmptyMessage(1);
}
}.start();