安卓开发-Toast使用详解

Toast使用详解

​ Toast(吐司):一个提示信息的控件:在屏幕中显示一个消息提示框,没任何按钮, 也不会获得焦点,一段时间过后自动消失。

常规用法

Toast.makeText(MainActivity.this, "提示的内容", Toast.LENGTH_LONG).show(); 
// Toast.makeText()只是创建出来一个Toast对象,后面需要接上show()方法才能展示出来
// makeText()方法参数:第一个是上下文对象, 第二个是显示的内容,第三个是显示的时间长短,只有LONG和SHORT两个值可选

通过setGravity()方法设置其显示的位置

Toast toast = Toast.makeText(MainActivity.this, "test -- ", Toast.LENGTH_SHORT);
//设置gravity属性,以改变默认位置
toast.setGravity(Gravity.BOTTOM | Gravity.RIGHT, 0, 0);
toast.show();

​ 其中Gravity表示重力值,常见的有四个值:TOP、BOTTOM、LEFT(较新的API中为START)、RIGHT(较新的API中为END);分别对应屏幕的上下左右边缘。后面两个参数是xOffset 和 yOffset ,表示相对于边缘的偏移量。

注意:Toast.setGravity()方法的使用在API>=30时增加了限制:

在这里插入图片描述

​ 意思就是,当targetSdk>=30时,针对text toast(即使用Toast.makeText()创建出来的默认Toast),setGravity()方法将不会有任何效果,但是自定义的Toast不受影响。

自定义Toast

​ 如果上面的改动还满足不了你的需求,那么你完全可以自己写一个Toast的布局,示例如下:

自定义Toast布局:view_toast_custom.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/iv_logo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

    <TextView
        android:id="@+id/tv_msg"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</LinearLayout>

MainActivity.java:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.btn_show).setOnClickListener(view -> customerToast());
    }

    private void customerToast() {
        LayoutInflater inflater = getLayoutInflater();
        // 加载自定义布局
        View view = inflater.inflate(R.layout.view_toast_custom, null);
        ImageView imgLogo = view.findViewById(R.id.iv_logo);
        TextView tvMsg = (TextView) view.findViewById(R.id.tv_msg);
        imgLogo.setImageResource(R.mipmap.ic_launcher);
        tvMsg.setText("customer toast");
        // 创建一个Toast对象,传递当前Context上下文即可
        Toast toast = new Toast(this);
        // 设定Toast位置居中
        toast.setGravity(Gravity.CENTER, 0, 0);
        // 设定显式时间长短
        toast.setDuration(Toast.LENGTH_LONG);
        // 通过setView()方法来设定Toast的View
        toast.setView(view);
        // 显式自定义Toast
        toast.show();
    }
}

在targetSdk=32上测试效果:

在这里插入图片描述

注意:targetSdk>=30时,在Toast.setView()方法头部有注释:

在这里插入图片描述

「Deprecated」 表示该功能目前仍可以使用,但可能会在将来的 Android 版本中删除。 建议开发人员避免长期使用此功能。
目前是 targetSdkVersion 为 R 或更高的 app 禁止后台弹出自定义 Toast,同时将 setView() 方法标记弃用,当该方法从源码中移除后,自定 Toast 的方式将被彻底禁用,这也可以看出,官方在一步步禁止自定义 Toast。当然,官方提供了相应的替代品,使用 Snackbar

修改Toast原生样式

​ 有时候不想自定义一个新的Toast,只是想修改Toast文字的颜色或者字体,这个时候可以在原生Toast样式上做修改。在修改前我们先看下Toast原生样式的代码:

<!--Android\Sdk\platforms\android-32\data\res\layout\transient_notification.xml-->
<?xml version="1.0" encoding="utf-8"?>
<!--
/* //device/apps/common/res/layout/transient_notification.xml
**
** Copyright 2006, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
-->

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:gravity="center_vertical"
    android:maxWidth="@dimen/toast_width"
    android:background="?android:attr/toastFrameBackground"
    android:elevation="@dimen/toast_elevation"
    android:layout_marginEnd="16dp"
    android:layout_marginStart="16dp"
    android:paddingStart="16dp"
    android:paddingEnd="16dp">

    <TextView
        android:id="@android:id/message"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:ellipsize="end"
        android:maxLines="2"
        android:paddingTop="12dp"
        android:paddingBottom="12dp"
        android:textAppearance="@style/TextAppearance.Toast"/>
</LinearLayout>

从Toast布局中可以看到,TextView的id是message,所以我们可以通过id获取TextView对象,从而做修改:

// SDK targetVersion为29
private void testDefaultToast(){
    // 创建一个Toast对象
    Toast toast = Toast.makeText(this,"xxxx", Toast.LENGTH_SHORT);
    // 通过id获取TextView对象
    TextView textView = toast.getView().findViewById(android.R.id.message);
    Log.d(TAG, "testDefaultToast: " + textView.getText().toString());
    // 设置TextView的颜色
    textView.setTextColor(Color.RED);
    // 设置字体为粗体
    Typeface typeface = Typeface.create("sans-serif-condensed", Typeface.BOLD);
    textView.setTypeface(typeface);
    // 设置Toast位置在顶部
    toast.setGravity(Gravity.TOP,0 ,0);
    // 显式Toast
    toast.show();
}

在targetSdk=29上的运行效果:

在这里插入图片描述

注意:上面的示例是在targetSdk<=29的情况下才能正常运行,当targetSdk>=30时,在代码中可以发现有如下提示:

在这里插入图片描述

​ 翻译过来意思大概是:用Toast(Context)构造出来的Toast,如果没有先调用setView()方法传入一个非空View,那么在这里将返回null。在API Build.VERSION_CODES.R或更高版本中,使用makeText(Context, CharSequence, int)或其变体构造出来的toast,在这里也将返回null,除非它们使用非空视图调用了setView(View)。

​ 简单来说就是,在API>=30时,创建Toast对象时,如果没有事先调用setView()传入一个非空的View,那么在下面使用getView()方法时,将不能获取Toast对象里的View,而是会返回null。所以如果targetSdk>=30时,是无法通过getView()获取原生Toast的View来进行自定义修改的。

如果将上面的代码在targetSdk>=30中运行,那么在这行的位置将会报错:

// 在这里会空指针异常,因为toast.getView()返回的是null
TextView textView = toast.getView().findViewById(android.R.id.message);
  • 30
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值