How to make snack bar and fab to move together - android

I want to move snack bar and fab to move together like happen in default behaviour but by default it happens only when we click on fab, the fab makes place for snackbar and fab itself moves up,
But want it to happen when some other event happen like other button liked on layout not fab itself, how can i trigger fab to move up and make place for snackbar when other button on layout clicks
Thanks
Onclick of button:
public void onClick(View view) {
if(spinner.getText().length() <= 0){
showListMenu(spinner);
}else{
showSnack("Added to bag we will hold it for 1 hour!", view.getRootView());
}
}
Inside showSnack:
Snackbar.make(view.getRootView(), getResources().getString(R.string.fab_msg), Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
final Animation myAnim = AnimationUtils.loadAnimation(MainActivity.this, R.anim.bounce);
double animationDuration = 2 * 1000;
myAnim.setDuration((long)animationDuration);
MyBounceInterpolator interpolator = new MyBounceInterpolator(0.20, 20.00);
myAnim.setInterpolator(interpolator);
fab.startAnimation(myAnim);

Just anchor fab with snackbar like this:
Snackbar.make(view.findViewById(R.id.fab), getResources().getString(R.string.fab_msg), Snackbar.LENGTH_LONG)
.setAction("Action", null).show();

Use CoordinatorLayout that's enough, no need to change anything on Java code. Add your button inside your CoordinatorLayout
<?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"
tools:context=".MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
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:background="?attr/colorPrimary"
app:popupTheme="#style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<include layout="#layout/content_main" />
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="#dimen/fab_margin"
app:srcCompat="#android:drawable/ic_dialog_email" />
</android.support.design.widget.CoordinatorLayout>
For both click event SnackBar and Fab moves up smoothly
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
toolbar.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Snackbar.make(v, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});

Related

Dynamically change the FAB in MainActivity for Android

I have the following XML layout
<androidx.coordinatorlayout.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"
tools:context=".MainActivity">
<FrameLayout
android:id="#+id/fragment_content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.google.android.material.bottomappbar.BottomAppBar
android:id="#+id/bottomAppBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:fabCradleMargin="20dp"
app:fabCradleVerticalOffset="10dp"
app:fabCradleRoundedCornerRadius="20dp"
android:layout_gravity="bottom">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottomNavigationView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginEnd="16dp"
android:background="#android:color/transparent"
app:menu="#menu/bottom_nav_menu" />
</com.google.android.material.bottomappbar.BottomAppBar>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_anchor="#id/bottomAppBar" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
The associated Java file is the following:
public class MainActivity extends AppCompatActivity {
BottomNavigationView bottomNavigationView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bottomNavigationView = findViewById(R.id.bottomNavigationView);
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Here's a Snackbar", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
My question is, I would like to assign an image source dynamically as well as an action based on which of the navigation fragment the user is on.
So when the app opens it would default to the fab button having a '+' which allows users to add items to list.
If they hit the setting nav button I would like for the image to be gear and if pressed it opens the user setting prefs.
I am just not sure how to achieve this?
UPDATE:
if (bottomNavigationView.getMenu().findItem(R.id.miHome).isChecked()) {
// Set icon image for FAB
fab.setImageResource(R.drawable.ic_add);
} else if (bottomNavigationView.getMenu().findItem(R.id.miSettings).isChecked()) {
fab.setImageResource(R.drawable.ic_settings);
fab.setBackgroundColor(Color.RED);
}
The behavior is that it will show the + sign on load, since the dashboard is the default at app launch, but when I hit the settings nav button, the FAB icon does NOT change to the gear and the background color does NOT turn red!?
Can anyone advise what I am doing wrong?
Using if (bottomNavigationView.getMenu().findItem(R.id.miHome).isChecked()) condition will be triggered only once, but you need to register a listener to the lifetime of the lifecycle owner of the bottomNavigationView which is the MainActivity.
This is typically the OnNavigationItemSelectedListener
bottomNavigationView.setOnNavigationItemSelectedListener(
new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
if (item.getItemId() == R.id.miHome) {
fab.setImageResource(R.drawable.ic_add);
} else if (item.getItemId() == R.id.miSettings) {
fab.setImageResource(R.drawable.ic_settings);
fab.setBackgroundColor(Color.RED);
}
return true;
}
});

Call navigation icon click in toolbar (android)

