android自定義Toast的顯示時間與消失

最近項目裏面需要一個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();









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