好久不更,强更。
作为Android开发人员,Toast对我们来说应该是老朋友了。Toast能在一个可视的界面给用户一些短暂的反馈,并且反馈完成后会自动消失。在APP开发过程中,Toast真的是一个不可或缺的角色。
提到Toast,很多童鞋信手拈来,三下五除二就撸出一个Toast,并展现在界面。
Toast.makeText(getApplicationContext(),
"你觉得我美吗?n(*≧▽≦*)n",
Toast.LENGTH_LONG).show();
这是Toast的一个基本使用了,这样能快速的创建一个Toast并且将它显示在界面上,但是。。。
但是这样创建的Toast的外观和手机系统主题有关,像我司这部测试机,4.4的系统,然后,你看到的Toast是酱紫的。┑( ̄Д  ̄)┍
并且这样还有一个问题,就是Toast的位置永远都是在同一个地方的。这对于程序猿来说,就感觉太死了,一点都不灵活。那么,我们如何打造一个属于记几的自定义Toast呢?
查看Toast的API,发现有这么多的方法可以供我们使用。
返回值 | 方法名 |
---|---|
void | cancel() 如果视图正在显示,关闭视图。如果视图尚未显示,则不显示 |
int | getDuration() 返回持续时间 |
int | getGravity() 返回视图在屏幕中显示的位置 |
float | getHorizontalMargin() 返回水平边距 |
float | getVerticalMargin() 返回垂直边距 |
View | getView() 返回视图 |
int | getXOffset() 返回应用于Gravity的X方向上的偏移量,以像素为单位 |
int | getYOffset() 返回应用于Gravity的Y方向上的偏移量,以像素为单位 |
static Toast |
makeText(Context context,CharSequence text,int duration) 创建一个包含文字的标准的Toast并返回 |
void | setDuration(int duration) 设置视图显示时长 |
void | setGravity(int gravity,int xOffset,int yOffset) 设置Toast在显示屏中的位置 |
void | setMargin(float horizontalMargin,float verticalMargin) 设置视图的边距 |
void | setText(int resId) 更新已makeText()方式创建的一个已存在的Toast的文字 |
void | setText(CharSequence) 更新已makeText()方式创建的一个已存在的Toast的文字 |
void | setView() 设置要显示的视图 |
void | show() 返回视图在屏幕中显示的位置 |
int | getGravity() 显示指定持续时长的视图 |
既然有了这些方法,我们就可以开始订制属于我们记几的Toast了。前几天在使用某个APP(忘记是哪个APP了)的时候看到一个比较有意思的显示方式。当我刷新的时候,APP弹出一个Toast显示正在刷新,然后刷新完成就告诉我刷新完成。我大致还原出来了,不过和原版还是有出入,以后优化吧。
Toast.gifOK,那我们现在来实现上面的那个效果。我们从上面给出的方法可以看到,Toast有个setView()的方法,这个方法可以让我们传入自己的view。那现在,我们创建一个名字叫custom_toast的布局文件。
custom_toast.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/custom_toast"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/shape_corner_orange"
android:orientation="horizontal"
android:padding="8dp">
<ImageView
android:id="@+id/image_icon"
android:layout_width="50dp"
android:layout_height="50dp"
android:padding="10dp"
android:layout_gravity="center"
android:src="@drawable/ic_check_white"
android:visibility="gone" />
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="center" />
<TextView
android:id="@+id/text_showText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="This is a custom toast!"
android:textColor="@android:color/white"
android:textSize="18sp" />
</LinearLayout>
布局文件有三个子控件,ImageView、ProgressBar和TextView。ImageView用来显示刷新完成后显示的icon,ProgressBar用于显示刷新时的显示旋转动态,最后TextView是用来显示我们的文本信息。这里需要注意,我们需要给根布局写一个id。
有了布局文件,我们就可以将我们的布局展示到Toast上。
mToastView = getLayoutInflater().inflate(R.layout.custom_toast,
(ViewGroup) findViewById(R.id.custom_toast));
mText = (TextView) mToastView.findViewById(R.id.text_showText);
mPro = (ProgressBar) mToastView.findViewById(R.id.progressBar);
mImg = (ImageView) mToastView.findViewById(R.id.image_icon);
mToast = new Toast(getApplicationContext());
mToast.setDuration(Toast.LENGTH_LONG);
mToast.setView(mToastView);
通常情况下,我们加载一个布局大多都会这样写:
view = getLayoutInflater().inflate(R.layout.custom_toast, null);
但是,这里需要注意,我们不能这样写,这里我们需要用xml和根布局的ID来加载布局。到此,我们调用show()方法,我们的自定义Toast就能在屏幕上显示出来了。但是,现在Toast的时长是Toast.LENGTH_LONG。如果我们想要实现加载完毕后再消失,这明显是不能符合我们的需求的。咦上面不是有一个setDuration()方法吗,我们设置想要的时长就好啦,机智!O(∩_∩)O~
But!!!
坑爹1 坑爹2看到了吗?
并不行!!!
setDuration()只接受两个值,一个是Toast.LENGTH_LONG,另外一个是Toast.LENGTH_SHORT。那没办法了,只能想其他的办法了。我们发现,当对同一个Toast实例调用show()方法时,它能一直显示,那好,我们就从这里下手了。
这里我们用到Timer来实现我们的功能。
//设置显示位置为上方并且水平居中,然后偏移量为actionBar的高度加30
mToast.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, getSupportActionBar().getHeight() + 30);
mText.setText("Refreshing...");
mPro.setVisibility(View.VISIBLE);
mImg.setVisibility(View.GONE);
//计时器,用于显示一个自定义时长的Toast
final Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
mToast.show();
}
}, 0, 3000);
timer.schedule(new TimerTask() {
@Override
public void run() {
timer.cancel();
mHandler.sendEmptyMessage(0);
}
}, 5000);
当要显示Toast的时候,我们新建一个定时器,这个定时器执行了两个任务,一个任务时控制Toast能持续的显示,另外一个任务是为了模拟网络加载,加载5s钟后即加载完成。然后发送消息通知加载完成,更新Toast视图。
这里给大家提个醒,Toast的创建方式有两种,一种是同个makeText()的方式来创建,另一种是通过构造函数也就是new的方式来创建,如果不需要用到setView()的话,官方推荐使用通过makeText()方法来创建一个Toast,因为通过构造函数的方法来创建,返回的Toast,是一个没有具体视图的Toast,如果直接使用的话会报错。
到这里我们的实现就算完成了。贴一下完整代码。
Activity.java
package com.kenny.mycustom;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import java.util.Timer;
import java.util.TimerTask;
public class SecondActivity extends BaseActivity {
private static final String TAG = SecondActivity.class.getSimpleName();
private Toast mToast;
private Button btn;
private View mToastView;
private TextView mText;
private ProgressBar mPro;
private ImageView mImg;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
mText.setText("Finished!");
mImg.setVisibility(View.VISIBLE);
mPro.setVisibility(View.GONE);
mToast.setDuration(Toast.LENGTH_LONG);
mToast.show();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
btn = (Button) findViewById(R.id.btn);
mToastView = getLayoutInflater().inflate(R.layout.custom_toast, (ViewGroup) findViewById(R.id.custom_toast));
mText = (TextView) mToastView.findViewById(R.id.text_showText);
mPro = (ProgressBar) mToastView.findViewById(R.id.progressBar);
mImg = (ImageView) mToastView.findViewById(R.id.image_icon);
mToast = new Toast(getApplicationContext());
mToast.setDuration(Toast.LENGTH_LONG);
mToast.setView(mToastView);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//设置显示位置为上方并且水平居中,然后偏移量为actionBar的高度加30
mToast.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, getSupportActionBar().getHeight() + 30);
mText.setText("Refreshing...");
mPro.setVisibility(View.VISIBLE);
mImg.setVisibility(View.GONE);
//计时器,用于显示一个自定义时长的Toast
final Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
mToast.show();
}
}, 0, 3000);
timer.schedule(new TimerTask() {
@Override
public void run() {
timer.cancel();
mHandler.sendEmptyMessage(0);
}
}, 5000);
}
});
}
}
感谢
http://www.jianshu.com/p/73b8b4768cf0
后记
1、这里自定义Toast起一个抛砖引玉的作用,相信大家以后可以根据自己的需求做出更有意思,更有创意,更炫酷的Toast。
2、代码逻辑并没有经过很缜密的思考,指在做一个例子便于讲解,有错漏之处,恳请谅解。
3、写这篇简书的原因主要是沉淀一下自己的学习知识。
4、既然都看到这了,留个脚印,给个like呗。(。・∀・)ノ゙嗨
网友评论