I have code below:
setSupportActionBar(toolbar);
toolbar.setNavigationOnClickListener(onClickListener);
and XML:
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.Toolbar
android:id="#+id/app_bar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:paddingStart="0dp"
android:paddingEnd="12dp"
app:contentInsetStart="0dp"
app:navigationIcon="#drawable/ic_menu_black_24dp"
app:title="#string/app_name" />
</com.google.android.material.appbar.AppBarLayout>
I want to call click on navigation icon of toolbar, but i cant find method to do it.
I can't call onClickListener(null) because I change icon inside onClick.
Please try this by replacing 'number' with the index of the icon. (It could be 1-2-3-4 etc.)
toolbar.getChildAt(number).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//do whatever you want here
}
});
Try this,
Toolbar toolbar;
toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
#Override
public boolean onSupportNavigateUp() {
onBackPressed();
return true;
}
You can used setNavigationOnClickListener {} for this.
// I used private function here, you don't need to.
private fun onBackArrowPressed() {
// when user clicked the navigation icon (here is back arrow)
binding.toolbar.setNavigationOnClickListener {
// find the nav controller and pop backstack
findNavController().popBackStack()
}
}
Material Components Android Top AppBar

Floating action button not responding to click

I have a floating action button in an activity which i plan to display over fragments. The FAB doesnot repond to clicks while the ripple is visible.
I searched SO for similar questions but the answers I found didnot work.
Here is my layout for the FAB.
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:theme="#style/MyTheme">
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/MainActivityFragmentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
<android.support.design.widget.FloatingActionButton
android:id="#+id/homeFAB"
android:layout_width="65dp"
android:layout_height="65dp"
android:layout_gravity="bottom|center"
android:layout_margin="16dp"
android:src="#drawable/ic_add_image"
android:onClick="runThis"
app:layout_anchor="#id/MainActivityFragmentContainer"
app:layout_anchorGravity="bottom|center" />
I rearranged the order of the button in the layout inside the coordinator layout but did not work.
Then I added android:onclick="runThis" to the FAB in the XML and a method in the activity.
public void runThis(View view) {
Toast.makeText(SlidingMenuActivity.this, "CLICKED", Toast.LENGTH_LONG).show();
}
Getting below error:
java.lang.IllegalArgumentException: Expected receiver of type
xxx.xxx.SlidingMenuActivity, but got
android.support.v7.internal.view.ContextThemeWrapper
Please help me figure out what I am missing.
Thank you
You are using fragments you should use click listener instead of defining onClick on xml like this....
inflate fab on onCreate view...
FloatingActionButton myFab = (FloatingActionButton) myView.findViewById(R.id.homeFAB);
myFab.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
doyourThing();
}
});
or
replace SlidingActivity.this with getActivity()
Try with below code and pass instead of SlidingMenuActivity
with getApplicationContext(). It should work.
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});

NavigationView on both side

I need to open navigation view on both side with different menu.. Also I need to change navigation icon (Currently with three horizontal line). This is better if I can open the nav_view and na_view2 with separate button clicks, these buttons are available in my toolbar, or I need to know how can I set separate icons on both side?.
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout 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:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<include
layout="#layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header_main"
app:menu="#menu/activity_main_drawer" />
<android.support.design.widget.NavigationView
android:id="#+id/nav_view2"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="end"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header_main"
app:menu="#menu/activity_main_drawer1" />
</android.support.v4.widget.DrawerLayout>
Any help will be highly appreciable.
We can get buttons from toolbar by following lines,
Button btnStart = (Button) findViewById(R.id.btnStart);
Button btnEnd = (Button) findViewById(R.id.btnEnd);
and while click the start button we can open and hide left drawer by following listener,
btnStart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (drawer.isDrawerOpen(GravityCompat.START))
drawer.closeDrawer(GravityCompat.START);
else drawer.openDrawer(GravityCompat.START);
}
});
and while click the end button we can open and hide right drawer by following listener,
btnEnd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (drawer.isDrawerOpen(GravityCompat.END))
drawer.closeDrawer(GravityCompat.END);
else drawer.openDrawer(GravityCompat.END);
}
});
And our onBackPressed method will be
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else if (drawer.isDrawerOpen(GravityCompat.END)) {
drawer.closeDrawer(GravityCompat.END);
} else {
super.onBackPressed();
}
}
This also used to close the drawers if those is in open state.

Snackbar with CoordinatorLayout disable dismiss

