在视图下方显示Toast小部件

9
感谢之前帮助我解决问题的人,非常感谢!我的代码已经没有任何问题,并且进行了额外的调整。现在应用程序实际上已经很强大了,我想再做一件事情。
这里查看 布局 的截图。
通常,Toast视图出现在屏幕底部中心。我想让它在 OnClick 调用后出现在“提交”按钮下方(8dp)。我该如何实现这一点?
在这里查看我 更新的完整项目
package com.lookjohn.guessnumber;

import java.util.Random;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends Activity {
Random random; 
Button button;
EditText text;

int input; 
int MIN, MAX;
int comp; 
int guesses;

public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    random = new Random();
    button = (Button)findViewById(R.id.button1);
    text = (EditText)findViewById(R.id.editText1);

    MIN = 1;
    MAX = 100;
    comp = random.nextInt(MAX - MIN + 1) + MIN; // Generate random number between 1 and 100.
    guesses = 0;

    button.setOnClickListener(myhandler1);
}

View.OnClickListener myhandler1 = new View.OnClickListener() {

    public void onClick(View v) {

        // Implemented max number of guesses, detect 
        // number of guesses and return from the method.

        String value = text.getText().toString(); // Get value from input from editTextView

        // If user submits an empty EditText, return to prevent a crash.
        if (value.isEmpty()) {
            Toast.makeText(MainActivity.this, "You must enter a guess!", Toast.LENGTH_SHORT);
            return;
        }

        input = Integer.parseInt(value); // Turn string into integer
        guesses++;
        if (input > 100) {
            Toast.makeText(MainActivity.this, 
                "That number is greater than 100. Not Valid!", 
                Toast.LENGTH_SHORT).show();
                return;
            }

        else if (input < comp)
            Toast.makeText(MainActivity.this, 
                "Your number is too small.", 
                Toast.LENGTH_SHORT).show();
        else if (input > comp) 
            Toast.makeText(MainActivity.this, 
                "Your number is too big.", 
                Toast.LENGTH_SHORT).show();
        else
            Toast.makeText(MainActivity.this, 
                "Good job! The answer was " + comp + ".\n" +
                "You made " + guesses + " guesses.\n" +
                "Restart the app to try again.", 
                Toast.LENGTH_LONG).show();
    }
};

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

}

1
关于代码风格的评论 - 你不应该在代码中嵌入字符串。这会阻止你的应用国际化。使用类似这样的字符串资源 getString(R.string.message); - Andrew Fielden
安德鲁:我明白了,感谢您的评论。我会立即修复它。 - jjkim
6个回答

19

android.widget.Toast定义了一些有用的方法,允许自定义toast通知的外观。你应该研究的方法是setGravity(int, int, int)。在偏移量都为0的情况下,以下代码将把toast顶部锚定到提供的视图底部,并将toast中心锚定到视图的中心。

public static void positionToast(Toast toast, View view, Window window, int offsetX, int offsetY) {
    // toasts are positioned relatively to decor view, views relatively to their parents, we have to gather additional data to have a common coordinate system
    Rect rect = new Rect();
    window.getDecorView().getWindowVisibleDisplayFrame(rect);
    // covert anchor view absolute position to a position which is relative to decor view
    int[] viewLocation = new int[2];
    view.getLocationInWindow(viewLocation);
    int viewLeft = viewLocation[0] - rect.left;
    int viewTop = viewLocation[1] - rect.top;

    // measure toast to center it relatively to the anchor view
    DisplayMetrics metrics = new DisplayMetrics();
    window.getWindowManager().getDefaultDisplay().getMetrics(metrics);
    int widthMeasureSpec = MeasureSpec.makeMeasureSpec(metrics.widthPixels, MeasureSpec.UNSPECIFIED);
    int heightMeasureSpec = MeasureSpec.makeMeasureSpec(metrics.heightPixels, MeasureSpec.UNSPECIFIED);
    toast.getView().measure(widthMeasureSpec, heightMeasureSpec);
    int toastWidth = toast.getView().getMeasuredWidth();

    // compute toast offsets
    int toastX = viewLeft + (view.getWidth() - toastWidth) / 2 + offsetX;
    int toastY = viewTop + view.getHeight() + offsetY;

    toast.setGravity(Gravity.LEFT | Gravity.TOP, toastX, toastY);
}

