1. 程式人生 > >android自定義Toast——讓你應用別具一格

android自定義Toast——讓你應用別具一格

實際上,在github上層看到這種toast,但我的感覺是:用起來太麻煩了!我需要的要求是越簡單越好!

簡化Toast

  • 原toast形式:
    Toast.makeText(this,”t”,Toast.LENGTH_LONG).show();或Toast.makeText(this,”t”,Toast.LENGTH_SHORT).show();

- 簡化後: ToastUtil.shorts(“t”); ToastUtil.longs(“t”); 這樣才方便簡單。

1.簡化為兩參

這一步很簡單,只需要這樣:

public class ToastUtil{
    public
static void shorts(Context context,String msg){ Toast.makeText(context,msg,Toast.LENGTH_SHORT).show(); } public static void longs(Context context,String msg){ Toast.makeText(context,msg,Toast.LENGTH_LONG).show(); } }

2.簡化為一參

  • 自定義Application
    這個需要自定義application,假設為MyApp:
    manifest中設定:
<application
    android:name=".MyApp"
>

</application>

在專案根目錄建立類:

public class MyApp extends Application{
    private static MyApp mApp;
    @Override
    public void onCreate() {
        super.onCreate();
        mApp = this;
    }

    public static void getApp(){
        return
mApp; } }
  • 更改ToastUtil
    public class ToastUtil{
    public static void shorts(String msg){
    Toast.makeText(MyApp.getApp(),msg,Toast.LENGTH_SHORT).show();
    }

    public static void longs(String msg){
    Toast.makeText(MyApp.getApp(),msg,Toast.LENGTH_LONG).show();
    }
    }

自定義toast

然後你會發現,系統提供的toast又沒特色,字又小,不使用圖示確實又不好看,使用者很可能在還沒有關注到的時候,資訊已經消失了,這個時候我們就要自定義toast.

1.改變字的大小和背景樣式

修改前:
這裡寫圖片描述
修改後:
這裡寫圖片描述

2.自定義佈局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/linear_outter"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:minHeight="18dp"
    android:background="@drawable/bg_toast"
    android:padding="10dp"
    android:orientation="vertical">
    <TextView
        android:id="@+id/txt_toast"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="18sp"
        android:textColor="@color/white"
        android:gravity="center_vertical"
        />
</LinearLayout>

背景:

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

自定義類,用於修改toast顯示效果

public class CustomToast{
    private static void longs(String message){
        //載入Toast佈局
        View toastRoot = LayoutInflater.from(AppUtils.getSuperContext()).inflate(R.layout.view_toast, null);
        //初始化佈局控制元件
        mTextView = (TextView) toastRoot.findViewById(R.id.txt_toast);
        //為控制元件設定屬性
        mTextView.setText(message);
        //Toast的初始化
        Toast toastStart = new Toast(AppUtils.getSuperContext());
        //獲取螢幕高度
        WindowManager wm = (WindowManager) AppUtils.getSuperContext().getSystemService(Context.WINDOW_SERVICE);
        int height = wm.getDefaultDisplay().getHeight();
        //Toast的Y座標是螢幕高度的2/3,不會出現不適配的問題
        toastStart.setGravity(Gravity.TOP, 0, height / 3*2);
        toastStart.setDuration(Toast.LENGTH_LONG);
        toastStart.setView(toastRoot);
        toastStart.show();
    }

    private static void shorts(String message){
        //載入Toast佈局
        View toastRoot = LayoutInflater.from(AppUtils.getSuperContext()).inflate(R.layout.view_toast, null);
        //初始化佈局控制元件
        mTextView = (TextView) toastRoot.findViewById(R.id.txt_toast);
        //為控制元件設定屬性
        mTextView.setText(message);
        //Toast的初始化
        Toast toastStart = new Toast(AppUtils.getSuperContext());
        //獲取螢幕高度
        WindowManager wm = (WindowManager) AppUtils.getSuperContext().getSystemService(Context.WINDOW_SERVICE);
        int height = wm.getDefaultDisplay().getHeight();
        //Toast的Y座標是螢幕高度的2/3,不會出現不適配的問題,這個比例可根據喜好更改
        toastStart.setGravity(Gravity.TOP, 0, height / 3*2);
        toastStart.setDuration(Toast.LENGTH_SHORT);
        toastStart.setView(toastRoot);
        toastStart.show();
    }
}

