一、引言

在开发的过程中你会发现Android自身的Toast提示有很多限制,比方我想自己定义Toast的动画、自己定义一个美观的View显示在Toast中、很多其它的是让Toast显示指定的时长等等。

首先一下效果怎样:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhhbmd3ZWl3dG1kYmY=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

二、原理

自己定义的原理也非常easy,就是给WindowManager加入View和删除View,只是须要设置WindowManager.LayoutParams和View的样式。使其看起来和Android系统的Toast看起来非常相像。

详细代码例如以下:

/**
* Custom Toast
*
* @author Lucky
*
*/
public class ToastHelper {
public static final int LENGTH_LONG = 3500;
public static final int LENGTH_SHORT = 2000;
private WindowManager mWindowManager;
private WindowManager.LayoutParams mWindowParams;
private View toastView;
private Context mContext;
private Handler mHandler;
private String mToastContent = "";
private int duration = 0;
private int animStyleId = android.R.style.Animation_Toast; private final Runnable timerRunnable = new Runnable() { @Override
public void run() {
removeView();
}
}; private ToastHelper(Context context) {
// Notice: we should get application context
// otherwise we will get error
// "Activity has leaked window that was originally added"
Context ctx = context.getApplicationContext();
if (ctx == null) {
ctx = context;
}
this.mContext = ctx;
mWindowManager = (WindowManager) mContext
.getSystemService(Context.WINDOW_SERVICE);
init();
} private void init() {
mWindowParams = new WindowManager.LayoutParams();
mWindowParams.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
mWindowParams.alpha = 1.0f;
mWindowParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
mWindowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
mWindowParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
mWindowParams.format = PixelFormat.TRANSLUCENT;
mWindowParams.type = WindowManager.LayoutParams.TYPE_TOAST;
mWindowParams.setTitle("ToastHelper");
mWindowParams.packageName = mContext.getPackageName();
mWindowParams.windowAnimations = animStyleId;// TODO
mWindowParams.y = mContext.getResources().getDisplayMetrics().widthPixels / 5;
} @SuppressWarnings("deprecation")
@SuppressLint("NewApi")
private View getDefaultToastView() { TextView view = new TextView(mContext);
view.setText(mToastContent);
view.setGravity(Gravity.CENTER_VERTICAL | Gravity.START);
view.setFocusable(false);
view.setClickable(false);
view.setFocusableInTouchMode(false);
view.setTextColor(android.graphics.Color.WHITE);
Drawable drawable = mContext.getResources().getDrawable(
android.R.drawable.toast_frame); if (Build.VERSION.SDK_INT < 16) {
view.setBackgroundDrawable(drawable);
} else {
view.setBackground(drawable);
}
return view;
} public void show() {
removeView();
if (toastView == null) {
toastView = getDefaultToastView();
}
mWindowParams.gravity = android.support.v4.view.GravityCompat
.getAbsoluteGravity(Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM,
android.support.v4.view.ViewCompat
.getLayoutDirection(toastView));
removeView();
mWindowManager.addView(toastView, mWindowParams);
if (mHandler == null) {
mHandler = new Handler();
}
mHandler.postDelayed(timerRunnable, duration);
} public void removeView() {
if (toastView != null && toastView.getParent() != null) {
mWindowManager.removeView(toastView);
mHandler.removeCallbacks(timerRunnable);
}
} /**
* @param context
* @param content
* @param duration
* @return
*/
public static ToastHelper makeText(Context context, String content,
int duration) {
ToastHelper helper = new ToastHelper(context);
helper.setDuration(duration);
helper.setContent(content);
return helper;
} /**
* @param context
* @param strId
* @param duration
* @return
*/
public static ToastHelper makeText(Context context, int strId, int duration) {
ToastHelper helper = new ToastHelper(context);
helper.setDuration(duration);
helper.setContent(context.getString(strId));
return helper;
} public ToastHelper setContent(String content) {
this.mToastContent = content;
return this;
} public ToastHelper setDuration(int duration) {
this.duration = duration;
return this;
} public ToastHelper setAnimation(int animStyleId) {
this.animStyleId = animStyleId;
mWindowParams.windowAnimations = this.animStyleId;
return this;
} /**
* custom view
*
* @param view
*/
public ToastHelper setView(View view) {
this.toastView = view;
return this;
}
}

另外分享一个自己定义的Anim:

1.显示Toast的动画:

<?xml version="1.0" encoding="utf-8"?

>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:fillAfter="true" > <alpha
android:fromAlpha="0.0"
android:toAlpha="1.0" /> <translate
android:fromYDelta="20%"
android:toYDelta="0%" /> <scale
android:fromXScale="0.5"
android:fromYScale="0.5"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1.0"
android:toYScale="1.0" /> </set>

2.退出Toast的动画:

<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:fillAfter="true" > <alpha
android:fromAlpha="1.0"
android:toAlpha="0.0" /> <translate
android:fromYDelta="0%"
android:toYDelta="20%" /> </set>

给WIndowManager中的View加入动画须要定义一个style,例如以下:

    <style name="PopToast">
