在Android 11(API 30)上,Toast.getView()返回null。

37

我刚刚在模拟器中安装了 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"

有新的方法可以做到吗??


9
这是有意而为之的-现在已经停用了烤面包片的修改功能,您只能显示原始文本:https://developer.android.com/preview/features/toasts - Pawel
1
@Pawel 好眼力。getView 现在返回 null。 - guipivoto
@Pawel Ok,toast修改已被弃用。因此,是否想要使用一个,有没有禁用显示其图标的方法? - Jorge Luiz
6个回答

27
自从Android 11版本开始,自定义toast/ toast修改已被Google弃用,旨在“保护用户”。这就是为什么您的Android 30应用程序无法显示自定义toast的原因。
根据Android开发者文档: 自定义toast视图已被弃用。应用可以使用makeText(android.content.Context, java.lang.CharSequence, int)创建标准文本toast。

1
虽然它被标记为过时,但只要你不尝试从后台显示自定义toast,你仍然可以使用它。 - user2288580

8

您可以在自定义提示消息之前进行检查

    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();

这应该是 <=,而不是 <,对吧? - Mattwmaster58
toast.getView已被弃用。 - Taslim Oseni
1
@Mattwmaster58 不,那是正确的。因为它自 Android 11 起已被弃用。 - Majid RigiZadeh

7

@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();
    }

布局如下:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/text"
    />

</androidx.constraintlayout.widget.ConstraintLayout>

1
我有一个应用程序广泛使用Toast。当我将其迁移到Android 11时,我采用了这种方法。对我来说效果非常好。谢谢。 - dazed
1
你能提供“custom_toast”的布局吗? - Mattwmaster58
@Mattwmaster58 布局文件已添加。 - Ajay Makwana

7

我发现从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);  

结果
结果


你能添加截图吗? - t0m
1
现在您可以根据需要自定义TextView或Toast的背景。 - Seigel
可以从正在运行的后台服务中调用这个吗? - t0m
1
很抱歉,这样做只会在包含它的活动处于活动状态时显示“toast”。 - Seigel
如果显示另一个新的对话框片段,这个 Toast 是否会持续存在?例如:playFragment.show(AppContext.supportFragmentManager()!!,"play")。 - Krešimir Prcela

3

API等级30中,使用自定义view的解决方案已被弃用。

文档说明如下:

该方法已在API级别30中被弃用。自定义toast视图也已被弃用。应用程序可以使用makeText(android.content.Context,java.lang.CharSequence,int)方法创建标准文本toast或者在前台使用Snackbar。从Android Build.VERSION_CODES#R开始,针对API级别Build.VERSION_CODES#R或更高版本的后台应用程序将无法显示自定义toast视图。

然而,仍有一种解决方法可以正常工作且未被弃用。

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'>


只是改变文本,那背景呢? - Mori

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接