一、引言

在开发的过程中你会发现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. JavaScript判断对象数组中是否存在某个对象【转】

    1. 如果要判断数组中是否存在某个元素的话很好判断,直接用数组的indexOf方法就好,存在返回当前索引不存在返回-1 var arr=[1,2,3,4] arr.indexOf(3) arr.ind ...

  2. python常见的加密方式

    1.前言 我们所说的加密方式都是对二进制编码的格式进行加密,对应到python中,则是我妈们的bytes. 所以当我们在Python中进行加密操作的时候,要确保我们的操作是bytes,否则就会报错. ...

  3. 题解报告:hdu 2647 Reward(拓扑排序)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2647 Problem Description Dandelion's uncle is a boss ...

  4. 【Leetcode 3】Longest Substring Without Repeating Characters0

    Description: Given a string, find the length of the longest substring without repeating characters. ...

  5. Android彻底组件化方案实践

    本文提出的组件化方案demo已经开源,参见文章Android彻底组件化方案开源. 文末有罗辑思维"得到app"的招聘广告,欢迎各路牛人加入!! 一.模块化.组件化与插件化 项目发展 ...

  6. html——ico

    下载: 网址+/favicon.ico 引用: 1.<link href="favicon.ico" rel="icon" /> 2.<lin ...

  7. 【SQLite】select into 语句

    sqlite不支持类似sqlserver中的select into 语法 在SQL Server中,我们要将一个表中的数据复制到一个新表中,可以这样写: SELECT * INTO newtable ...

  8. Codeforces_738B

    B. Spotlights time limit per test 1 second memory limit per test 256 megabytes input standard input ...

  9. 扩增子图表解读8网络图:节点OTU或类Venn比较

    网络图 Network 网络图虽然给人高大上的感觉,但是由于信息太多,无法给读者提供读有效的可读信息或是读者不知道该理解什么,总是让人望尔却步.那是因为大家太不了解网络,自己读不懂网络想表达的意思及其 ...

  10. Navicat 导出为 Excel 文件

    1:先选择一个表 再点击导出向导 2:看图   3:选择保存的路径  4:选择字段    5:最后执行吧