I have a scrolling activity, and I want to be notified when the floating action button is being hidden.
In order to do so, I created MyFab which extends FloatingActionButton and an interface (to use as a callback) to call when the floating action button is being hidden, but I can't quite figure out what method is being called when I scroll and the floating action button disappears (I want to override the method, so I can call super and the callback that is implemented in the activity)
The interface:
public interface OnAppearanceChangedListener {
void onAppearanceChanged(int alpha);
}
My Floating Action Button:
public class MyFloatingActionButton extends FloatingActionButton {
private OnAppearanceChangedListener mListener;
public void setListener(OnAppearanceChangedListener mListener){
this.mListener = mListener;
}
/*insert code here to call mListener.onAppearanceChanged(),
probably by overriding some method */
}
The activity:
public class MainActivity extends Activity implements OnAppearanceChangedListener {
#Override
public void onAppearanceChanged(boolean visible) {
// I want this function to be called when Floating Action Button hide/show state is changed
}
}
--edit--
figured it out. animate() was the function I was looking for. It is being called to animate the floating action button shrinking action (what I was referring to as hiding)
Your question is quite ambiguous but if what you are looking for is to animate (hide) the fab on scroll you might want to refer to this tutorial. Otherwise explain your post to gain more help in community.
Cheers
Related
I'm using BottomAppbar with floating action button in single activity.The Fab has different responsibility in different fragment.
HomeFragment -> adds new item
AddProblemFragment ->saves item(also icon changes)
DetailsFragment -> adds items to selected collections(also icon changes)
I have tried to use listener between activity and fragments. Icon and position changes perfectly but I couldn't handle calling methods that in fragments when clicked.
To solve clicking problem I'm getting fab reference from activity with
fab = requireActivity().findViewById(R.id.fab) in each fragment (in onViewCreated).
So, problem is after orientation changes gives
java.lang.NullPointerException: requireActivity().findViewById(R.id.fab) must not be null
Is there way to avoid getting this error after orientation changes? or Which lifecycle should choose to initialize fab?
Is it possible to initialize fab in BaseFragment and use it because almost each fragment have fab?
The Code Snippets:
//Each fragment same approach
private lateinit var fab:FloatingActionButton
override fun onViewCreated(view:View,savedInstanceState:Bundle?){
fab = requireActivity().findViewById(R.id.fab_btn_add)
fab.setImageResource(R.drawable.ic_related_icon)
fab.setOnClickListener {
//calls method
}
First you need to create an interface for you fab click listener for Example:
interface FabClickCallback {
void onFabClick()
}
and on your activity,
You Need create an instance from this Callback
private FabClickCallback fabCallback;
and you want create new method inside your Activity called for Example:
public void handleFabClickListener(FabClickCallback callback){
// TODO Here put callback
this.fabCallback = callback;
}
and you want trigger this callback when user click on Fab Button like This:
fab.setOnClickListener ( view -> {
if (this.fabCallback != null ) {
this.fabCallback.onFabClick();
}
});
finally on Each Fragment you want handle Fab Click you want call this function and pass your actual fab click code :
((YourActivity) requireActivity()).handleFabClickListener(this);
and your fragment must implements FabClickCallback interface
I am making an Android application which has one activity and many fragments. The activity contains a bottom app bar and that bottom bar has a navigation icon in it. Like this:
<com.google.android.material.bottomappbar.BottomAppBar
android:id="#+id/bottom_appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:backgroundTint="#color/colorbottomappbar"
app:fabAlignmentMode="center"
app:navigationIcon="#drawable/ic_menu_green_24dp">
</com.google.android.material.bottomappbar.BottomAppBar>
This navigation menu icon will be shown in every fragment. However, in some fragments I want to change that navigation icon in the bottom app bar to back button/icon. How can I achieve this? Also, currently I handle the navigation icon click in the main activity. How can I handle the click in the case of the back icon? How will it know what the current fragment is and how can I determine which fragment the back icon leads to?
If you look at the documentation, you'll see that BottomAppBar extends from Toolbar and it has an inherited method called setNavigationIcon(int res).
You can implement an interface that your main Activity implements like so:
interface FramentChangedListener {
void onFragmentChanged(int type);
}
Your activity would do something like this:
public class MainActivity extends Activity implements FragmentChangedListener {
// This will keep track of what is currently shown
private int current = 0;
#Override
public void onFragmentChanged(int type) {
if (type == FirstFragment.SOME_TYPE) {
// Update the current fragment value, we're associating each fragment
// with an int value.
current = type;
bottomAppBar.setNavigationIcon(R.drawable.your_back_icon);
}
}
...
}
In your fragment you would do something like this:
public class FirstFragment extends Fragment {
private FragmentChangedListener listener;
public static final int SOME_TYPE = 1;
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceOf FragmentChangedListener) {
// context in this case is your activity, which implements FragmentChangedListener
listener = (FragmentChangedListener) context;
// You can call the listener now
listener.onFragmentChanged(SOME_TYPE);
}
}
}
In your Activity, add a listener to the BottomAppBar via setNavigationOnClickListener and whenever you receive the navigation icon event, you can check against the current value that we defined.
I am working or an app where I have 4 fragments in viewpager and floating action button (fab). When I click on fab there appear 3 subfabs. Each of them start different activities where user can search data from different fragments. Is it possible to set fab so that if I click on it while I'm in first fragment it'll open an activity for searching inside this fragment, onClick inside second - search for second and etc. The issue is that now clicking on sub fab while I'm in some fragment I can search data from another fragment too and it's a bit weird. I understand question is kinda strange, if something is unclear I'll explain further
You can make FAB button public and implement onClick listener in each fragment.
You should override setUserVisibleHint and put your code onResume so getActivity() will not return null. Fab button will have different actions in different fragments.
Here's an example, inside each fragment when you want Fab click listener:
#Override
public void setUserVisibleHint(boolean visible)
{
super.setUserVisibleHint(visible);
if (visible && isResumed())
{
onResume();
}
}
#Override
public void onResume()
{
super.onResume();
if (!getUserVisibleHint())
{
return;
}
MainActivity mainActivity = (MainActivity)getActivity();
mainActivity.fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Do what you want
}
});
}
You can check in onclick method of floating action button which fragment is currently opened and calling it.
Call findFragmentById() on FragmentManager and determine which fragment is in your R.id.frameTitle container.
I've got a Main Activity which is a search interface, when the user clicks a result in the list, the result details are displayed in a Fragment. The Main Activity has an Action Bar, but in the details Fragment, the Action Bar is hidden. To hide the Action Bar in the Fragment, I'm calling a method in the Main Activity from the Fragment Activity like this: ((SearchInterface)getActivity()).hideABar();. Then when the user clicks the back button, they go back to the search interface and the Action Bar reappears. Doing that is a bit more complex than simply calling a method. I set up an Interface in the Main Activity and override the method in the Fragment like this:
Main Activity:
public interface Callback {
public void onBackPressedCallback();
}
#Override
public void onBackPressed() {
super.onBackPressed();
if(fragBackPressed != null)
fragBackPressed.onBackPressedCallback();
checkActionBarState();
}
...
public void checkActionBarState(){
bar_AB = getSupportActionBar();
boolean barVisible = bar_AB.isShowing();
if(barVisible){
Toast.makeText(getApplicationContext(),"ActionBar WAS Visible",Toast.LENGTH_LONG).show();
}else{
Toast.makeText(getApplicationContext(),"ActionBar WAS NOT Visible",Toast.LENGTH_LONG).show();
bar_AB.show();
}
}
Fragment:
#Override
public void onBackPressedCallback() {
Log.d("SSIVideoFrag", "checking action bar state");
}
So now, when the user presses the Back button while in the Details Fragment, they go back to Main Activity and the Action Bar reappears. Now I'd like to add a button in the Details Fragment that does what clicking the Back button does, but I can't figure out how to do it. I don't know how to override the onBackPressedCallback() method from within the onClick of a Button:
back_BTN.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
//--- what to do here?
}
});
simple:
getFragmentManager().popBackStack();
https://developer.android.com/reference/android/app/FragmentManager.html#popBackStack()
ps.: that's not an actual back press, your onBackPressed will not be called. But the fragment will be removed, just like in a back press.
We can use the setDisplayHomeAsUpEnabled() method on an activity to display the "up" arrow on the action bar.
If I understand correctly, we're only really supposed to show the up arrow if we're not the root activity.
Clicking the "up" arrow should take us to the root activity. Is that all there is to it? I should then add this call to all my activities like so:
class RootActivity {
public void onCreate() {
setDisplayHomeAsUpEnabled(false);
}
}
class AppleActivity {
public void onCreate() {
setDisplayHomeAsUpEnabled(true);
}
}
class OrangeActivity {
public void onCreate() {
setDisplayHomeAsUpEnabled(true);
}
}
...
Yes, that's pretty much it.
Clicking the up-arrow should take you towards the root.
and don't forget to actually handle the click in onOptionsItemSelected by checking the item id against android.R.id.home