因為工作需求,所以自己研究了自定義Toast,這里做出總結:
在此之前有一點需要提前說明:Toast與其他組件一樣,都屬於UI界面中的內容,因此在子線程中無法使用Toast彈出提示內容,如果強行在子線程中增加會導致錯誤。本例子使用異步任務來說明,原理跟子線程一樣。
主界面:
自定義Toast彈出的樣式:
MainActivity:
1 public class MainActivity extends AppCompatActivity implements View.OnClickListener { 2 Button btn_define; //自定義Toast 3 Button btn_thread; //線程中的Toast 4 5 @Override 6 protected void onCreate(Bundle savedInstanceState) { 7 super.onCreate(savedInstanceState); 8 requestWindowFeature(Window.FEATURE_NO_TITLE); 9 setContentView(R.layout.activity_main); 10 initButton(); 11 btn_define.setOnClickListener(this); 12 btn_thread.setOnClickListener(this); 13 } 14 15 private void initButton() { 16 btn_define = (Button) findViewById(R.id.btn_all_define); 17 btn_thread = (Button) findViewById(R.id.btn_other_thread); 18 } 19 20 @Override 21 public void onClick(View v) { 22 switch (v.getId()) { 23 case R.id.btn_all_define: 24 ToastMessage("自定義Toast", "這是我自定義的Toast"); 25 break; 26 case R.id.btn_other_thread: 27 //異步任務 28 new AsyncTask<String, Void, Object>() { 29 @Override 30 protected void onPreExecute() { 31 super.onPreExecute(); 32 } 33 34 protected Object doInBackground(String... strings) { 35 //線程中無法使用Toast,需要將Toast發送至主線程中才能使用 36 Message msg = new Message(); 37 msg.what = 1;//標記位,標記是哪個線程傳數據 38 msg.obj = "這是線程的toast"; 39 mHandler.sendMessage(msg); 40 return null; 41 } 42 43 @Override 44 protected void onPostExecute(Object o) { 45 super.onPostExecute(o); 46 } 47 }.execute(); 48 49 break; 50 } 51 } 52 53 Handler mHandler = new MyHandler(); 54 55 private class MyHandler extends Handler { 56 @Override 57 public void handleMessage(Message msg) { 58 super.handleMessage(msg); 59 switch (msg.what) { 60 case 1: 61 String str = (String) msg.obj; 62 Toast.makeText(getApplicationContext(), str, Toast.LENGTH_LONG).show(); 63 break; 64 } 65 } 66 } 67 68 /** 69 * 將Toast封裝在一個方法中,在其它地方使用時直接輸入要彈出的內容即可 70 */ 71 private void ToastMessage(String titles, String messages) { 72 //LayoutInflater的作用:對於一個沒有被載入或者想要動態載入的界面,都需要LayoutInflater.inflate()來載入,LayoutInflater是用來找res/layout/下的xml布局文件,並且實例化 73 LayoutInflater inflater = getLayoutInflater();//調用Activity的getLayoutInflater() 74 View view = inflater.inflate(R.layout.toast_style, null); //加載layout下的布局 75 ImageView iv = view.findViewById(R.id.tvImageToast); 76 iv.setImageResource(R.mipmap.atm);//顯示的圖片 77 TextView title = view.findViewById(R.id.tvTitleToast); 78 title.setText(titles); //toast的標題 79 TextView text = view.findViewById(R.id.tvTextToast); 80 text.setText(messages); //toast內容 81 Toast toast = new Toast(getApplicationContext()); 82 toast.setGravity(Gravity.CENTER, 12, 20);//setGravity用來設置Toast顯示的位置,相當於xml中的android:gravity或android:layout_gravity 83 toast.setDuration(Toast.LENGTH_LONG);//setDuration方法:設置持續時間,以毫秒為單位。該方法是設置補間動畫時間長度的主要方法 84 toast.setView(view); //添加視圖文件 85 toast.show(); 86 } 87 }
activity的布局文件:activity_main.xml
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout 3 xmlns:android="http://schemas.android.com/apk/res/android" 4 android:layout_width="match_parent" 5 android:layout_height="match_parent" 6 android:gravity="center_horizontal" 7 android:orientation="vertical"> 8 9 <Button 10 android:id="@+id/btn_all_define" 11 android:text="自定義Toast" 12 android:layout_width="match_parent" 13 android:layout_height="wrap_content" 14 android:gravity="center_horizontal"/> 15 16 <Button 17 android:id="@+id/btn_other_thread" 18 android:text="線程中Toast的使用" 19 android:layout_width="match_parent" 20 android:layout_height="wrap_content" 21 android:gravity="center_horizontal"/> 22 </LinearLayout>
toast的樣式:toast_style.xml
我這里是比較簡單的樣式,如果想要其他形式的可以根據自身的需求更改界面即可實現。
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:id="@+id/llToast" 4 android:layout_width="wrap_content" 5 android:layout_height="wrap_content" 6 android:background="#ffffffff" 7 android:orientation="vertical" > 8 9 <TextView 10 android:id="@+id/tvTitleToast" 11 android:layout_width="fill_parent" 12 android:layout_height="wrap_content" 13 android:layout_margin="1dip" 14 android:background="#bb000000" 15 android:gravity="center" 16 android:textColor="#ffffffff" /> 17 18 <LinearLayout 19 android:id="@+id/llToastContent" 20 android:layout_width="wrap_content" 21 android:layout_height="wrap_content" 22 android:layout_marginBottom="1dip" 23 android:layout_marginLeft="1dip" 24 android:layout_marginRight="1dip" 25 android:background="#44000000" 26 android:orientation="vertical" 27 android:padding="15dip" > 28 29 <ImageView 30 android:id="@+id/tvImageToast" 31 android:layout_width="wrap_content" 32 android:layout_height="wrap_content" 33 android:layout_gravity="center" /> 34 35 <TextView 36 android:id="@+id/tvTextToast" 37 android:layout_width="wrap_content" 38 android:layout_height="wrap_content" 39 android:gravity="center" 40 android:paddingLeft="10dip" 41 android:paddingRight="10dip" 42 android:textColor="#ff000000" /> 43 </LinearLayout> 44 45 </LinearLayout>
以上就是今天上午研究的自定義的Toast。以后開發直接拿來用就OK!
補充:上面的形式總歸上不了大雅之堂,現在補充一個新的完全自定義的Toast,可以根據自身需求隨意設置:
import com.example.myproject.R; import android.content.Context; import android.view.View; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; public class ToastUtils { private Toast toast; private LinearLayout toastView; /** * 完全自定義布局Toast */ public ToastUtils(Context context, View view, int duration) { toast = new Toast(context); toast.setView(view); toast.setDuration(duration); } /** * 向Toast中添加自定義View */ public ToastUtils addView(View view, int position) { toastView = (LinearLayout) toast.getView(); toastView.addView(view, position); return this; } /** * 設置Toast字體及背景 */ public ToastUtils setToastBackground(int messageColor, int background) { View view = toast.getView(); if (view != null) { TextView message = (TextView) view.findViewById(R.id.message); message.setBackgroundResource(background); message.setTextColor(messageColor); } return this; } /** * 短時間顯示Toast */ public ToastUtils Short(Context context, CharSequence message) { if (toast == null || (toastView != null && toastView.getChildCount() > 1)) { toast = Toast.makeText(context, message, Toast.LENGTH_SHORT); toastView = null; } else { toast.setText(message); toast.setDuration(Toast.LENGTH_SHORT); } return this; } /** * 長時間顯示toast */ public ToastUtils Long(Context context, CharSequence message) { if (toast == null || (toastView != null && toastView.getChildCount() > 1)) { toast = Toast.makeText(context, message, Toast.LENGTH_LONG); toastView = null; } else { toast.setText(message); toast.setDuration(Toast.LENGTH_LONG); } return this; } /** * 自定義顯示Toast的時長 */ public ToastUtils Indefinite(Context context, CharSequence message, int duration) { if (toast == null || (toastView != null && toastView.getChildCount() > 1)) { toast = Toast.makeText(context, message, duration); toastView = null; } else { toast.setText(message); toast.setDuration(duration); } return this; } /** * 顯示Toast */ public ToastUtils show() { toast.show(); return this; } /** * 獲取Toast */ public Toast getToast() { return toast; } }