Java 制作一个没有视图的小吃店?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/38748294/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 20:35:45  来源:igfitidea点击:

Making a Snackbar Without a View?

javaandroidxmlcrashandroid-snackbar

提问by Kelvin Kellner

I want to show a snackbar as soon as the user opens the Google Maps activity, but the thing is that there's no views in the activity to use as the first parameter of the activity (in the findViewById()of Snackbar.make()). What do I put there? Here's the java class code:

我想在用户打开 Google Maps 活动后立即显示小吃店,但问题是活动中没有视图可用作活动的第一个参数(在findViewById()of 中Snackbar.make())。我在那里放什么?这是java类代码:

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {

private GoogleMap mMap;

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

    // Obtain the SupportMapFragment and get notified when the map is ready to be used.
    SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
            .findFragmentById(R.id.map);
    mapFragment.getMapAsync(this);
}

@Override
public void onMapReady(GoogleMap googleMap) {
    mMap = googleMap;
    mMap.setBuildingsEnabled(true);
    mMap.getUiSettings().setZoomControlsEnabled(true);
    float cameraZoom = 17;
    LatLng location = new LatLng(43.404032, -80.478184);
    mMap.addMarker(new MarkerOptions().position(location).title("49 McIntyre Place #18, Kitchener, ON N2R 1G3"));
    CameraUpdateFactory.newLatLngZoom(location, cameraZoom);
    Snackbar.make(findViewById(/*WHAT DO I PUT HERE?*/), "Click the pin for more options", Snackbar.LENGTH_LONG).show();
}
}

Also, here is the activity xml code:

此外,这里是活动 xml 代码:

<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="ca.davesautoservice.davesautoservice.MapsActivity" />

And lastly, here's the stacktrace error:

最后,这是堆栈跟踪错误:

08-03 11:42:21.333 3901-3901/? E/AndroidRuntime: FATAL EXCEPTION: main
    Process: ca.davesautoservice.davesautoservice, PID: 3901
    java.lang.NullPointerException
        at android.support.design.widget.Snackbar.<init>(Snackbar.java:183)
        at android.support.design.widget.Snackbar.make(Snackbar.java:215)
        at ca.davesautoservice.davesautoservice.MapsActivity.onMapReady(MapsActivity.java:48)
        at com.google.android.gms.maps.SupportMapFragment$zza.zza(Unknown Source)
        at com.google.android.gms.maps.internal.zzo$zza.onTransact(Unknown Source)
        at android.os.Binder.transact(Binder.java:361)
        at xz.a(:com.google.android.gms.DynamiteModulesB:82)
        at maps.ad.u.run(Unknown Source)
        at android.os.Handler.handleCallback(Handler.java:808)
        at android.os.Handler.dispatchMessage(Handler.java:103)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:5333)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:515)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:828)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:644)
        at dalvik.system.NativeStart.main(Native Method)

Thanks for the help! :)

谢谢您的帮助!:)

采纳答案by W0rmH0le

I see some options... Not sure which one can fix your issue.

我看到了一些选项...不确定哪一个可以解决您的问题。

Simpliest

最简单

SupportMapFragmentextends class android.support.v4.app.Fragment. This way, it has a method getView()

SupportMapFragment扩展类android.support.v4.app.Fragment。这样,它有一个方法getView()

Snackbar.make(mapFragment.getView(), "Click the pin for more options", Snackbar.LENGTH_LONG).show();

Find Root View

查找根视图

From this answer, there's a way to get the root view via:

从这个答案,有一种方法可以通过以下方式获取根视图:

getWindow().getDecorView().getRootView()

So, maybe, you can do:

所以,也许,你可以这样做:

Snackbar.make(getWindow().getDecorView().getRootView(), "Click the pin for more options", Snackbar.LENGTH_LONG).show();

NOTE:This approach has the side effect mentioned in the comments below:

注意:此方法具有以下评论中提到的副作用:

The message will be shown behind the bottom navigation bar if the following method will be used to get view getWindow().getDecorView().getRootView()

如果使用以下方法获取视图 getWindow().getDecorView().getRootView() 则消息将显示在底部导航栏后面

Add a dummy LinearLayout to get the View

添加一个虚拟的 LinearLayout 来获取视图

Honestly, I'm not sure if this solution is possible. I'm not sure if you can add a LinearLayout above the Maps fragment... I think it is OK but since I never work with Maps API before, I'm not sure.

老实说,我不确定这个解决方案是否可行。我不确定您是否可以在 Maps 片段上方添加 LinearLayout ......我认为这没问题,但因为我以前从未使用过 Maps API,所以我不确定。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/dummy_layout_for_snackbar"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <fragment 
        xmlns:map="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/map"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="ca.davesautoservice.davesautoservice.MapsActivity" />
</LinearLayout>

and then:

进而:

Snackbar.make(findViewById(R.id.dummy_layout_for_snackbar), "Click the pin for more options", Snackbar.LENGTH_LONG).show();

回答by Umasankar

Try this in any activity:

在任何活动中试试这个:

snackbar(findViewById(android.R.id.content),"your text")

回答by millibit

As Shahab Rauf points out, getting the view via getDecorView() may put the snackbar behind the navigation bar in the bottom. I use the following code: (Use and extend to your delight)

