A brief summary of Android toast


The old rule, let’s go to the renderings first


It mainly realizes several common ways

1. The most basic toast

The system’s built-in toast is in the form of queue. The next toast can only be displayed after the current toast disappears. The reason is that toast management is in the queue. Click once to generate a new toast. The task of displaying toast will not be finished until the toast in the queue is processed. So ~ we can change toast to singleton mode, and create a new toast without toast. In this way, we can solve the problem of continuously clicking toast and displaying it all the time.

2. Toast of custom location

3. Toast of custom layout (with pictures)

4. Customize toast control with animation effect

OK, here’s the code

Code implementation:

Start with the activity code

public class ToastActivity extends BaseTitleActivity {
    Button basicToast;
    Button basicToast2;
    Button customLocation;
    Button customPicture;
    Button customSmile;
    Button customSmile2;
//    private static CustomToast customToastView;
    public static void newInstance(Context context){
        Intent intent = new Intent(context, ToastActivity.class);
    protected void onCreate(@Nullable Bundle savedInstanceState) {
    public int getResourcesId() {
        return R.layout.activity_toast;
    public void initView() {
    public void initData() {
    public int getTitleText() {
        return R.string.play_toast;
    @OnClick( {R.id.btn_basic_toast, R.id.btn_custom_location, R.id.btn_custom_picture, R.id.btn_custom_smile, R.id.btn_custom_smile2,
                R.id.btn_basic_toast2} )
    public void onViewClick(View v){
        switch (v.getId()){
            /*The most basic toast solves the problem that native toast cannot be updated quickly*/
            case R.id.btn_basic_toast:
                ToastUtils.showToast (this, "this is the most basic toast");
            case R.id.btn_basic_toast2:
                ToastUtils.showToast (this, "= = = updated = =");
            /*Toast for custom location
             *Relative to Gravity.LEFT Position, offset in X direction, offset in Y direction*/
            case R.id.btn_custom_location:
                Toast toast =  Toast.makeText ( ToastActivity.this , toast of custom location, Toast.LENGTH_ SHORT);
                toast.setGravity(Gravity.LEFT,0, 0);
            /*Toast with pictures, custom layout
             *Reference Toast.makeText () method*/
            case R.id.btn_custom_picture:
                Toast result = new Toast(this);
                View toastView = LayoutInflater.from(this).inflate(R.layout.toast_custom, null);
                ImageView img = (ImageView) toastView.findViewById(R.id.iv_img);
                TextView msg = (TextView) toastView.findViewById(R.id.tv_msg);
                result.setGravity(Gravity.BOTTOM, 0 , 0);
            /*  Custom toast control, with an animation effect
             *  It solves the problem that native toast cannot be updated quickly
             *  But it doesn't get rid of the call of native toast display method */
            case R.id.btn_custom_smile:
                ToastUtils.showToast This is "looking at me", true;
            case R.id.btn_custom_smile2:
                ToastUtils.showToast (this, "= = still looking at me = =, true);

The corresponding layout code is relatively simple, so it will not be pasted

Here is the layout of the fourth effect

Next is the custom control part of the code

public class CustomToast extends View {
     *Initialize some variables
     *Implement three constructors
     *Initializes brush and rectangle parameters
     *Set the parameters of the brush and rectangle
     *Override onmeasure: the onmeasure() method is mainly responsible for measuring and determining the width and height of the control itself or its child controls
     *Rewrite OnDraw: OnDraw () method is responsible for drawing, that is, if the effect we want to get does not have ready-made support in Android native controls, then we need to draw the display effect of our own custom controls.
     *Realization of animation effect in custom view
    private Toast toast;
    private Context context;
    Rectf rectf = new rectf(); // rectangle, used when setting toast layout
    Valueanimator; // property animation
    Private paint paint; // customize the brush of view
    float mAnimatedValue = 0f;
    Private float mwidth = 0f; // width of view
    Private float mpadding = 0f; // inner margin of view
    private float endAngle  =  0f ;    // The degree of the end of an arc
    Private float meyewidth = 0f; // eye radius of smiling face
    private boolean isSmileLeft = false;
    private boolean isSmileRight = false;
    public CustomToast(Context context){
        this.context = context;
    public CustomToast(Context context, AttributeSet attrs){
        super(context, attrs);
        this.context = context;
    public CustomToast(Context context, AttributeSet attrs, int defStyleAttr){
        super(context, attrs, defStyleAttr);
        this.context = context;
    private void initPaint(){
        paint = new Paint();
        paint . setAntiAlias ( true );   // Anti-Aliasing 
        paint.setStyle ( Paint.Style.STROKE ); // brush style: Hollow
        paint . setColor ( Color . parseColor ("# 5cb85c "));    // The color of the drawing
        paint.setStrokeWidth (dip2px (2)); // set the thickness of the brush
    private void initRect(){
        rectF = new RectF(mPadding, mPadding, mWidth-mPadding, mWidth-mPadding);
    //Dip to PX. In order to support multi-resolution mobile phone
    public int dip2px(float dpValue){
        final float scale = getContext().getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        Mwidth = getmeasuredwidth(); // width of view
        mPadding = dip2px(10);
        mEyeWidth = dip2px(3);
    // Each time you touch the custom view / OnDraw will be triggered in ViewGroup () method
    protected void onDraw(Canvas canvas) {
        canvas.drawArc (rectf, 180, endangle, false, paint); // draw a smile arc
        paint.setStyle ( Paint.Style.FILL ); // brush style: solid
        if (isSmileLeft){
            canvas.drawCircle (mpadding + meyewidth + meyewidth / 2, mwidth / 3, meyewidth, paint); // draw circle
        if (isSmileRight){
            canvas.drawCircle(mWidth-mPadding-mEyeWidth-mEyeWidth/2, mWidth/3, mEyeWidth, paint);
    //Open animation
    public void startAnimator(boolean playAnimate){
        if (playAnimate){
            startViewAnim(0f, 1f, 2000);
    //Stop Animation
    public void stopAnimator(){
        if (valueAnimator != null){
            isSmileLeft = false;
            isSmileRight = false;
            mAnimatedValue = 0f;
     *Start animation
     *@ param start starting value
     *End value of @ param end
     *Time of @ param time animation
     * @return
    public ValueAnimator startViewAnim(float start, float end, long time){
        valueAnimator =  ValueAnimator.ofFloat (start, end); // set the start and end values of valueanimator
        valueAnimator.setDuration (time); // set animation time
        valueAnimator.setInterpolator (new linear interpolator()); // set the interpolator to control the change rate of animation
        valueAnimator.addUpdateListener (new  ValueAnimator.AnimatorUpdateListener () {// set the listener. Monitor the change of animation value and make the corresponding way
            public void onAnimationUpdate(ValueAnimator animation) {
                mAnimatedValue = (float) valueAnimator.getAnimatedValue();
                if (mAnimatedValue < 0.5){
                    isSmileLeft = false;
                    isSmileRight = false;
                    endAngle = -360 * (mAnimatedValue);
                } else if (mAnimatedValue > 0.55 && mAnimatedValue < 0.7){
                    endAngle = -180;
                    isSmileLeft = true;
                    isSmileRight = false;
                } else{
                    endAngle = -180;
                    isSmileLeft = true;
                    isSmileRight = true;
                Postvalidate(); // redraw
        if (!valueAnimator.isRunning()){
        return valueAnimator;
     *In essence, it relies on the display method of Android native toast,
     *Only the introduction of a custom layout, add a custom animation
    public void show(String message, boolean playAnimate){
        /*Solve the problem that the prompt does not disappear after repeatedly clicking toast*/
        if (toast == null){
            toast = new Toast(context);
        View customToastView = LayoutInflater.from(context).inflate(R.layout.toast_custom, null);
        TextView msg2 = (TextView) customToastView.findViewById(R.id.tv_msg);
        ImageView img2 = (ImageView) customToastView.findViewById(R.id.iv_img);
//        img2.setVisibility(View.GONE);
        CustomToast customToast = (CustomToast) customToastView.findViewById(R.id.smileView);
        toast.setGravity(Gravity.BOTTOM, 0 , 0);

Finally, paste the tool class shared by effect 1 and effect 4, mainly to solve the problem of continuously clicking toast and displaying it all the time. Add a point: effect 4 is still displayed based on the original toast display method of the system, so the problem of continuous click display still exists. Try not to use this method later.

public class ToastUtils {
    private static Toast toast;
    private static CustomToast customToast;
     *Customize the display of customtoast
     * @ Param context
     *@ param message prompt content
     *Does @ param playanimation display animation true, false and not
    public static void showToast(Context context, String message, boolean playAnimate){
        if (customToast == null){
            customToast = new CustomToast(context);
        customToast.show(message, playAnimate);
     *The display of Android native toast mainly solves the problem of prompt as many times as possible
    public static void showToast(Context context, String content){
        if (toast == null){
            toast = Toast.makeText(context, content, Toast.LENGTH_SHORT);
        } else {

OK, complete, novice learning report~