Toast.getView() returns 在 Android 11 (API 30) 上为空

Toast.getView() returns null on Android 11 (API 30)

我刚刚在模拟器中安装了 Android R (API 30) 图像来试用我的应用程序,但在尝试设置 Toast 的背景颜色时它崩溃了。

    Toast toast = Toast.makeText(ctxt, msg, duration);
    View view = toast.getView();
    view.setBackgroundColor(0xFF303030);
    TextView tview = view.findViewById(android.R.id.message);
    tview.setTextColor(Color.WHITE);
    toast.show();

这真的很奇怪,因为 Android Q (API 29) 工作得很好。

我的 build.gradle 更新为 Android R (API 30)

    compileSdkVersion 30
    buildToolsVersion "30.0.1"

有新的方法吗??

自 Android 11 起,根据 Google“保护用户”,自定义 toasts/toast 修改已弃用。因此,为什么您在 Android 30 中的应用无法显示自定义祝酒词。

来自 Android 开发者文档:

Custom toast views are deprecated. Apps can create a standard text toast with the makeText(android.content.Context, java.lang.CharSequence, int)

我发现从 API 30 开始显示自定义 toast 的唯一方法是临时创建它们。

XML 布局
根据需要自定义

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
  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=".main_activity">



        <!--Ad hoc toast Textview-->
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="12dp"
            android:layout_margin="18dp"
            android:background="@drawable/ad_hoc_toast_background"
            android:textColor="#1e1e1e"
            android:gravity="center"
            android:visibility="gone"
            android:layout_alignParentBottom="true"
            android:id="@+id/ad_hoc_toast_textview"
            tools:text="Temporary message bla bla bla ..."/>



</RelativeLayout>

吐司背景 (ad_hoc_toast_background.xml)
根据需要自定义

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
    <shape
             xmlns:android="http://schemas.android.com/apk/res/android"
             android:shape="rectangle">

        <size
                 android:width="220dp"
                 android:height="100dp"/>
        <corners
                 android:radius="25dp"
            />

        <solid
                 android:color="#e6ffffff"
            />
    </shape>
</item>
</selector>

定义show_ad_hoc_toast()方法

private void show_ad_hoc_toast(final TextView ad_hoc_toast_textview, String text){


    //Set the text
    ad_hoc_toast_textview.setText(text);


    //Create alpha animation
    AlphaAnimation animation1 = new AlphaAnimation(0f, 1f);

    //Set duration
    animation1.setDuration(300);

    //Set that the animation changes persist once the animation finishes
    animation1.setFillAfter(true);


    //Set on AnimationEnd Listner
    animation1.setAnimationListener(new Animation.AnimationListener() {

        @Override public void onAnimationStart(Animation animation){}
        @Override public void onAnimationRepeat(Animation animation){}
        @Override public void onAnimationEnd(Animation animation){

            //After 2250 millis -> hide the toast
            new CountDownTimer(2250, 1) {
                public void onTick(long millisUntilFinished){}
                public void onFinish() {hide_ad_hoc_toast(ad_hoc_toast_textview);}
            }.start();


        }

    });


    //Make the view visible
    ad_hoc_toast_textview.setVisibility(View.VISIBLE);


    //Start animation
    ad_hoc_toast_textview.startAnimation(animation1);


}

定义hide_ad_hoc_toast()方法

private void hide_ad_hoc_toast(final TextView ad_hoc_toast_textview){


    //Create alpha animation
    AlphaAnimation animation1 = new AlphaAnimation(1f, 0f);

    //Set duration
    animation1.setDuration(300);

    //Set that the animation changes persist once the animation finishes
    animation1.setFillAfter(true);


    //Set on AnimationEnd Listner
    animation1.setAnimationListener(new Animation.AnimationListener() {

        @Override public void onAnimationStart(Animation animation) { }
        @Override public void onAnimationRepeat(Animation animation) { }
        @Override public void onAnimationEnd(Animation animation) {

            //Make the view gone
            ad_hoc_toast_textview.setVisibility(View.GONE);

        }

    });



    //Start animation
    ad_hoc_toast_textview.startAnimation(animation1);



}

需要时从代码中调用方法

//Find ad_hoc_toast textview
TextView ad_hoc_toast_textview = findViewById(R.id.ad_hoc_toast_textview);

//Define the text to be shown
String text = "This is the custom toast message"

//Show the ad_hoc toast
show_ad_hoc_toast(ad_hoc_toast_textview, text);  

结果

自定义toast之前可以查看

    Toast toast = Toast.makeText(ctxt, msg, duration);
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
        View view = toast.getView();
        view.setBackgroundColor(0xFF303030);
        TextView tview = view.findViewById(android.R.id.message);
        tview.setTextColor(Color.WHITE);
    }
    toast.show();

Toast 上设置自定义 view 的解决方案已弃用 API 级别 30

文档说

This method was deprecated in API level 30. Custom toast views are deprecated. Apps can create a standard text toast with the makeText(android.content.Context, java.lang.CharSequence, int) method, or use a Snackbar when in the foreground. Starting from Android Build.VERSION_CODES#R, apps targeting API level Build.VERSION_CODES#R or higher that are in the background will not have custom toast views displayed.

有一个解决方法仍然有效并且没有被弃用

Toast.makeText(applicationContext,
                HtmlCompat.fromHtml("<font color='red'>custom toast message</font>", HtmlCompat.FROM_HTML_MODE_LEGACY),
                Toast.LENGTH_LONG).show()

Html色标也可以是<font color='#ff6347'>

@pvalle & @Aayush Panda,它适用于我 Android 11。请检查下面的代码

public static void showCenterToastMessage(Context context, String msg) {
        LayoutInflater inflater = LayoutInflater.from(context);
        View layout = inflater.inflate(R.layout.custom_toast,null);
        TextView text = (TextView) layout.findViewById(R.id.text);
        text.setText(msg);
        text.setPadding(20,0,20,0);
        text.setTextSize(18);
        text.setTextColor(Color.WHITE);
        Toast toast = new Toast(context);
        toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
        toast.setDuration(Toast.LENGTH_LONG);
        layout.setBackgroundColor(Color.DKGRAY);
        toast.setView(layout);
        toast.show();
    }