安卓学习笔记之CustomToast
分析
- 一般Toast都是在界面底部展现的,不过通过设置属性值,改变它的显示状态,和显示消失动画
- toast.setGravity设置显示的位置
- toast.setView(view)用来自定义Toast显示的内容
- 对于设置view的params不起作用时,可以设置view中的子view(如TextView)的LinearLayout.LayoutParams的值
- 通过反射拿到params字段,用以设置动画的样式
实例代码
package com.yu.customview;
import java.lang.reflect.Field;
import android.content.Context;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.yu.safer.R;
public class CustomToast extends Toast{
static Toast toast;
public CustomToast(Context context) {
super(context);
}
/**
* 用以显示Toast
* @param context
* @param text
* @param duration
*/
public static void showToast(Context context,CharSequence text,int duration) {
toast = new Toast(context);
// 加载自定义view
View view = LayoutInflater.from(context).inflate(R.layout.style_toast, null);
// LinearLayout.LayoutParams.MATCH_PARENT -1;
// LinearLayout.LayoutParams.MATCH_PARENT -2;
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(-2, -2);
TextView tv = (TextView) view.findViewById(R.id.tv_toast_content);
// 设置Textview的params属性 可以改变其显示大小
tv.setLayoutParams(params);
tv.setGravity(Gravity.CENTER);
tv.setText(text);
toast.setDuration(duration);
// 设置使Toast显示水平铺满
toast.setGravity(Gravity.FILL_HORIZONTAL, 0, 0);
// 设置动画
setAnimation(R.style.style_toast);
// 将view添加到toast
toast.setView(view);
toast.show();
}
/**
* 设置动画
* @param styleId
*/
public static void setAnimation(int styleId) {
Object mTN = null;
/**
* 获取mTN字段的对象,必须是Toast的实例对象
* 1、通过Toast获取其中的mTN字段
* 2、通过mTN获取其中的mParams字段
* 3、通过mParams进而得到用以设置windowAnimations属性的params
* 查看源码部分mTN()的组成
*/
mTN = getField(toast, "mTN");
if (mTN != null) {
Object mParams = getField(mTN, "mParams");
if (mParams != null && mParams instanceof WindowManager.LayoutParams) {
WindowManager.LayoutParams params = (LayoutParams) mParams;
params.windowAnimations = styleId;
}
}
}
/**
* 反射以获取字段
* @param object 用以获取字段的对象
* @param fieldName 想要获取的字段名
* @return
*/
public static Object getField(Object object,String fieldName) {
try {
Field field = object.getClass().getDeclaredField(fieldName);
if (field != null) {
// 设置为true 用以阻止IllegalAccessException
field.setAccessible(true);
return field.get(object);
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
return null;
}
}
参考Toast的相关源代码,里面右Toast的相关设置
// 以下是源码部分
TN() {
// XXX This should be changed to use a Dialog, with a Theme.Toast
// defined that sets up the layout params appropriately.
final WindowManager.LayoutParams params = mParams;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.width = WindowManager.LayoutParams.WRAP_CONTENT;
params.format = PixelFormat.TRANSLUCENT;
// 设置动画
params.windowAnimations = com.android.internal.R.style.Animation_Toast;
params.type = WindowManager.LayoutParams.TYPE_TOAST;
params.setTitle("Toast");
params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
}
使用案例
注:动画效果在4.4以下似乎有点不行
CustomToast.showToast(this, "自定义Toast", 1);
效果