好吧,這段程式碼冗餘的太多了,我們合併一下:

public class CustomToast{
    private static void longs(String message){
        message(true,message);
    }

    private static void shorts(String message){
        message(false,message);
    }

    private static void message(boolean isLong,String message){
        //載入Toast佈局
        View toastRoot = LayoutInflater.from(AppUtils.getSuperContext()).inflate(R.layout.view_toast, null);
        //初始化佈局控制元件
        mTextView = (TextView) toastRoot.findViewById(R.id.txt_toast);
        //為控制元件設定屬性
        mTextView.setText(message);
        //Toast的初始化
        Toast toastStart = new Toast(AppUtils.getSuperContext());
        //獲取螢幕高度
        WindowManager wm = (WindowManager) AppUtils.getSuperContext().getSystemService(Context.WINDOW_SERVICE);
        int height = wm.getDefaultDisplay().getHeight();
        //Toast的Y座標是螢幕高度的2/3,不會出現不適配的問題
        toastStart.setGravity(Gravity.TOP, 0, height / 3*2);
        toastStart.setDuration(isLong?Toast.LENGTH_LONG:Toast.LENGTH_SHORT);
        toastStart.setView(toastRoot);
        toastStart.show();
    }
}

修改一下ToastUtil的程式碼:

public class ToastUtil {
    public static void shorts(String msg){
            CustomToast.shorts(msg);
    }

    public static void longs(String msg){
        CustomToast.longs(msg);
    }
 }

這樣就可以了,原有外部呼叫ToastUtil的程式碼可以不用變,這是我使用這個ToastUtil中間類而非直接使用CustomToast的原因,以後修改CustomToast可以不用影響主程式程式碼。

3.增加不同顏色標識不同的toast

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

可以看到,這些和普通toast的區別是背景變了,左側的icon也有變化,圖示大家可以在iconfont自己下載,這裡寫一下三個顏色供讀者參考:紅-E75427 橙-FF8800 綠-1DB34A
貼一下新的CustomToast和ToastUtil:
CustomToast.java

public class CustomToast {
    private static DrawTextView mTextView;

    public static void longs(String message) {
        message(true,message);
    }

    public static void shorts(String message) {
        message(false,message);
    }

    private static void message(boolean longMsg,String message){
        message(longMsg,MSG_NORMAL,message);
    }

    public static void info(String message) {
        message(true,MSG_INFO,message);
    }

    public static void sucess(String message) {
        message(true,MSG_SUCESS,message);
    }

    public static void error(String message) {
        message(true,MSG_ERROR,message);
    }

    public static void shortInfo(String message){
        message(false,MSG_INFO,message);
    }

    public static void shortSuccess(String message){
        message(false,MSG_SUCESS,message);
    }

    public static void shortError(String message){
        message(false,MSG_ERROR,message);
    }

    private static final int MSG_NORMAL = 1;
    private static final int MSG_INFO = 2;
    private static final int MSG_SUCESS = 3;
    private static final int MSG_ERROR = 4;
    private static void message(boolean longMsg,int mode,String message){
        //載入Toast佈局
        View toastRoot = LayoutInflater.from(AppUtils.getSuperContext()).inflate(R.layout.view_toast, null);
        if(mode!=MSG_NORMAL){
            toastRoot.setBackgroundResource(getBGIdByMode(mode));
        }
        //初始化佈局控制元件
        mTextView = (DrawTextView) toastRoot.findViewById(R.id.txt_toast);
        //為控制元件設定屬性
        mTextView.setText(message);
        if(mode!=MSG_NORMAL){
            mTextView.setDraw(getIconByMode(mode));
        }
        //Toast的初始化
        Toast toastStart = new Toast(AppUtils.getSuperContext());
        //獲取螢幕高度
        WindowManager wm = (WindowManager) AppUtils.getSuperContext().getSystemService(Context.WINDOW_SERVICE);
        int height = wm.getDefaultDisplay().getHeight();
        //Toast的Y座標是螢幕高度的2/3,不會出現不適配的問題
        toastStart.setGravity(Gravity.TOP, 0, height / 3*2);
        toastStart.setDuration(longMsg?Toast.LENGTH_LONG:Toast.LENGTH_SHORT);
        toastStart.setView(toastRoot);
        toastStart.show();
    }

