web-dev-qa-db-fra.com

Faire une snack sans vue?

Je souhaite afficher une barre dès que l'utilisateur ouvre l'activité Google Maps, mais le fait est qu'il n'y a pas de vues dans l'activité à utiliser comme premier paramètre de l'activité (dans la fonction findViewById() of Snackbar.make()). Qu'est-ce que je mets là? Voici le code de classe 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();
}
}

Aussi, voici l'activité 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" />

Et enfin, voici l'erreur stacktrace:

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$1.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$5.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)

Merci pour l'aide! :)

26
Kelvin Kellner

Je vois quelques options ... Vous ne savez pas lequel peut résoudre votre problème.

Plus simple

SupportMapFragment étend la classe Android.support.v4.app.Fragment. De cette façon, il a une méthode getView()

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

Trouver la vue racine

À partir de cette réponse , il existe un moyen d'obtenir la vue racine via:

getWindow().getDecorView().getRootView()

Alors peut-être que vous pouvez faire:

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

Ajouter un LinearLayout factice pour obtenir la vue

Honnêtement, je ne suis pas sûr que cette solution soit possible. Je ne sais pas si vous pouvez ajouter un LinearLayout au-dessus du fragment Maps ... Je pense que c'est OK, mais comme je n'ai jamais travaillé avec Maps API auparavant, je n'en suis pas sûr.

<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>

et alors:

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

Comme le souligne Shahab Rauf, obtenir la vue via getDecorView () peut placer la barre de contrôle derrière la barre de navigation en bas. J'utilise le code suivant: (Utilisez et étendez votre plaisir)

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();
    }
}
3
millibit

Je dirais que findViewById est la meilleure approche. Si vous utilisez getWindow().getDecorView().getRootView(), le message sera affiché derrière la barre de navigation inférieure.

Dans mon cas, je n'avais pas besoin de créer un élément factice en XML. J'ai utilisé le code suivant

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

et mon fichier XML est comme suit

<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>
0
Rami Alloush

Essayez ceci dans n'importe quelle activité:

snackbar(findViewById(Android.R.id.content),"your text")
0
Umasankar