I need some help figuring out, what's wrong with my Snackbars (Design Support), which are not showing up.
I have a VideoView (FrameLayout containing a dynamically created SurfaceView).
The layout file is:
<?xml version="1.0" encoding="utf-8"?>
<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="false"
android:id="#+id/coordinator"
android:background="#android:color/white"
tools:context="com.denisloh.typhoonCamera.MainActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<VideoView
android:id="#+id/videoView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="top|start"
android:background="#drawable/toolbar_gradient"
android:theme="#style/AppTheme.AppBarOverlay"
app:popupTheme="#style/AppTheme.PopupOverlay">
<android.support.v7.widget.ActionMenuView
android:id="#+id/action_bar"
android:layout_height="wrap_content"
android:layout_width="wrap_content" />
</android.support.v7.widget.Toolbar>
</RelativeLayout>
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center|end"
android:layout_margin="#dimen/fab_margin"
android:src="#drawable/ic_camera_white_24dp" />
</android.support.design.widget.CoordinatorLayout>
I create and show the snackbar with this snippet:
...
mCoordinatorLayout = (CoordinatorLayout) findViewById(R.id.coordinator);
...
private void showWifiSettingsSnackBar(final String message) {
Snackbar.make(
mCoordinatorLayout,
getString(R.string.wifi_error_open_settings, message),
Snackbar.LENGTH_INDEFINITE)
.setAction(R.string.wifi_settings, new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
}
})
.show();
Log.d(TAG, "Showing snackbar.");
}
When I try to open the snackbar it isn't shown. However, when I remove the VideoView from my layout, it is shown without any problems.
So, I guess, that the VideoView is hiding it or the snackbar is shown out of bounds. To check that, I replaced the VideoView with a basic View of the same size. But there, I can see the snackbars.
Did someone else had a similar issue with SurfaceViews in connection with Snackbars?
try adding, videoView.setZOrderOnTop(false); in your java file.
Attach the snack bar to your VideoView instead of CoordinatorLayout
I have got a similar problem, while using WebView in Fullscreen and AppCompat, the Snackbar is hiden. My solution for the issue:
• Init the snackbar.
View rootView = super.findViewById(R.id.mainContainer);
Snackbar snack = Snackbar.make(rootView, message, Snackbar.LENGTH_INDEFINITE);
snack.setAction("OK", callback);
View view = snack.getView();
• Important for showing the snack foreground.
view.requestFocusFromTouch();
• Set position Top and show the snack. (!Important: Setting it Bottom will hide it overlay.
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) view.getLayoutParams();
params.setGravity(Gravity.TOP);
view.setLayoutParams(params);
snack.show();
Related
In an Android project, I have an Activity that contains (from top to bottom) a header, a RecyclerView and a RelativeLayout.
Code sample :
<android.support.design.widget.CoordinatorLayout ...>
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
...
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
...
</RelativeLayout>
</android.support.design.widget.CoordinatorLayout>
This is the behaviour I want : the RelativeLayout is "folded" by default, i.e. under the RecyclerView. When the user swipes up, the RelativeLayout expands to use the whole screen, and folded again when swipes down.
What is the right way to do it ? As I want the RelativeLayout to be BELOW the RecyclerView when folded, and OVER it when expanded. I tried setting the dependencies between elements dynamically but couldn't manage to do so.
Thanks for any help or advice on how to organize the activity to get such a behaviour.
EDIT
This is the XML structure :
<CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
</AppBarLayout>
<RecyclerView
android:id="#+id/top_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/app_bar"
android:layout_above="#+id/relativelayout_footer" />
<RelativeLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_alignParentBottom="true">
<TextView ...>
<RecyclerView
android:id="#+id/included_list"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:visibility="gone"/>
</RelativeLayout>
</RelativeLayout>
</CoordinatorLayout>
And the listener :
top_list.setVisibility(playlistOpened ? View.VISIBLE : View.GONE);
app_bar.setVisibility(playlistOpened ? View.VISIBLE : View.GONE);
included_list.setVisibility(playlistOpened ? View.GONE : View.VISIBLE);
Transition cb = new ChangeBounds();
cb.setDuration(1000);
TransitionManager.beginDelayedTransition(slider, cb);
playlistOpened = ! playlistOpened;
As you see, I switch the visibility of the elements in order to reorganise the view. When the included_list is set to VISIBLE, it pushes up the TextView.
The only problem is that the top_list and the app_bar disappear before being covered by the RelativeLayout. I tried adding a Listener to the Transition and do these when the transition ends, but it doesn't work (I guess because they're not set to GONE at the beginning, so the RelativeLayout can't move up). Any idea of how to do so ? Maybe I should open another question for it ?
Okay, a final attempt. I am back to RelativeLayout and added another one around the RecyclerView to fix its scrolling problem. However, transitions get tricky (and the listener complicated) then. In order to prevent the RecyclerView from popping away before the RelativeLayout with the TextView inside fully covers the latter, I had to include a fading transition to the RecyclerView, too. Hope this suits you.
XML:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
</android.support.design.widget.AppBarLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="#+id/rlwithrecyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/rlwithtextview"
android:layout_alignParentTop="true">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
<RelativeLayout
android:id="#+id/rlwithtextview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<TextView
android:layout_width="match_parent"
android:layout_height="400dp"
android:id="#+id/textview"
android:text="Just a test" />
</RelativeLayout>
</RelativeLayout>
</android.support.design.widget.CoordinatorLayout>
onClick():
#Override
public void onClick(View v) {
RelativeLayout rlWithRecyclerView = findViewById(R.id.rlwithrecyclerview);
RelativeLayout.LayoutParams layoutParamsRlWithRecyclerView;
RelativeLayout rlWithTextView = findViewById(R.id.rlwithtextview);
RelativeLayout.LayoutParams layoutParamsRlWithTextView;
if (rlWithTextView.getLayoutParams().height == MATCH_PARENT) {
layoutParamsRlWithTextView = new RelativeLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT);
layoutParamsRlWithRecyclerView = new RelativeLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT);
layoutParamsRlWithRecyclerView.addRule(RelativeLayout.ALIGN_PARENT_TOP);
layoutParamsRlWithRecyclerView.addRule(RelativeLayout.ABOVE, R.id.rlwithtextview);
} else {
layoutParamsRlWithRecyclerView = new RelativeLayout.LayoutParams(MATCH_PARENT, 0);
layoutParamsRlWithTextView = new RelativeLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT);
}
layoutParamsRlWithTextView.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
Transition changeBounds = new AutoTransition();
changeBounds.setDuration(500);
TransitionManager.beginDelayedTransition(rlWithRecyclerView, changeBounds);
TransitionManager.beginDelayedTransition(rlWithTextView, changeBounds);
rlWithRecyclerView.setLayoutParams(layoutParamsRlWithRecyclerView);
rlWithTextView.setLayoutParams(layoutParamsRlWithTextView);
}
Although I got credit for the two other answers, I will eventually delete them, since they don't solve the problem.
I have an activity with a coordinator layout. Inside the coordinator layout is a view which inherits the default bottom sheet layout behavior for the Google Support Library Bottom Sheet. The issue is that when I call Snackbar.show() with the coordinator layout as the view, the bottomsheet pops up as well.
Here is the call to show snackbar:
Snackbar.make(coordinatorLayout, R.string.status_image_saved,
Snackbar.LENGTH_SHORT).show();
Here is the layout:
<android.support.design.widget.CoordinatorLayout>
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout>
<android.support.v7.widget.Toolbar />
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView />
</android.support.constraint.ConstraintLayout>
<LinearLayout
android:id="#+id/attachment_selector"
android:layout_width="match_parent"
android:layout_height="480dp"
android:background="#color/colorBack"
android:elevation="10dp"
android:orientation="vertical"
app:behavior_hideable="true"
app:behavior_peekHeight="#dimen/bottom_sheet_start"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior">
<android.support.design.widget.TabLayout
android:id="#+id/attachment_selector_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabGravity="fill"
app:tabMode="fixed" />
<android.support.v4.view.ViewPager
android:id="#+id/attachment_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
It's a late answer but might be helpful for others.
If you are using a Dialog or BottomSheetDialog you can show a Snackbar providing the top-level window decor view.
Here's my solution in Kotlin:
Snackbar.make(
dialog.window.decorView, // important part
"your-string",
Snackbar.LENGTH_SHORT
).show()
The solution using dialog.window.decorView appeared over Android's soft navigation keys for me. Instead I shifted the Snackbar's elevation to be greater than the BottomSheetDialog's elevation.
This keeps the Snackbar at the correct position in the y-axis and the new elevation brings it above the bottom sheet:
Snackbar.make(binding.root, "Example", Snackbar.LENGTH_LONG)
.apply {
view.elevation = 1000F
}.show()
Snackbar.make(
dialog.window.decorView,
"your-string",
Snackbar.LENGTH_SHORT
).show()
also add anchor view to SnackBar (you can add view at bottom of the root view in your layout and use it as anchor view in SnackBar)
e.g.,
snackbar.setAnchorView(your_view_here)
I am using SnackBar for single line message for related operation.
Snackbar snackBar;
public void showSnackBar(View view){
snackBar = Snackbar.make(view, "Searching for GPS", Snackbar.LENGTH_INDEFINITE);
snackBar.show();
}
In the method isGPSEnabled , i use the method showSnackBar
if(Helper.isGPSEnabled(this)){
showSnackBar(findViewById(android.R.id.content));
}
But I got this,
Why SnackBar allow some space from bottom bar ?
Edit
The layout file :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/content"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:drawable/edit_text"
android:divider="#android:drawable/divider_horizontal_textfield"
android:addStatesFromChildren="true">
<LinearLayout android:id="#+id/container"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingEnd="0dip"
/>
<AutoCompleteTextView android:id="#+id/edit"
android:completionThreshold="1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:layout_gravity="center_vertical"
/>
</LinearLayout>
change 'content' Linear layout_height = "match_parent"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/content"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:drawable/edit_text"
android:divider="#android:drawable/divider_horizontal_textfield"
android:addStatesFromChildren="true">
add answer. try this.
in xml linear id change
android:id="#+id/content" to android:id="#+id/parentLinear"
and code
LinearLayout linear = (LinearLayout)findViewById(R.id.parentLinear);
Snackbar.make(linear, "Searching for GPS", Snackbar.LENGTH_INDEFINITE).show();
Please check android.R.id.content view in your layout file.
SnackBar will be shown at the bottom of this view if it is FrameLayout. If you have added padding try removing it.
Can help you better, if you share the layout code.
I built a project based on Scrolling Activity, and faced a strange issue. Consider the following scenario:
I click on fab button to go to another fragment but when the fragment displaces, the fab button will not disappear!
Can anybody know how to fix this problem?
Here is my XML of Scrolling Activity that I added to my frameLayout:
<?xml version="1.0" encoding="utf-8"?>
<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="ir.apio.myapplication.ScrollingActivity">
<android.support.design.widget.AppBarLayout
android:id="#+id/app_bar"
android:layout_width="match_parent"
android:layout_height="#dimen/app_bar_height"
android:fitsSystemWindows="true"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:popupTheme="#style/AppTheme.PopupOverlay" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<include layout="#layout/content_scrolling" />
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="#dimen/fab_margin"
android:src="#android:drawable/ic_dialog_email"
app:layout_anchor="#id/app_bar"
app:layout_anchorGravity="bottom|end" />
<FrameLayout
android:id="#+id/frame"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.design.widget.CoordinatorLayout>
content_scrolling.xml :
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView 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"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context="ir.apio.myapplication.ScrollingActivity"
tools:showIn="#layout/activity_scrolling">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="#dimen/text_margin"
android:text="#string/large_text" />
</android.support.v4.widget.NestedScrollView>
My fab ClickListener :
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.frame,new TestFragment())
.commit();
}
});
And also my TestFragment :
public static class TestFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_test,container,false);
return view;
}
}
Here is the screen-shot in the first place:
Here is screen-shot when going to the new fragment:
The reason you are still seeing the FAB is elevation, which refers to a views depth on the screen. It affects which elements are above or below one another and the shadows they cast(for example a FAB sits on top of the main content and casts a shadow).
The FAB by default will have some elevation, which you can override using the elevation attribute, eg app:elevation="4dp". The other elements will be at the 0dp level.
In your case, you've put the FrameLayout last in your layout file, and I presume that's where you are loading your fragment into. What this does is not actually replace your other content, but just cover it with the content of your FrameLayout.
The reason it doesn't cover the FAB, is because the FAB has some elevation and the FrameLayout doesn't. So although you've put your FrameLayout last and would normally expect that to be "on top", the FAB actually has a higher elevation which overrides that.
A quick fix, would be to give your floating action button app:elevation=0dp which would put it back on the same elevation level as everything else and the normal rules would apply, the FrameLayout is last and would be on top.
In reality, just putting a big frame covering the previous content is not usually the best thing to do and you would want to look at other ways to structure the app.
I had the same problem. I called the .hide() method on the FragmentTransaction and it worked for me.
fab.setOnClickListener {
val fragmentManager = fragmentManager
val fragmentTransaction = fragmentManager?.beginTransaction()
val fragment = YourFragment()
fragmentTransaction?.add(R.id.fragment_container, fragment)
fragmentTransaction?.addToBackStack(null)
fragmentTransaction?.hide(this)
fragmentTransaction?.commit()
}
I'm currently using the Design Support Library. I've tried implementing the Snackbar with my CoordinatorLayout wraping the entire layout. When the Snackbar is to be displayed, it raises the FAB. But it makes no effort to come down and thereby stays above the translated distance.
It however, does come down when I dismiss the Snackbar by swiping it. So the CoordinatorLayout is aware of the FAB wrapped inside.
.xml
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ads="http://schemas.android.com/apk/res-auto"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/coordinator_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="#+id/relative_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#color/primary"
android:elevation="4dp"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar" />
<com.google.android.gms.ads.AdView
android:id="#+id/ad_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/toolbar"
android:layout_centerHorizontal="true"
android:layout_gravity="center_horizontal"
ads:adSize="BANNER"
ads:adUnitId="#string/banner_ad_unit_id" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/ad_view">
<include layout="#layout/card_view" />
</ScrollView>
</RelativeLayout>
<android.support.design.widget.FloatingActionButton
android:id="#+id/btn_generate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right|end"
android:layout_margin="16dp"
android:src="#drawable/ic_refresh_white_24dp"
app:elevation="6dp"
app:fabSize="normal"
app:pressedTranslationZ="12dp" />
</android.support.design.widget.CoordinatorLayout>
.java
Snackbar.make(mCoordinatorLayout, R.string.copied_to_clipboard,
Snackbar.LENGTH_SHORT).show();
If you want to show the Snackbar such that while it showed up, the CoordinatorLayout will be adjusted, then try the code below
findViewById(R.id.btn_generate).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Hello Snackbar", Snackbar.LENGTH_LONG).show();
}
});
You can try the code below, it should work fine. This is how I implement my snackbar in all of my projects and it has never failed me. Study carefully; merry coding ;-) !
Snackbar.make(findViewById(android.R.id.content),"Your text",Snackbar.LENGTH_SHORT).show();
Remember, never forget your show() method, your snackbar is useless without it.
EDIT:
If you're using databinding or viewbinding, you can attach/anchor your SnackBar to any view within your layout by doing something like this:
Snackbar.make(binding.button, message, Snackbar.LENGTH_SHORT).show()
Kindly note that you can still use this approach even if you're not using data/view binding. Just pass the view as the first argument.