    private static int getIconByMode(int mode) {
        switch (mode){
            case MSG_INFO:
                return R.drawable.ic_toast_info;
            case MSG_SUCESS:
                return R.drawable.ic_toast_pass;
            case MSG_ERROR:
                return R.drawable.ic_toast_fail;
        }
        return 0;
    }

    private static int getBGIdByMode(int mode) {
        switch (mode){
            case MSG_INFO:
                return R.drawable.bg_toast_info;
            case MSG_SUCESS:
                return R.drawable.bg_toast_success;
            case MSG_ERROR:
                return R.drawable.bg_toast_error;
        }
        return 0;
    }
}
public class ToastUtil {
    public static void shorts(String msg){
            CustomToast.shorts(msg);
    }

    public static void longs(String msg){
        CustomToast.longs(msg);
    }

    public static void info(String msg){
        CustomToast.info(msg);
    }

    public static void success(String msg){
        CustomToast.sucess(msg);
    }

    public static void error(String msg){
        CustomToast.error(msg);
    }

    public static void sInfo(String msg){
        CustomToast.shortInfo(msg);
    }

    public static void sSuccess(String msg){
        CustomToast.shortSuccess(msg);
    }

    public static void sError(String msg){
        CustomToast.shortError(msg);
    }
}

使用:

ToastUtil.shorts("xx");//普通短訊息
ToastUtil.longs("xx");//普通長訊息
ToastUtil.info("xx");//提醒短訊息
ToastUtil.sInfo("xx");//提醒長訊息
ToastUtil.success("xx");//操作成功短訊息
ToastUtil.sSucess("xx");//操作成功長訊息
ToastUtil.error("xx");//操作失敗短訊息
ToastUtil.sError("xx");//操作失敗長訊息

是不是超超超簡單呢?然而很好用!在一個應用內,我們的toast只需要一種風格足夠。在開發中我往往糾結於為什麼每次想著增加靈活度的時候,都意味著更復雜的程式碼。實際上,很多時候我們只需要一種風格,這種靈活度卻增加了程式碼冗餘。比如使用Glide進行圖片顯示,實際上我並不想每次都這樣寫:

Glide.with(context)
                        .load(url)
                        .diskCacheStrategy(DiskCacheStrategy.SOURCE)
                        .placeholder(R.drawable.place)
                        .into(holder.img_product);

真的相當的麻煩,進行圖片處理一個應用實際上只需要2-3種呼叫形式就足夠了:

public class PicUtil{
    private int defaultDraw = R.drawable.place;
    public static void showCachePic(String url,View target){
        Glide.with(MyApp.getApp())
                .load(url)
                .diskCacheStrategy(DiskCacheStrategy.SOURCE)
                .placeholder(defaultDraw )
                .into(target);
   }

    public static void showPic(String url,View target){
        Glide.with(MyApp.getApp())
                .load(url)
                .placeholder(defaultDraw)
                .into(target);
   }
}

於是,我下次可以直接寫:PicUtil.showCachePic(url,target);

總結

第三方框架為了靈活多樣式往往會增加設計的複雜度,自己的應用可以不用這樣靈活【應用有自己的風格,往往風格比較固定】,甚至在專案中犧牲一定的靈活性降低複雜度,更加簡潔,方便修改(比如如果替換佔位圖)。