7

I am appreciating the FloatingActionButton (fab) feature of Android and want to use them in a lot of different places in my project.

Right now, I have something like this, where I have several xml specifications for them, all of them are the same, except the id, icon and the onclick.

<android.support.design.widget.FloatingActionButton
    android:id="@+id/fabFoo"
    android:onClick="onFabFoo"
    android:src="@drawable/ic_foo" 
    app:backgroundTint="?attr/colorButtonNormal"
    app2:elevation="2dp"
    app:fabSize="mini" 
    android:focusable="true"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_alignParentLeft="true"
    android:layout_margin="2dp"
    app:rippleColor="?attr/colorSwitchThumbNormal" />

In the interest of avoiding duplicate code... Is there a way to create the fab entirely programmatically without needing to specify it in xml?

...

Trying out some suggestions... There was no 'setSize' until I upgraded the SDK to current (# 25)

FloatingActionButton fab = new FloatingActionButton(this);
fab.setId(View.generateViewId());
fab.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
      Log.d("DEBUG", "onFabFoo");
   }
});
fab.setImageResource(R.drawable.ic_foo);
fab.setElevation(2);
fab.setSize(android.support.design.widget.FloatingActionButton.SIZE_MINI);
fab.setFocusable(true);
RelativeLayout.LayoutParams lay = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                        ViewGroup.LayoutParams.WRAP_CONTENT);
lay.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
lay.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
lay.setMargins(2,2,2,2);
fab.setLayoutParams(lay);

Haven't yet figured out how to set the colors

//  app:backgroundTint="?attr/colorButtonNormal"
//  app:rippleColor="?attr/colorSwitchThumbNormal"

I see there are methods to set these (setBackgroundTintList and setRippleColor) but I don't see how to set it to the colors I chose in the original xml setting (colorButtonNormal and colorSwitchThumbNormal)

Also, don't know how to attach it to the parent and get it to display...

Okay, I guess I realize now, if you do all this programmatically, then you can't use features like the xml Design view in Android Studio. So it's much harder to work with.

slashdottir
  • 7,835
  • 7
  • 55
  • 71
  • 2
    It is all in the [documentation](https://developer.android.com/reference/android/support/design/widget/FloatingActionButton.html) – Shreyash S Sarnayak Mar 06 '17 at 19:43
  • 1
    consider making your style in xml and then applying that style or using a helper class to avoid code duplication – Stefan Mar 06 '17 at 19:45
  • @ShreyashSSarnayak Okay, I looked at the documentation. I see at least one attribute that cannot be set programmatically - that is the fabSize. So I guess I am to deduce the real answer is "no, you cannot"? – slashdottir Mar 06 '17 at 21:17
  • @Stefan Thank you Stefan, your answer is more helpful. – slashdottir Mar 06 '17 at 21:18
  • 2
    You can set size programmatically using [setSize](https://developer.android.com/reference/android/support/design/widget/FloatingActionButton.html#setSize(int)) it is not named as `setfabSize` as you expected. – Shreyash S Sarnayak Mar 07 '17 at 01:50
  • if you don't want to duplicate your xml, you can put it in one place, and use an include – njzk2 Mar 08 '17 at 22:16
  • @njzk2 That sounds interesting, can you provide an example where you include the xml and then make adjustments to variables (like, id, icon and onclick?) – slashdottir Mar 08 '17 at 22:26

3 Answers3

6

There are two I can think of

Using java only

Create a FloatingActionButton directly in code like

public FloatingActionButton getFab(Context context) {
    FloatingActionButton fab = new FloatingActionButton(context);
    ...
    return fab;
}

Inflating the layout

public FloatingActionButton getFab(Context context, ViewGroup parent) {
    LayoutInflater inflater = LayoutInflater.from(context);
    return (FloatingActionButton) inflater.inflate(R.layout.myfab, parent, false);
}

More about inflater

Edit:

You can use setBackgroundTintList and setRippleColor to set the 2 attributes.

And to attach it to parent you do

layout.addView(v);

But I feel using LayoutInflater is better because it does both tasks of generating a FloatingActionButton and attaching it to its parent.

inflater.inflate(R.layout.myfab, layout, true)
Shreyash S Sarnayak
  • 2,309
  • 19
  • 23
  • The layout inflator does not work because a FloatingActionButton is not a layout. – slashdottir Mar 09 '17 at 17:05
  • I tested with layout inflator it worked. I put exact same xml (only FAB no layout) as you posted in the question. – Shreyash S Sarnayak Mar 09 '17 at 17:36
  • Getting theme attributes programmatically doesn't look easy. See this [answer](http://stackoverflow.com/questions/9398610/how-to-get-the-attr-reference-in-code) – Shreyash S Sarnayak Mar 09 '17 at 17:49
  • Hm, ok. Well, when I try it it doesn't compile, it just says: Expected resource of type layout. If I move the xml that defines the fab to its own file, it still does not recognize it as a layout. The only way to access it is by R.id.fabFoo, there is no identifier called R.layout.fabFoo – slashdottir Mar 09 '17 at 18:07
  • Ok, I see. If you want to call it by R.layout.fabFoo, the actual layout file must be named 'fabFoo.xml'. Android programming API is so inconsistent, I'm amazed anyone is able to keep up with all the endless non-intuitive quirks. – slashdottir Mar 09 '17 at 18:18
  • Lol. Ok. By the way, I think capital letter in name `fabFoo.xml` is not allowed. – Shreyash S Sarnayak Mar 09 '17 at 18:22
  • Almost there, so now how do I get a handle to the parent layout? I tried findViewById, but it requires a ViewGroup, not a view. – slashdottir Mar 09 '17 at 18:25
  • 2
    `Layout` is nothing but a `ViewGroup`. So whichever layout you have (LinearLayout, RelativeLayout, etc.) can be used. Do `findViewById` of the layout in which you want to put this FAB and type cast it to ViewGroup. Example - `vg = (ViewGroup) findViewById(...)` – Shreyash S Sarnayak Mar 09 '17 at 19:12
  • You have gone over and above to help me. Thank you! – slashdottir Mar 09 '17 at 21:32
2

We can achieve to create a Floating action button in Programmatically

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/my_relative_layout">
</RelativeLayout>

This is the main xml layout file Not inside this parent layout file we can crate floating action button with the following code in class file.

public class MyClass extends AppCompatActivity{
    RelativeLayout relativeLayout;

    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_name);

        relativeLayout = (RelativeLayout) findViewByID(R.id.my_relative_layout);

        FloatingActionButton fab = new FloatingActionButton(getContext());
        fab.setId(R.id.fab_location_main);
        fab.setLayoutParams(new RelativeLayout.LayoutParams(
                RelativeLayout.LayoutParams.WRAP_CONTENT,
                RelativeLayout.LayoutParams.WRAP_CONTENT
                ));
        relativeLayout.addView(fab);
    }
}

