Android 原生自定义toast的简单实现
一,需求分析
1,装toast组件容器需要为一个从上往下进行布局的内容
2,toast组件添加后需要播放消失动画
消失动画的表现方式
1,布局往上推,然后缓慢变透明直至消失
2,消失过程中,后加入的toast位置随着逐渐消失的toast的位置改变而跟着改变
二,代码实现
1,布局,就一个按钮
<?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
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
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
<?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

浙公网安备 33010602011771号