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
Making a Snackbar Without a View?
提问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
最简单
SupportMapFragment
extends 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 findViewById
is 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();