Now

Suresh Chaudhari
  • 648
  • 1
  • 8
  • 21
0

For Advance Users

If you want more control over the FLoating action button:

  • Margin,
  • Padding,
  • Rotation
  • Constraint set
  • Tint
  • Drawable
  • Click listener

    private fun addFabButton() {
    
        // tint color from theme
        val typedValue = TypedValue()
        context.theme.resolveAttribute(R.attr.drawer_fab_tint, typedValue, true)
        @ColorInt val tintColor = typedValue.data
    
        val pillView = FloatingActionButton(context)
        pillView.run {
            id = View.generateViewId()              // set ID
            scaleType = ImageView.ScaleType.FIT_XY  // scale Type
            setImageResource(R.drawable.ic_toolkit_arrow_left_auto_mirror) // UI LIb icon
            setColorFilter(tintColor) // tint color based on theme
    
            setOnClickListener { v: View ->
               //Handle Click
            }
        }
    
        parentView.addView(pillView)
    
        // --------Set Height, Width & padding --------
        val params = pillView.layoutParams
    
         // convert dp to pixels
        params.height = context.resources.getDimensionPixelSize(R.dimen.fab_icon_height)
        params.width = context.resources.getDimensionPixelSize(R.dimen.fab_icon_width)
        pillView.layoutParams = params
    
        val padding = context.resources.getDimensionPixelSize(com.bmwgroup.idnext.keyboard.R.dimen.hide_key_padding)
        pillView.setPadding(padding,padding,padding,padding)
        pillView.requestLayout()
    
        pillView.rotation = -90f
        // --------Apply Constraint set-------
        val set = ConstraintSet()
        set.clone(view)
        // Left Constraint
        val marginStart = context.resources.getDimensionPixelSize(com.bmwgroup.idnext.keyboard.R.dimen.hide_key_margin_start)
        set.connect(pillView.id,ConstraintSet.LEFT,ConstraintSet.PARENT_ID,ConstraintSet.LEFT,
                marginStart
        )
        // top Constraint
        set.connect(pillView.id,ConstraintSet.TOP,ConstraintSet.PARENT_ID,ConstraintSet.TOP,0)
        set.applyTo(view)
    
    }
    
Hitesh Sahu
  • 41,955
  • 17
  • 205
  • 154