I am using the support
FloatingActionButton
Snackbar
CoordinatorLayout
I need the CoordinatorLayout so that if SnackBar is shown the FloatingActionButton moves up to make room for the Snackbar. For better understanding check this video.
I am using SnackBar for double-back to exit the application, but the SnackBar can be dismissed.
Is there a way to disable the dismiss on the SnackBar?
Snackbar snackbar = Snackbar.make(view, R.string.press_back_again_to_exit, Snackbar.LENGTH_SHORT);
snackbar.setAction(R.string.ok, new View.OnClickListener() {
#Override
public void onClick(View v)
{
}
});
snackbar.setActionTextColor(getResources().getColor(R.color.white));
View view = snackbar.getView();
view.setBackgroundColor(getResources().getColor(R.color.orange_warning));
snackbar.show();
Layout
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.widget.DrawerLayout
android:id="#+id/drawer_layout"
xmlns:sothree="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
android:fitsSystemWindows="true">
<com.sothree.slidinguppanel.SlidingUpPanelLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="bottom"
sothree:umanoFadeColor="#android:color/transparent"
sothree:umanoPanelHeight="100dp"
sothree:umanoShadowHeight="4dp">
<!-- Toolbar and main content -->
<LinearLayout
android:id="#+id/toolbar_and_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include layout="#layout/toolbar"/>
<!-- Your content layout -->
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"/>
</LinearLayout>
<!-- Sliding up panel layout -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/darker_grey"
android:orientation="vertical">
...
</LinearLayout>
</com.sothree.slidinguppanel.SlidingUpPanelLayout>
<!-- Navigation drawer -->
<ExpandableListView
android:id="#+id/lv_left_drawer"
android:layout_width="280dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#color/white"
android:childDivider="#android:color/transparent"
android:clickable="true"
android:divider="#color/divider_color"
android:dividerHeight="0.6dp"
android:fadeScrollbars="true"
android:groupIndicator="#null"
android:listSelector="#drawable/button_drawer_child_selector"
android:scrollbarSize="0dp"/>
</android.support.v4.widget.DrawerLayout>
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|bottom"
android:layout_marginBottom="#dimen/floating_action_button_margin"
android:layout_marginRight="#dimen/floating_action_button_margin"
android:src="#drawable/ic_add"
android:visibility="invisible"
app:backgroundTint="#color/orange"
app:borderWidth="0dp"
app:elevation="6dp"
app:fabSize="normal"/>
</android.support.design.widget.CoordinatorLayout>
P.S.
I am aware of this GitHub library, that has this functionality, but is there a 'native' way to do it?
Snackbar now has actual support disabling swipe to dismiss using the setBehavior method. The great thing here is that before you would always lose some behaviors which are now preserved. You'll also want to use Snackbar.LENGTH_INDEFINITE
Note that the package moved so you have to import the "new" Snackbar in the snackbar package.
Snackbar.make(view, stringId, Snackbar.LENGTH_INDEFINITE)
.setBehavior(new NoSwipeBehavior())
.show();
class NoSwipeBehavior extends BaseTransientBottomBar.Behavior {
#Override
public boolean canSwipeDismissView(View child) {
return false;
}
}
You can alter the duration of Snackbar to be shown. It will be similar to disable dismiss.
int LENGTH_INDEFINITE Show the Snackbar indefinitely.
Check docs.
if it does not work
For this then there is only one way, Implement Your custom Snackbar and override dismiss() method and in that do nothing. :) As dismiss() is a public API.
The answer about just using LENGTH_INDEFINITE is not sufficient.
It is only non-dismissable when the Snackbar is no child of CoordinatorLayout.
When it is a child, you can still swipe away the SnackBar.
What you can do in that case is listen for the dismiss swipe and simply re-show the Snackbar.
public void showAnnoyingSnackBar(View root, String text) {
Snackbar.make(root, text, Snackbar.LENGTH_INDEFINITE)
.setCallback(new Snackbar.Callback() {
#Override public void onDismissed(Snackbar snackbar, int event) {
// recursively call this method again when the snackbar was dismissed through a swipe
if (event == DISMISS_EVENT_SWIPE) showAnnoyingSnackBar(root, text);
}
})
.show();
}
I noticed that when show() method is called, SnackbarLayout is not fully initialised yet.
To lock dissmiss we have to clear behavior after SnackbarLayout initialisation.
the best place to do this is for example in OnPreDrawListener of SnackbarLayout
final Snackbar snack = Snackbar.make(getView(), "I can't be dissmiss", Snackbar.LENGTH_INDEFINITE);
snack.show();
snack.getView().getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
#Override
public boolean onPreDraw() {
snack.getView().getViewTreeObserver().removeOnPreDrawListener(this);
((CoordinatorLayout.LayoutParams) snack.getView().getLayoutParams()).setBehavior(null);
return true;
}
});
I was successful in disabling the swipe-sideways-to-dismiss snackbars with the following hack (after calling snackbar.show())
((android.support.design.widget.CoordinatorLayout.LayoutParams) snackbar.getView().getLayoutParams()).setBehavior(null);

Categories

Resources