标签:
Toast作为一个基本的界面提醒方式,使用还是比较广,但是介于默认样式比较难看外加有些特殊要求,比如需要在Toast的界面上做事件处理啥的,所以衍生出了Toast的自定义样式
1 Toast tempToast = Toast.makeText(getApplicationContext(), "默认的Toast样式", 2 Toast.LENGTH_LONG); 3 //可以设置位置 4 //tempToast.setGravity(Gravity.BOTTOM | Gravity.RIGHT, 10, 10); 5 tempToast.show();
对于这种基本的样式,在不同的android版本或者不同的rom显示不同,比如在官方的4.4的版本之后该Toast会变成蓝色背景,而之前的背景都是如图的黑色背景。简单场景能用,稍微需要显示复杂点的东西就无法使用了
然而大部分的使用情况肯定不限于该种样式,很多开发者希望Toast能够显示更多东西,如图片和文字按一定规则混排啥的,这个也非常简单,只需要自定义一个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="match_parent" 12 android:layout_height="wrap_content" 13 android:layout_margin="1dip" 14 android:background="#bb000000" 15 android:gravity="center" 16 android:text="Title" 17 android:textColor="#ffffffff" /> 18 19 <LinearLayout 20 android:id="@+id/llToastContent" 21 android:layout_width="wrap_content" 22 android:layout_height="wrap_content" 23 android:layout_marginBottom="1dip" 24 android:layout_marginLeft="1dip" 25 android:layout_marginRight="1dip" 26 android:background="#44000000" 27 android:orientation="vertical" 28 android:padding="15dip" > 29 30 <ImageView 31 android:id="@+id/tvImageToast" 32 android:layout_width="wrap_content" 33 android:layout_height="wrap_content" 34 android:layout_gravity="center" 35 android:contentDescription="@string/hello_world" 36 android:src="@drawable/ic_launcher" /> 37 38 <TextView 39 android:id="@+id/tvTextToast" 40 android:layout_width="wrap_content" 41 android:layout_height="wrap_content" 42 android:gravity="center" 43 android:paddingLeft="10dip" 44 android:paddingRight="10dip" 45 android:singleLine="false" 46 android:text="自定义显示语句" 47 android:textColor="#ff000000" /> 48 </LinearLayout> 49 50 </LinearLayout>
然后再代码中,将该布局设置为Toast的View即可
public void showCustomToast(View v) { // 通用的布局加载器 LayoutInflater inflater = getLayoutInflater(); // 加载根容器,方便用于后面的view的定位 View layout = inflater.inflate(R.layout.toast_test, (ViewGroup) findViewById(R.id.llToast)); // 设置图片的源文件 ImageView image = (ImageView) layout.findViewById(R.id.tvImageToast); image.setImageResource(R.drawable.ic_launcher); // 设置title及内容 TextView title = (TextView) layout.findViewById(R.id.tvTitleToast); title.setText("通知"); TextView text = (TextView) layout.findViewById(R.id.tvTextToast); text.setText("通过XML自定义Toast"); Toast tempToast = new Toast(getApplicationContext()); // 设置位置 tempToast.setGravity(Gravity.BOTTOM | Gravity.RIGHT, 10, 10); // 设置显示时间 tempToast.setDuration(Toast.LENGTH_LONG); tempToast.setView(layout); tempToast.show(); }
通过XML对Toast进行自定义后,可视化效果提高了很多,也能满足基本的现实要求了。
但是由于Toast的组件属性,导致其不能获取焦点,也就是我无法在上面获取onclick等事件,假设我想在Toast上增加一个关闭按钮,或者点击Toast的主体内容即可跳转一个网页啥的,这个时候基本的Toast就无法满足了
当然,不仅限于Dialog,任何View都可以进行自定义布局然后伪装成Toast,只是Dialog提供好了show方法和dissmis方法,所以工作量比较小,就使用Dialog进行伪装而已
首先要去除Dialog的基本样式,也就是不能带有原有的基本边框,所以我们需要先定义一个需要的dialog的主题
1 <style name="ToastDialog" parent="@android:Theme.Dialog"> 2 <item name="android:windowFrame">@null</item> 3 <item name="android:windowNoTitle">true</item> 4 <item name="android:windowIsFloating">true</item> 5 <item name="android:windowContentOverlay">@null</item> 6 <item name="android:backgroundDimEnabled">false</item> 7 </style>
代码的意思就是单纯的英文意思,就不做翻译了,这样就吧dialog剥成了一个什么都没有的浮动view
下面对dialog的样式进行定义,也就是layout,跟上一段代码差不多,我们增加一个关闭按钮
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 <LinearLayout 10 android:layout_width="match_parent" 11 android:layout_height="wrap_content" 12 android:orientation="horizontal" > 13 14 <TextView 15 android:id="@+id/tvTitleToast" 16 android:layout_width="0dp" 17 android:layout_height="wrap_content" 18 android:layout_weight="1" 19 android:layout_margin="1dip" 20 android:background="#bb000000" 21 android:gravity="center" 22 android:text="Title" 23 android:textColor="#ffffffff" /> 24 25 <ImageView 26 android:id="@+id/ivClose" 27 android:layout_marginRight="1dip" 28 android:layout_marginTop="1dip" 29 android:layout_marginBottom="1dip" 30 android:background="#bb000000" 31 android:layout_width="wrap_content" 32 android:layout_height="match_parent" 33 android:src="@android:drawable/presence_offline" /> 34 35 </LinearLayout> 36 37 <LinearLayout 38 android:id="@+id/llToastContent" 39 android:layout_width="wrap_content" 40 android:layout_height="wrap_content" 41 android:layout_marginBottom="1dip" 42 android:layout_marginLeft="1dip" 43 android:layout_marginRight="1dip" 44 android:background="#44000000" 45 android:orientation="vertical" 46 android:padding="15dip" > 47 48 <ImageView 49 android:id="@+id/tvImageToast" 50 android:layout_width="wrap_content" 51 android:layout_height="wrap_content" 52 android:layout_gravity="center" 53 android:contentDescription="@string/hello_world" 54 android:src="@drawable/ic_launcher" /> 55 56 <TextView 57 android:id="@+id/tvTextToast" 58 android:layout_width="wrap_content" 59 android:layout_height="wrap_content" 60 android:gravity="center" 61 android:paddingLeft="10dip" 62 android:paddingRight="10dip" 63 android:singleLine="false" 64 android:text="自定义显示语句" 65 android:textColor="#ff000000" /> 66 </LinearLayout> 67 68 </LinearLayout>
接下来则是需要自定义一个dlalog的类,考虑到只是个教程,所以都是以最简单的方法进行编写
1 public class MyToastDialog extends Dialog { 2 3 // 显示的时间,用于模拟Toast的duringTime 4 private long showTime; 5 6 // 显示结束后自动关闭dialog的线程 7 private Runnable autoDissmis = new Runnable() { 8 9 @Override 10 public void run() { 11 try { 12 Thread.sleep(showTime); 13 // 注意进行是否存在显示的判定 14 if (isShowing()) { 15 dismiss(); 16 } 17 } catch (InterruptedException e) { 18 e.printStackTrace(); 19 } 20 } 21 }; 22 23 public MyToastDialog(Context context, long duringTime) { 24 // 设置dialog的主题 25 super(context, R.style.ToastDialog); 26 // 设置dlaog的样式,把它放在构造函数里的好处在于:也可以再外面使用setContentView进行重新设定 27 setContentView(R.layout.toast_test_dialog); 28 showTime = duringTime; 29 } 30 31 @Override 32 protected void onCreate(Bundle savedInstanceState) { 33 super.onCreate(savedInstanceState); 34 35 // 通过获取dialog的windows对象对位置坐标进行设置 36 Window dialogWindow = this.getWindow(); 37 WindowManager.LayoutParams lp = dialogWindow.getAttributes(); 38 dialogWindow.setGravity(Gravity.BOTTOM | Gravity.RIGHT); 39 40 lp.x = 10; // 新位置X坐标 41 lp.y = 10; // 新位置Y坐标 42 // lp.width = 300; // 宽度 43 // lp.height = 300; // 高度 44 // lp.alpha = 1f; // 透明度 45 46 dialogWindow.setAttributes(lp); 47 } 48 49 @Override 50 public void show() { 51 // 重构show函数,在show的同时 启动计时进程 52 new Thread(autoDissmis).start(); 53 super.show(); 54 } 55 56 }
然后再代码中调用显示,并且设置想要设置的事件相应即可
1 public void showToastDialog(View v) { 2 long duringTime = 3000; 3 final MyToastDialog tempDialog = new MyToastDialog(this, duringTime); 4 5 ImageView image = (ImageView) tempDialog.findViewById(R.id.ivClose); 6 image.setOnClickListener(new OnClickListener() { 7 8 @Override 9 public void onClick(View v) { 10 tempDialog.dismiss(); 11 } 12 }); 13 14 tempDialog.show(); 15 }
上图:
这个的好处在于,可以获取Toast对象的焦点,可以实现像QQ左下角弹出对话框一样的东东~~估计还是有点点用处
其实伪造的并不是很成功,因为Toast不获取焦点也有不获取焦点的好处,这样不会妨碍Toast显示过程中对后面界面的操作,但是一旦获取焦点之后,后面的界面就会变得无法操作,难免造成不良体验,当然需求总是仁者见仁智者见智,考虑实际场景选择合适的做法才是最优解
标签:
原文地址:http://www.cnblogs.com/coldcode/p/4504797.html