如何制作自定义Toast布局以在Android中真正填满全屏?

时间:2016-05-27 00:35:22

标签: android android-toast

我的Android应用程序中的自定义Toast设计面临一点问题。

我在notifications_info.xml中定义了这样的toast XML(仅在此处简化为背景):

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/Fifty_Percent_Black"
    android:gravity="center"
>
    <!-- Centered round-corner background, text and icon here -->
</RelativeLayout>

我这样使用它:

// Load the XML layout using inflater
notificationLayout = inflater.inflate(R.layout.notifications_info, aParentView, false);
// Create the toast message
Toast notification = new Toast(App.context);
// Get the associated TextView
TextView notificationText = (TextView) notificationLayout.findViewById(R.id.Notification_Message);
// Set the text from the provided argument
notificationText.setText(aText);
// Finalize the message
notification.setView(notificationLayout);
notification.setGravity(Gravity.FILL, 0, 0);
notification.setDuration(Toast.LENGTH_SHORT);
notification.show();

除了一件事之外,一切都按预期工作......如下面的屏幕截图所示,我的toast背景并未涵盖状态和导航栏不在全屏时的空间(尽管我设置了我的应用程序)全屏使用沉浸式粘性模式)​​。

Top and bottom parts should be covered by toast background as well!

在这里,我们可以在我的应用程序的顶部和底部看到2个更明亮的“条形图”,它们不应该是明亮的,但是有50%的半透明黑色图层(如截图的其余部分)。那么请问您如何解决这个问题呢?

度过愉快的一天。

2 个答案:

答案 0 :(得分:1)

我遇到了同样的问题,但无法实现。我认为唯一的方法是通过更改android源代码来处理显示Toast,请参阅Toast.java中的以下代码。

private static class TN extends ITransientNotification.Stub {
    final Runnable mShow = new Runnable() {
        @Override
        public void run() {
            handleShow();
        }
    };

    ...
    TN() {
        // XXX This should be changed to use a Dialog, with a Theme.Toast
        // defined that sets up the layout params appropriately.
  

在我看来,他们正计划添加该功能以允许用户调整吐司的主题,但还没有

        final WindowManager.LayoutParams params = mParams;
        params.height = WindowManager.LayoutParams.WRAP_CONTENT;
        params.width = WindowManager.LayoutParams.WRAP_CONTENT;
        params.format = PixelFormat.TRANSLUCENT;
        params.windowAnimations = com.android.internal.R.style.Animation_Toast;
        params.type = WindowManager.LayoutParams.TYPE_TOAST;
        params.setTitle("Toast");
        params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                       | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                       | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
  

添加以下行可能可以使吐司尊重全屏模式

  | WindowManager.LayoutParams.FLAG_FULLSCREEN

    }

    /**
     * schedule handleShow into the right thread
     */
    @Override
    public void show() {
        if (localLOGV) Log.v(TAG, "SHOW: " + this);
        mHandler.post(mShow);
    }

    /**
     * schedule handleHide into the right thread
     */
    @Override
    public void hide() {
        if (localLOGV) Log.v(TAG, "HIDE: " + this);
        mHandler.post(mHide);
    }

    public void handleShow() {
        if (localLOGV) Log.v(TAG, "HANDLE SHOW: " + this + " mView=" + mView
                                  + " mNextView=" + mNextView);
        if (mView != mNextView) {
            // remove the old view if necessary
            handleHide();
            mView = mNextView;
            Context context = mView.getContext().getApplicationContext();
            String packageName = mView.getContext().getOpPackageName();
            if (context == null) {
                context = mView.getContext();
            }
            mWM = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
            // We can resolve the Gravity here by using the Locale for getting
            // the layout direction
            final Configuration config = mView.getContext().getResources().getConfiguration();
            final int gravity = Gravity.getAbsoluteGravity(mGravity, config.getLayoutDirection());
            mParams.gravity = gravity;
            if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.FILL_HORIZONTAL) {
                mParams.horizontalWeight = 1.0f;
            }
            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.FILL_VERTICAL) {
                mParams.verticalWeight = 1.0f;
            }
            mParams.x = mX;
            mParams.y = mY;
            mParams.verticalMargin = mVerticalMargin;
            mParams.horizontalMargin = mHorizontalMargin;
            mParams.packageName = packageName;
            if (mView.getParent() != null) {
                if (localLOGV) Log.v(TAG, "REMOVE! " + mView + " in " + this);
                mWM.removeView(mView);
            }
            if (localLOGV) Log.v(TAG, "ADD! " + mView + " in " + this);
            mWM.addView(mView, mParams);
            trySendAccessibilityEvent();
        }
    }

修改

另一个选择是使用对话框或类似的东西创建自己的Toast实现,它具有以下功能:

  1. 与用户触摸事件不对应
  2. 不拦截窗口中的用户触摸事件
  3. 将在一段时间后解雇
  4. 显示多个祝酒词排队
  5. 我最终放弃了,因为我认为这不值得付出努力。从用户体验的角度来看,吐司的使用应该不那么中断,但你的设计是让吐司占据整个屏幕而已经失败了。您可能想重新审视您的设计:您是否必须使用吐司?为什么不只是简单地创建一个从用户点击或一段时间后解雇自己的对话框?

答案 1 :(得分:0)

也许你需要全屏显示你的应用程序。我认为这两个明亮的区域是导航栏和状态栏。

在UI线程中尝试此方法。

protected void hideSystemUI() {
    // Set the IMMERSIVE flag.
    // Set the content to appear under the system bars so that the content
    // doesn't resize when the system bars hide and show.
    getWindow().getDecorView().setSystemUiVisibility(
            View.SYSTEM_UI_FLAG_IMMERSIVE
                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
                    |  View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
}

希望这可以帮到你。