Android12-Toast behavior change + bottom navigation bar adaptation

foreword

The thing is like this, because we are making game products, and there are new instructions on the restrictions related to the underage policy, so after the interface is changed on the server side, there is an adaptation problem on the front end, which will greatly affect the UI.

 Hey, using Toast to display long text, why the display is incomplete.

After a search, it turned out that Google made adjustments after Android 12, targetSdkVersion>31.

 For the display of long text, it is not recommended to use Toast, but there is no other way, and I can't explain it to the project team. It is not appropriate to use pop-up windows, so I can only think about adaptation. Since there are other implementation methods If it doesn’t work, then find a way, customize Toast?

That's right, after all Toast provides the setView method, just make a layout and put it in. Paste the code directly here

import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.os.Build;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;
import android.widget.Toast;

public class BToast extends Toast {
    private BToast(Context context) {
        super(context);
    }
    private static BToast toast;
    private static void cancelToast() {
        //为什么把这个if语句去掉,就会异常终止呢?
        //因为程序第一次进来时, toast时为空的,第二次及以后, 它才不为空,才能执行toast.cancel()。
        if (toast != null) {
            toast.cancel();
        }
    }
    public void cancel() {
        super.cancel();
    }
    public void show() {
        super.show();
    }

    public static void initToast( Context context, CharSequence text,boolean NavigationBar) {
        //第二次点击及以后,它会先取消上一次的Toast, 然后show本次的Toast。
        cancelToast();
        toast = new BToast(context);

        View mView = LayoutInflater.from(context).inflate(RGet.$L("tc_activity_toast"), null);
        TextView mText = mView.findViewById(RGet.$ID("toast_show"));
        mText.setText(text);
        toast.setView(mView);
        int  height =  0;
        if(NavigationBar){
            height =  getNavigationBarHeight(context)/2;
        }
        Log.d("BToast",height+"");
        toast.setGravity(Gravity.TOP, -height, 70);
        toast.setDuration(Toast.LENGTH_LONG);
        toast.show();
    }

    //屏幕高度
    public  static int getHeight(Activity activity) {
        DisplayMetrics dm = new DisplayMetrics();
        WindowManager windowManager = (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE);
        windowManager.getDefaultDisplay().getMetrics(dm);
        return dm.widthPixels;
    }

    //真实高度
    public static int getRealHeight(Activity activity) {
        WindowManager windowManager = (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE);
        Display display = windowManager.getDefaultDisplay();
        DisplayMetrics dm = new DisplayMetrics();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            display.getRealMetrics(dm);
        } else {
            display.getMetrics(dm);
        }
        int realHeight = dm.widthPixels;
        return realHeight;
    }



    public static int getNavigationBarHeight(Context context) {
        Resources resources = context.getResources();
        int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
        return resourceId != 0 ? resources.getDimensionPixelSize(resourceId) : 0;
    }

layout layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/toast_backgound"
    >
    <TextView
        android:id="@+id/toast_show"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:padding="8dp"
        android:text=""
        android:textColor="#000000"
        android:gravity="center"
        android:textSize="14sp" />
</LinearLayout>

 toast_backgound.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <corners android:radius="10dp"/>
    <solid android:color="#ffffffff"/>
</shape>

transfer

BToast.initToast(this,"",isshowNavigationBar);

 

It's that simple, but it's not over yet. The display of the text is too long is solved, but you will find that on the mobile phone with the bottom navigation bar, the View of the Toast is not centered. This... Then check the information and find that the bottom navigation bar adaptations searched online also return all True, with or without it, it's a pain in the ass. After reading this big guy's blog, I finally found a solution.

https://blog.csdn.net/qq_20451879/article/details/79109501

Bottom Virtual Navigation Bar

Whether there is a virtual button

注意:指的是当前手机是否设置有虚拟按键!而不是指虚拟按键是否显示!

 public static boolean isHaveSoftKey(Activity activity) {
     Display d = activity.getWindowManager().getDefaultDisplay();
     DisplayMetrics realDisplayMetrics = new DisplayMetrics();
     d.getRealMetrics(realDisplayMetrics);
     int realHeight = realDisplayMetrics.heightPixels;
     int realWidth = realDisplayMetrics.widthPixels;
     DisplayMetrics displayMetrics = new DisplayMetrics();
     d.getMetrics(displayMetrics);
     int displayHeight = displayMetrics.heightPixels;
     int displayWidth = displayMetrics.widthPixels;
     return (realWidth - displayWidth) > 0 || (realHeight - displayHeight) > 0;
 }