使用它需要在你的onClick方法中修改与 toast 相关的代码行:

int offsetY = getResources().getDimensionPixelSize(R.dimen.toast_offset_y);

Toast toast = Toast.makeText(MainActivity.this, "That number is greater than 100. Not Valid!", Toast.LENGTH_SHORT);
positionToast(toast, v, getWindow(), 0, offsetY);
toast.show();

1
toast.getView().measure(widthMeasureSpec, heightMeasureSpec); 这段代码很好,很聪明。谢谢。 - Maroloccio
这应该是被接受的答案,谢谢你,伙计。 - buradd
1
遗憾的是,在针对Android R时,toast.getView()将返回null:https://developer.android.com/reference/android/widget/Toast#getView()。是否有一个好的解决方法? - android developer

3

对我来说,以上的答案都没有解决我的问题,我结合了上面的答案,最终得到了解决方案。

图片描述

第二个计时器是目标视图。

 public static void displayToastUnderView(Activity activity, View view, String text) {
        Toast toast = Toast.makeText(activity, text, Toast.LENGTH_SHORT);
        toast.setGravity( Gravity.TOP, view.getLeft() - view.getWidth() / 2 - toast.getView().getWidth() / 2, view.getBottom());
        toast.show();
    }

如果视图位于底部,你会怎么做? - android developer

2

对于你的问题,如何在指定位置显示 Toast,可以这样做:

Toast toast = new Toast();
toast.setGravity(Gravity.TOP|Gravity.LEFT, 0, 0);
toast.makeText(getApplicationContextt(),"Text",Toast.LENGTH_SHORT);
toast.show();

您可以在这行代码中进行修改以更改toast的位置:-
    toast.setGravity(Gravity.TOP|Gravity.LEFT, 0, 0);

2
从开发者指南中,您可以使用toast.setGravity()方法来定位您的Toast。我在http://developer.android.com/guide/topics/ui/notifiers/toasts.html上找到了这个方法。
引用: 定位你的Toast 标准的Toast通知出现在屏幕底部,水平居中。您可以使用setGravity(int,int,int)方法更改此位置。它接受三个参数:Gravity常量、x位置偏移和y位置偏移。
例如,如果您决定Toast应该出现在左上角,您可以像这样设置重力: toast.setGravity(Gravity.TOP|Gravity.LEFT, 0, 0); 如果您想将其位置向右移动,增加第二个参数的值。要将其向下推,请增加最后一个参数的值。
我认为您可以获取按钮的位置并将其转发到上述方法中。

2
我想在solmaks的回答中补充一点内容。
在positionToast函数中:
    ...
    int toastHeight= toast.getView().getMeasuredHeight();

    // compute toast offsets
    ...
    int toastY = viewTop + (view.getHeight() - toastHeight) / 2 + offsetY;

in onClick:

    positionToast(toast, view, getWindow(), 0, 0);  

在我看来,这将完美地将Toast置于中心位置,无论该视图放置在哪里。我的代码假定Toast始终比其所在的视图小。


1

根据我的了解,这是我为该程序想出的最佳方案。这样做可以将Toast消息放置在手机屏幕中心。

if(input > 100) {   
            Toast toast = Toast.makeText(MainActivity.this, 
                R.string.over_guess, 
                Toast.LENGTH_SHORT);
            toast.setGravity(Gravity.CENTER, 0, 0); 
            toast.show();   
            return;
            }
        else if(input < comp) {
            Toast toast = Toast.makeText(MainActivity.this, 
                getString(R.string.guess_low, input), 
                Toast.LENGTH_SHORT);
            toast.setGravity(Gravity.CENTER, 0, 0); 
            toast.show();
        }
        else if(input > comp) {
            Toast toast = Toast.makeText(MainActivity.this, 
                getString(R.string.guess_high, input), 
                Toast.LENGTH_SHORT);
            toast.setGravity(Gravity.CENTER, 0, 0); 
            toast.show();
        }
        else {
            Toast toast = Toast.makeText(MainActivity.this, 
                getString(R.string.correct, comp, guesses), 
                Toast.LENGTH_LONG);
            toast.setGravity(Gravity.CENTER, 0, 0); 
            toast.show();
        }

在我的回答中,我提供了一种方法让你将一个toast相对于任何视图进行定位,这应该解决了你最初的问题。 - Maksim Solodovnikov

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