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();
}
});
Related
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;
}
});
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
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();
}
});
I want to go from fragment to activity using back button using toolbar back icon.
The fragment is my navigation drawer item & activity is my MainActivity.
How do I do it?
You can use app:navigationIcon="?attr/homeAsUpIndicator" for that back navigation icon.
<android.support.v7.widget.Toolbar
android:id="#+id/toolbarId"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:navigationIcon="?attr/homeAsUpIndicator"/>
For navigation:
Toolbar toolbar = (ToolBar) getActivity().findViewById(R.id.toolbarId);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
getActivity().onBackPressed();
}
});
Call this method in your fragment onCreateView
public void showBackButton() {
if (getActivity() instanceof ActionBarActivity) {
((ActionBarActivity) getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
}
Try this worked for me :
in XML:
<android.support.v7.widget.Toolbar
android:id="#+id/profileToolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content">
Create an back arrow icon in drawable folder. Name it 'ic_back_button'.
Not sure how :-
just right click on drawable > new > ImageAsset > Clip Art > Search back > select > OK > Finish (don't forget to change the name).
then Inside your fragment in onCreateView :
Toolbar toolbar = view.findViewById(R.id.profileToolbar);
toolbar.setNavigationIcon(R.drawable.ic_back_button);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getActivity().onBackPressed();
}
});
It might help in case if you want to come back from fragment to previous location.
Put this in your class with navController.
#Override
public boolean onSupportNavigateUp() {
navController.navigateUp();
return super.onSupportNavigateUp();
}
don't forget implement relevant dependency such as navigation and navigation UI.
Add this xml code to your fragment and try
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#FFFFFF"
android:layout_gravity="center"
android:gravity="center_horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Title Here"
android:typeface="serif"
android:layout_gravity="center"
android:id="#+id/toolbar_title"
android:textSize="20sp"
android:textColor="#android:color/black"/>
<ImageView
android:id="#+id/ivback_water"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:padding="15dp"
android:scaleType="fitCenter"
android:layout_gravity="left"
android:background="#drawable/ic_arrow_back_black_24dp" />
</android.support.v7.widget.Toolbar>
You can easily do that, if you are using a Custom back button that is placed on your Custom top app bar, in the button's onClick() function you can call.. getActivity().onBackPressed();
it would work the same as if you have clicked the android navigation's back button...
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);