The height of the bottom virtual button

 public static int getBottomSoftKeysHeight(Activity activity) {
     Display d = activity.getWindowManager().getDefaultDisplay();
     DisplayMetrics realDisplayMetrics = new DisplayMetrics();
     d.getRealMetrics(realDisplayMetrics);
     int realHeight = realDisplayMetrics.heightPixels;
     DisplayMetrics displayMetrics = new DisplayMetrics();
     d.getMetrics(displayMetrics);
     int displayHeight = displayMetrics.heightPixels;
     return (realHeight - displayHeight);
 }

Hide, show - bottom virtual navigation bar

  /**
     * @param state   true 隐藏  false 还原显示
     */
    public static void hideBottomMenu(Context context,boolean state){
        Intent barIntent = new Intent();
        barIntent.setAction("com.alf.switch_status_bar");
        barIntent.putExtra("hide", state);
        context.sendBroadcast(barIntent);
    }
————————————————
版权声明:本文为CSDN博主「Modu_Liu」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_20451879/article/details/79109501

Hide - bottom virtual navigation bar

    private void hideBottomMenu() {
        int flags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
                View.SYSTEM_UI_FLAG_FULLSCREEN |
                View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
                View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |
                View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
        View decorView = getWindow().getDecorView();
        decorView.setSystemUiVisibility(flags);
    }

Hide - bottom virtual navigation bar

隐藏底部虚拟按键,但是如果你在底部网上滑动还是显示的出来的

    private void hideBottomMenu() {
        //android 隐藏底部虚拟按键
        //隐藏虚拟按键,并且全屏
        if (Build.VERSION.SDK_INT > 11 && Build.VERSION.SDK_INT < 19) { // lower api
            View v = this.getWindow().getDecorView();
            v.setSystemUiVisibility(View.GONE);
        } else if (Build.VERSION.SDK_INT >= 19) {
            //for new api versions.
            View decorView = getWindow().getDecorView();
            int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
                    | View.SYSTEM_UI_FLAG_FULLSCREEN;
            decorView.setSystemUiVisibility(uiOptions);
        }
    }

关于这个功能我在网上找了很多半成品,大部分都无效,所幸拼拼凑凑实现了此项功能,亲测可用!

Paste the code below.

NavigationActivity
建议:可以将NavigationActivity的关键代码移植到我们项目的BaseActivity,同时此类中的一些Log完全可以删掉,这里打Log只是为了看一些执行流程 ~


import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;

public class NavigationActivity extends Activity implements ViewTreeObserver.OnGlobalLayoutListener {
    FrameLayout content;
    private static final String TAG = "BaseActivityForAuto";
    private boolean mLayoutComplete = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        content = (FrameLayout) findViewById(android.R.id.content);
        content.post(new Runnable() {
            @Override
            public void run() {
                mLayoutComplete = true;
                Log.e(TAG, "content 布局完成");
            }
        });
        content.getViewTreeObserver().addOnGlobalLayoutListener(NavigationActivity.this);
    }


    @Override
    public void onGlobalLayout() {
        Log.e(TAG, "onGlobalLayout");
        if (!mLayoutComplete)
            return;
        onNavigationBarStatusChanged();
    }

    protected void onNavigationBarStatusChanged() {
        // 子类重写该方法,实现自己的逻辑即可。
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        content.getViewTreeObserver().removeOnGlobalLayoutListener(this);
    }
}

MainActivity
此处的MainActivity替代到对应的需求类即可,但是要记得继承上方的父类 - - ~

因为我们的游戏是横屏,所以这里的判断高度,实质上是宽度。

import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.WindowManager;

public class MainActivity extends NavigationActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    boolean isshowNavigationBar = true;

    @Override
    protected void onNavigationBarStatusChanged() {
        super.onNavigationBarStatusChanged();
        int displayWidth = BToast.getHeight(this)+BToast.getNavigationBarHeight(this);
        int basicWidth = BToast.getRealHeight(this);
        Log.e("tag", "宽度" + displayWidth);
        Log.e("tag", "真实宽度" + basicWidth);
        if (displayWidth < basicWidth) {
            isshowNavigationBar = true;
            Log.e("tag", "底部导航显示");
        } else {
            isshowNavigationBar = false;
            Log.e("tag", "底部导航隐藏");
        }
    }
}

Summarize

Through this small problem, I found that with the update of the Android version, many changes have taken place in the behavior, and it is still necessary to keep pace with the times. There are many articles on the Internet about the adaptation of the bottom navigation bar, but after a try, I found that they all have the same effect, which is not very useful, and my business may not be consistent with the other party's. In short, I still want to thank the big brother Modu_Liu for allowing me to successfully solve the problem. respect!

Guess you like

Origin blog.csdn.net/qq_34123324/article/details/131230802