正如Shahab Rauf 指出的那样,通过getDecorView() 获取视图可能会将snackbar 放在底部导航栏的后面。我使用以下代码:(使用并扩展到您的喜悦)

public class BaseActivity extends AppCompatActivity {

    private View getRootView() {
        final ViewGroup contentViewGroup = (ViewGroup) findViewById(android.R.id.content);
        View rootView = null;

        if(contentViewGroup != null)
            rootView = contentViewGroup.getChildAt(0);

        if(rootView == null)
            rootView = getWindow().getDecorView().getRootView();

        return rootView;
    }

    protected void showSnackBarWithOK(@StringRes int res) {
        final View rootView = getRootView();
        if(rootView != null) {
            final Snackbar snackbar = Snackbar.make(getRootView(), res, Snackbar.LENGTH_INDEFINITE);
            snackbar.setAction(R.string.ok, new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    snackbar.dismiss();
                }
            });

            snackbar.show();
        }
    }

    protected void showSnackBar(@StringRes int res) {
        final View rootView = getRootView();
        if(rootView != null)
            Snackbar.make(rootView, res, Snackbar.LENGTH_LONG).show();
    }
}

回答by Rami Alloush

I would say that findViewByIdis the best approach. As using getWindow().getDecorView().getRootView()will cause the message to be shown behind the bottom navigation bar.

我会说这findViewById是最好的方法。使用getWindow().getDecorView().getRootView()将导致消息显示在底部导航栏后面。

In my case, I didn't need to create a dummy element in XML. I used the following code

就我而言,我不需要在 XML 中创建虚拟元素。我使用了以下代码

Snackbar.make(findViewById(R.id.container),"This will start payment process.", Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show();

and my XML file is as follows

我的 XML 文件如下

<android.support.design.widget.CoordinatorLayout 
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"
android:fitsSystemWindows="true"
tools:context=".HomePatientActivity">

<android.support.design.widget.AppBarLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingTop="@dimen/appbar_padding_top"
    android:theme="@style/AppTheme.AppBarOverlay">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:layout_weight="1"
        android:background="?attr/colorPrimary"
        app:layout_scrollFlags="scroll|enterAlways"
        app:popupTheme="@style/AppTheme.PopupOverlay">

    </android.support.v7.widget.Toolbar>

    <android.support.design.widget.TabLayout
        android:id="@+id/sliding_tabs"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        app:layout_anchorGravity="top"
        app:tabMode="fixed" />

</android.support.design.widget.AppBarLayout>

<android.support.v4.view.ViewPager
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

</android.support.v4.view.ViewPager>

<android.support.design.widget.FloatingActionButton
    android:id="@+id/fab"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="end|bottom"
    android:layout_margin="@dimen/fab_margin"
    app:srcCompat="@android:drawable/ic_dialog_email" />

</android.support.design.widget.CoordinatorLayout>

回答by Wincelee

Add any layout and assign the layout an id example below:

添加任何布局并在下面为布局分配一个 id 示例:

<RelativeLayout
    android:id="@+id/relativeLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment
        android:id="@+id/map_fragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        />

</RelativeLayout>

In your activity find the layout using findViewById:

在您的活动中使用 findViewById 查找布局:

RelativeLayout relativeLayout = findViewById(R.id.relativeLayout);

Example for other layouts respectively as long as your assign the layouts their Id's:

其他布局的示例,只要您为布局分配了它们的 ID:

LinearLayout relativeLayout = findViewById(R.id.linearLayout);
FrameLayout frameLayout = findViewById(R.id.frameLayout);

Displaying the Snackbar:

显示 Snackbar:

Snackbar.make(relativeLayout,"You are displaying a Snackbar",Snackbar.LENGTH_SHORT).show();

For other layouts just change the name of the layouts examples:

对于其他布局,只需更改布局示例的名称:

Snackbar.make(linearLayout,"You are displaying a Snackbar",Snackbar.LENGTH_SHORT).show();

Snackbar.make(frameLayout,"You are displaying a Snackbar",Snackbar.LENGTH_SHORT).show();

回答by humble_wolf

Don't do it.

不要这样做。

Why ?

为什么 ?

The entire idea of giving an anchor view to snackbar is probably because it gives us the ablity to put it on our favourite place on the screen,

为小吃店提供锚点视图的整个想法可能是因为它使我们能够将其放在屏幕上我们最喜欢的位置,

As mentioned in other answers there are ways by which you can attach the root view to it automatically, Using getWindow().getDecorView().getRootView()is one of these, but it can cause this message to appear on bottom navigation view, which doesn't look good (at least to me).

正如其他答案中提到的,您可以通过多种方式自动将根视图附加到它,使用getWindow().getDecorView().getRootView()是其中之一,但它可能导致此消息出现在底部导航视图上,这看起来不太好(至少对我而言) )

If you want something for general message display go for toast, it is much less error prone and have a consistent appearence, if you need something with interaction I would suggest Alert Dialogue

如果您想要一些用于一般消息显示的东西,那就去toast,它不太容易出错并且外观一致,如果您需要一些交互性的东西,我建议使用Alert Dialogue

回答by Emi Raz

I think the simplest is this:

我觉得最简单的就是这个:

Snackbar.make(requireView(), R.string.message, Snackbar.LENGTH_SHORT).show();