Android 原生自定义toast的简单实现

一,需求分析

1,装toast组件容器需要为一个从上往下进行布局的内容
2,toast组件添加后需要播放消失动画
消失动画的表现方式
1,布局往上推,然后缓慢变透明直至消失
2,消失过程中,后加入的toast位置随着逐渐消失的toast的位置改变而跟着改变

二,代码实现

1,布局,就一个按钮

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
 
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <Button
        android:id="@+id/test_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="测试"
        tools:ignore="MissingConstraints" />
 
</androidx.constraintlayout.widget.ConstraintLayout>

 

2,MainActivity.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package com.ahao.toastdemo;
 
import androidx.appcompat.app.AppCompatActivity;
 
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.View;
import android.widget.Button;
 
public class MainActivity extends AppCompatActivity {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        Button btn = findViewById(R.id.test_btn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Handler(Looper.getMainLooper()).post(new Runnable() {
                    @Override
                    public void run() {
                        ToastUtils.showToast(MainActivity.this, "你好啊你好啊", 1200);
                    }
                });
            }
        });
    }
}

  

3,ToastUtils.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package com.ahao.toastdemo;
 
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.view.Gravity;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;
 
import java.lang.ref.WeakReference;
 
public class ToastUtils {
    private static WeakReference<LinearLayout> toastLayoutRef;
 
    @SuppressLint({"RtlHardcoded", "UseCompatLoadingForDrawables"})
    public static void showToast(Context context, String content, int duration) {
        if (toastLayoutRef == null) {
            WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
            LinearLayout linearLayout = new LinearLayout(context);
            LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
            linearLayout.setLayoutParams(lp);
            linearLayout.setOrientation(LinearLayout.VERTICAL);
            WindowManager.LayoutParams winLp = new WindowManager.LayoutParams();
            winLp.gravity = Gravity.RIGHT | Gravity.CENTER_VERTICAL;
            winLp.type = WindowManager.LayoutParams.TYPE_APPLICATION;
            winLp.width = WindowManager.LayoutParams.MATCH_PARENT;
            winLp.height = WindowManager.LayoutParams.MATCH_PARENT;
            winLp.flags = WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
            winLp.format = PixelFormat.RGBA_8888;
            windowManager.addView(linearLayout, winLp);
            toastLayoutRef = new WeakReference<>(linearLayout);
            showToast(context, content, duration);
            return;
        }
        LinearLayout toastItem = new LinearLayout(context);
        toastItem.setHorizontalGravity(Gravity.CENTER_HORIZONTAL);
        LinearLayout.LayoutParams toastLp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 56);
        toastLp.setMargins(0,0,0, 16);
        toastItem.setLayoutParams(toastLp);
        TextView toastContent = new TextView(context);
        toastContent.setText(content);
        toastContent.setPadding(10, 10, 10, 10);
        toastContent.setMinWidth(200);
        toastContent.setHeight(56);
        toastContent.setGravity(Gravity.CENTER);
        toastContent.setBackground(context.getResources().getDrawable(R.drawable.toast_bg));
        toastContent.setTextColor(Color.parseColor("#FFFFFF"));
        toastItem.addView(toastContent);
        toastItem.animate()
                .setStartDelay(duration)
                .setDuration(1200)
                .alpha(0)
                .translationY(0)
                .setUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    private float oldHeight = 0;
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        float currentProgress = Float.parseFloat(animation.getAnimatedValue().toString());
                        if (oldHeight == 0){
                            oldHeight = toastItem.getMeasuredHeight();
                        }
                        LinearLayout.LayoutParams toastLP = (LinearLayout.LayoutParams) toastItem.getLayoutParams();
                        int newMarginBottom = (int) (-1 * currentProgress * oldHeight);
                        toastLP.setMargins(0,0,0,newMarginBottom);
                        toastItem.post(new Runnable() {
                            @Override
                            public void run() {
                                toastItem.setLayoutParams(toastLP);
                            }
                        });
                    }
                })
                .setListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        super.onAnimationEnd(animation);
                        toastLayoutRef.get().removeView(toastItem);
                    }
                })
                .start();
        toastLayoutRef.get()
                .addView(toastItem);
    }
}

  

  

4,toast_bg.xml

1
2
3
4
5
6
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="#000000"/>
    <corners android:radius="1000dp"/>
    <stroke android:color="#1d39c4" />
</shape>

  

三,演示

 

 

 

四,项目代码

https://gitee.com/UPUP0326/android-toast-demo

 

查看html 版本

posted @   Dmail  阅读(127)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
点击右上角即可分享
微信分享提示