<item name="@android:windowEnterAnimation">@anim/anim_toast_enter</item>
<item name="@android:windowExitAnimation">@anim/anim_toast_exit</item>
</style>

最后能够依照例如以下的方式去使用:

ToastHelper
.makeText(this, "hello world 你好。哈拉雷速度发说得对",
ToastHelper.LENGTH_SHORT)
.setAnimation(R.style.PopToast).show();

三、參考资料:

SuperToast: https://github.com/JohnPersano/SuperToasts

Android自己定义Toast的更多相关文章

  1. Android 自己定义ScrollView ListView 体验各种纵向滑动的需求

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38950509.本文出自[张鸿洋的博客] 1.概述 群里的一个哥们有个需求是这种: ...

  2. Android自己定义组件系列【5】——进阶实践(2)

    上一篇<Android自己定义组件系列[5]--进阶实践(1)>中对任老师的<可下拉的PinnedHeaderExpandableListView的实现>前一部分进行了实现,这 ...

  3. 46.Android 自己定义Dialog

    46.Android 自己定义Dialog Android 自己定义Dialog 前言 提示Dialog 提示Dialog 效果图 菜单Dialog 菜单Dialog 效果图 DialogActivi ...

  4. Android 自己定义RecyclerView 实现真正的Gallery效果

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38173061 .本文出自:[张鸿洋的博客] 上一篇博客我使用自己定义Horizo ...

  5. android自己定义刷新类控件

    android尽管定义了种类很丰富的控件.可是有的时候这些自己定义的控件还是不能满足我的要求,为了可以适配很多其它的需求,我们须要在原有的基础上进行自己定义控件. 今天我向大家介绍的就是android ...

  6. Android自己定义DataTimePicker(日期选择器)

    Android自己定义DataTimePicker(日期选择器)  笔者有一段时间没有发表关于Android的文章了,关于Android自己定义组件笔者有好几篇想跟大家分享的,后期会记录在博客中.本篇 ...

  7. Android UI--自定义ListView(实现下拉刷新+加载更多)

    Android UI--自定义ListView(实现下拉刷新+加载更多) 关于实现ListView下拉刷新和加载更多的实现,我想网上一搜就一堆.不过我就没发现比较实用的,要不就是实现起来太复杂,要不就 ...

  8. Android自己定义组件系列【7】——进阶实践(4)

    上一篇<Android自己定义组件系列[6]--进阶实践(3)>中补充了关于Android中事件分发的过程知识.这一篇我们接着来分析任老师的<可下拉的PinnedHeaderExpa ...

  9. ANDROID自己定义视图——onLayout源代码 流程 思路具体解释

    转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! 简单介绍: 在自己定义view的时候.事实上非常easy.仅仅须要知道3步骤: 1.測量- ...

随机推荐

  1. Java中的自定义注解

    ## 元注解 要声明一个注解, 我们需要元注解, 元注解是指注解的注解,包括@Retention, @Target, @Document, @Inherited. @Retention 注解的保留位置 ...

  2. display:none 和 hidden 区别

  3. jmeter关联、下载文件、简单压测

    关联 一.什么是关联 关联是请求与请求之间存在数据依赖关系,需要从上一个请求获取下一个请求需要回传回去的数据. 简单地说就是在测试过程中有些数据的值会经常发生变化,要获取并使用这些数据,把这个动态的信 ...

  4. shell script练习:利用日期进行文件的创建

    随日期变化:利用 date 进行文件的创建 想像一个状况,假设我的服务器内有数据库,数据库每天的数据都不太一样,因此当我备份时, 希望将每天的数据都备份成不同的档名,这样才能够让旧的数据也能够保存下来 ...

  5. 如何下载Nginx(Windows) 并且简单使用

    官网地址:http://nginx.org/ 进入官网后点击: 推荐下载的是稳定版: 现在开始简单的使用: 一.打开下载文件的目录解压后打开文件 二.在其他盘新建一个test.html,静态资源,用来 ...

  6. (转)Vue 爬坑之路(三)—— 使用 vue-router 跳转页面

    使用 Vue.js 做项目的时候,一个页面是由多个组件构成的,所以在跳转页面的时候,并不适合用传统的 href,于是 vue-router 应运而生. 官方文档: https://router.vue ...

  7. Serializable和Parcelable的简单介绍

    Serializable和Pacelable接口可以完成对象的序列化过程,当我们需要通过Intent和Binder传输数据时就需要使用Parcelable或者Serializable. Seriali ...

  8. Android Studio查看CPU使用率。

    进入AS自带的CMD,依次输入: (1)进入Android Atudio安卓的目录: 1.H: 2.cd AndroidStudio\sdk\platform-tools (2)adb shell ( ...

  9. 移动web——bootstrap响应式轮播图

    基本介绍 1.bootstrap有轮播图的模板,我们只需要改动下就行. 2.这里我们将介绍桌面版本和移动版本最后是综合版本 桌面版本 1.这里的图片设置是有窍门的,不再去添加img标签,而是作为a标签 ...

  10. docker安装后出现Cannot connect to the Docker daemon

    启动docker service docker start docker安装后出现Cannot connect to the Docker daemon You need to add user in ...