引用自:http://www.myandroidsolutions.com/2015/01/01/android-floating-action-button-fab-tutorial/
TUTORIAL DEPRECATED
Use this tutorial instead: Floating Action Button New
In this tutorial I will show you how to add a Floating Action Button aka FAB, for pre Lollipop versions and for Lollipop. For pre versions it will be just a simple round button with shadow and click effect, but for Android 5.0 we will use ripple effect and elevation.
We will create a ListView and the floating action button will be positioned over the list on the right-bottom of the list.
1. Create a new project with minSdk:9 and targetSdk:21 and name your main activity as “MainActivity” (it should be generated this way when it’s created)
This is my build.gradle
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
apply plugin: ‘com.android.application’
android { compileSdkVersion 21 buildToolsVersion “21.1.2”
defaultConfig { applicationId “ro.funcode.floatingactionbutton” minSdkVersion 9 targetSdkVersion 21 versionCode 1 versionName “1.0” } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile(‘proguard-android.txt’), ‘proguard-rules.pro’ } } }
dependencies { compile fileTree(dir: ‘libs’, include: [‘*.jar’]) compile ‘com.android.support:appcompat-v7:21.0.3’ } |
Pre Lollipop
2. Go to res – layout and add a new xml for the items from the list. Name your xml as “list_item.xml” and add the following code:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?xml version=“1.0” encoding=“utf-8”?>
<LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android” android:orientation=“horizontal” android:layout_width=“fill_parent” android:layout_height=“fill_parent” android:id=“@+id/list_item” android:gravity=“center_vertical”>
<TextView android:layout_width=“wrap_content” android:layout_height=“wrap_content” android:id=“@+id/list_item_text_view” android:textSize=“20sp” android:padding=“10dp” android:layout_marginLeft=“5dp”/>
</LinearLayout> |
3. Go to res – drawable folder and create a new xml and name it fab_shape.xml. Copy the following code which will represent the shape of the floating action button with shadow and click effect:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 |
<?xml version=“1.0” encoding=“utf-8”?>
<selector xmlns:android=“http://schemas.android.com/apk/res/android”> <item android:state_pressed=“true”> <layer-list> <!– Shadow –> <item android:top=“1dp” android:right=“1dp”> <layer-list> <item> <shape android:shape=“oval”> <solid android:color=“#08000000”/> <padding android:bottom=“3px” android:left=“3px” android:right=“3px” android:top=“3px” /> </shape> </item> <item> <shape android:shape=“oval”> <solid android:color=“#09000000”/> <padding android:bottom=“2px” android:left=“2px” android:right=“2px” android:top=“2px” /> </shape> </item> <item> <shape android:shape=“oval”> <solid android:color=“#10000000”/> <padding android:bottom=“2px” android:left=“2px” android:right=“2px” android:top=“2px” /> </shape> </item> <item> <shape android:shape=“oval”> <solid android:color=“#11000000”/> <padding android:bottom=“1px” android:left=“1px” android:right=“1px” android:top=“1px” /> </shape> </item> <item> <shape android:shape=“oval”> <solid android:color=“#12000000”/> <padding android:bottom=“1px” android:left=“1px” android:right=“1px” android:top=“1px” /> </shape> </item> <item> <shape android:shape=“oval”> <solid android:color=“#13000000”/> <padding android:bottom=“1px” android:left=“1px” android:right=“1px” android:top=“1px” /> </shape> </item> <item> <shape android:shape=“oval”> <solid android:color=“#14000000”/> <padding android:bottom=“1px” android:left=“1px” android:right=“1px” android:top=“1px” /> </shape> </item> <item> <shape android:shape=“oval”> <solid android:color=“#15000000”/> <padding android:bottom=“1px” android:left=“1px” android:right=“1px” android:top=“1px” /> </shape> </item> <item> <shape android:shape=“oval”> <solid android:color=“#16000000”/> <padding android:bottom=“1px” android:left=“1px” android:right=“1px” android:top=“1px” /> </shape> </item> </layer-list> </item>
<!– Blue button pressed –> <item> <shape android:shape=“oval”> <solid android:color=“#90CAF9”/> </shape> </item> </layer-list> </item>
<item android:state_enabled=“true”>
<layer-list> <!– Shadow –> <item android:top=“2dp” android:right=“1dp”> <layer-list> <item> <shape android:shape=“oval”> <solid android:color=“#08000000”/> <padding android:bottom=“4px” android:left=“4px” android:right=“4px” android:top=“4px” /> </shape> </item> <item> <shape android:shape=“oval”> <solid android:color=“#09000000”/> <padding android:bottom=“2px” android:left=“2px” android:right=“2px” android:top=“2px” /> </shape> </item> <item> <shape android:shape=“oval”> <solid android:color=“#10000000”/> <padding android:bottom=“2px” android:left=“2px” android:right=“2px” android:top=“2px” /> </shape> </item> <item> <shape android:shape=“oval”> <solid android:color=“#11000000”/> <padding android:bottom=“1px” android:left=“1px” android:right=“1px” android:top=“1px” /> </shape> </item> <item> <shape android:shape=“oval”> <solid android:color=“#12000000”/> <padding android:bottom=“1px” android:left=“1px” android:right=“1px” android:top=“1px” /> </shape> </item> <item> <shape android:shape=“oval”> <solid android:color=“#13000000”/> <padding android:bottom=“1px” android:left=“1px” android:right=“1px” android:top=“1px” /> </shape> </item> <item> <shape android:shape=“oval”> <solid android:color=“#14000000”/> <padding android:bottom=“1px” android:left=“1px” android:right=“1px” android:top=“1px” /> </shape> </item> <item> <shape android:shape=“oval”> <solid android:color=“#15000000”/> <padding android:bottom=“1px” android:left=“1px” android:right=“1px” android:top=“1px” /> </shape> </item> <item> <shape android:shape=“oval”> <solid android:color=“#16000000”/> <padding android:bottom=“1px” android:left=“1px” android:right=“1px” android:top=“1px” /> </shape> </item> </layer-list> </item>
<!– Blue button –> <item> <shape android:shape=“oval”> <solid android:color=“#03A9F4”/> </shape> </item> </layer-list>
</item>
</selector> |
4. You will have to download the “+” icons which will be displayed on fab. You can download them from below:
Copy these icons into your drawable files.
5. Now, go to res – values – dimens.xml and copy the follwing dimensions:
1
2 3 4 5 6 7 8 9 10 11 |
<resources>
<!– Default screen margins, per the Android Design guidelines. –> <dimen name=“activity_horizontal_margin”>16dp</dimen> <dimen name=“activity_vertical_margin”>16dp</dimen>
<dimen name=“fab_button_diameter”>56dp</dimen> <dimen name=“fab_button_margin_bottom”>16dp</dimen> <dimen name=“fab_button_margin_right”>16dp</dimen> <dimen name=“elevation_low”>1dp</dimen> <dimen name=“elevation_high”>8dp</dimen> </resources> |
6. Now go again, in the res – layout folder where you should have an xml for the main activity with the following name“activity_main.xml”. Open this xml and add the following code in order to add the ListView and the floating action button:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<RelativeLayout xmlns:android=“http://schemas.android.com/apk/res/android”
xmlns:tools=“http://schemas.android.com/tools” android:layout_width=“match_parent” android:layout_height=“match_parent” tools:context=“.MainActivity” android:background=“@android:color/white”>
<ListView android:id=“@+id/list” android:layout_width=“fill_parent” android:layout_height=“fill_parent” android:cacheColorHint=“#00000000” android:transcriptMode=“alwaysScroll”/>
<ImageButton android:id=“@+id/fab_image_button” android:layout_width=“@dimen/fab_button_diameter” android:layout_height=“@dimen/fab_button_diameter” android:layout_alignParentRight=“true” android:layout_alignParentEnd=“true” android:layout_alignParentBottom=“true” android:layout_marginBottom=“@dimen/fab_button_margin_bottom” android:layout_marginRight=“@dimen/fab_button_margin_right” android:background=“@drawable/fab_shape” android:src=“@drawable/fab_ic_add” android:tint=“@android:color/white”/>
</RelativeLayout> |
7. Now we can create the adapter for the list view. Create a new java class and name it MyCustomAdapter. Copy the code below:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
package ro.funcode.floatingactionbutton;
import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView;
import java.util.ArrayList;
public class MyCustomAdapter extends BaseAdapter { private ArrayList<String> mListItems; private LayoutInflater mLayoutInflater;
public MyCustomAdapter(Context context, ArrayList<String> arrayList){
mListItems = arrayList;
//get the layout inflater mLayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); }
@Override public int getCount() { //getCount() represents how many items are in the list return mListItems.size(); }
@Override //get the data of an item from a specific position //i represents the position of the item in the list public Object getItem(int i) { return null; }
@Override //get the position id of the item from the list public long getItemId(int i) { return 0; }
@Override
public View getView(int position, View view, ViewGroup viewGroup) {
// create a ViewHolder reference ViewHolder holder;
//check to see if the reused view is null or not, if is not null then reuse it if (view == null) { holder = new ViewHolder();
view = mLayoutInflater.inflate(R.layout.list_item, null); holder.itemName = (TextView) view.findViewById(R.id.list_item_text_view);
// the setTag is used to store the data within this view view.setTag(holder); } else { // the getTag returns the viewHolder object set as a tag to the view holder = (ViewHolder)view.getTag(); }
//get the string item from the position “position” from array list to put it on the TextView String stringItem = mListItems.get(position); if (stringItem != null) { if (holder.itemName != null) { //set the item name on the TextView holder.itemName.setText(stringItem); } }
//this method must return the view corresponding to the data at the specified position. return view;
}
/** * Static class used to avoid the calling of “findViewById” every time the getView() method is called, * because this can impact to your application performance when your list is too big. The class is static so it * cache all the things inside once it’s created. */ private static class ViewHolder {
protected TextView itemName;
} } |
8. Now the final step, for pre Lollipop example, is to set customize the theme a little bit.
8.1 So first you have to go to res – values – colors.xml (if you don’t have the colors.xml you just have to right click the values folder – select New – Value resource file and write colors.xml in the window that opens). Copy the following colors:
1
2 3 4 5 6 7 |
<?xml version=“1.0” encoding=“utf-8”?>
<resources> <!–Color primary 500 from palette colors –> <color name=“primary”>#03A9F4</color> <!–Color primary dark 700 from palette colors –> <color name=“primaryDark”>#0288D1</color> </resources> |
8.2 Now go to res – values – styles.xml and copy the code below:
1
2 3 4 5 6 7 8 9 10 |
<resources>
<!– Base application theme. –> <style name=”AppTheme” parent=”Theme.AppCompat.Light.DarkActionBar”> <!– Customize your theme here. –> <item name=”colorPrimary”>@color/primary</item> <item name=”colorPrimaryDark”>@color/primaryDark</item> </style>
</resources> |
9. Now go to MainActivity and copy the following code and then you can run the app.
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle; import android.view.View; import android.widget.ImageButton; import android.widget.ListView;
import java.util.ArrayList;
public class MainActivity extends ActionBarActivity {
private ListView myList;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
//relate the listView from java to the one created in xml myList = (ListView) findViewById(R.id.list); myList.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Toast.makeText(MainActivity.this, “Row “ + position + ” clicked” ,Toast.LENGTH_SHORT).show(); } });
ImageButton fabImageButton = (ImageButton) findViewById(R.id.fab_image_button);
final ArrayList<String> list = new ArrayList<>();
//for simplicity we will add the same name for 20 times to populate the list view for (int i = 0; i < 5; i++) { list.add(“Item “ + i); }
final MyCustomAdapter adapter = new MyCustomAdapter(MainActivity.this, list); fabImageButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { list.add(“New Item”); adapter.notifyDataSetChanged(); } });
//show the ListView on the screen // The adapter MyCustomAdapter is responsible for maintaining the data backing this list and for producing // a view to represent an item in that data set. myList.setAdapter(adapter);
} } |
For Lollipop
For Lollipop we will have to add new directory resources for v21.
- anim-v21 directory
- drawable-v21 directory
- layout-v21 directory
- values-v21 directory
1. First we will create anim-v21 folder for the elevation animation. Go to res folder and right click on it – select New – Android Resource directory – and from the Resource type drop down select anim – select Version qualifier and inside the edit text from the right write 21.
Do the same for the other 3 directories.
2. Now that the anim-v21 directory is created you should add a new xml to it. So right click on anim-v21 and create a new xml file with the name of button_elevation.xml.
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<?xml version=“1.0” encoding=“utf-8”?>
<selector xmlns:android=“http://schemas.android.com/apk/res/android”> <item android:state_pressed=“true”> <objectAnimator android:propertyName=“translationZ” android:duration=“@android:integer/config_shortAnimTime” android:valueFrom=“@dimen/elevation_low” android:valueTo=“@dimen/elevation_high” android:valueType=“floatType”/> </item> <item> <objectAnimator android:propertyName=“translationZ” android:duration=“@android:integer/config_shortAnimTime” android:valueFrom=“@dimen/elevation_high” android:valueTo=“@dimen/elevation_low” android:valueType=“floatType”/> </item> </selector> |
3. Now, go to res – drawable-v21 and create a new xml named oval_ripple.xml in order to add the ripple effect and the floating action button shape:
1
2 3 4 5 6 7 8 9 |
<?xml version=“1.0” encoding=“utf-8”?>
<ripple xmlns:android=“http://schemas.android.com/apk/res/android” android:color=“?android:colorControlHighlight”> <item> <shape android:shape=“oval”> <solid android:color=“?attr/colorAccent”/> </shape> </item> </ripple> |
4. Now go to res – layout-v21 and create a new xml named activity_main.xml. This is the same xml used in our activity but we have to create it again in order to add the elevation attribute and stateListAnimator which are available only starting api level 21.
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<RelativeLayout xmlns:android=“http://schemas.android.com/apk/res/android”
xmlns:tools=“http://schemas.android.com/tools” android:layout_width=“match_parent” android:layout_height=“match_parent” tools:context=“.MainActivity” android:background=“@android:color/white”>
<ListView android:id=“@+id/list” android:layout_width=“fill_parent” android:layout_height=“fill_parent” android:cacheColorHint=“#00000000” android:transcriptMode=“alwaysScroll”/>
<ImageButton android:id=“@+id/fab_image_button” android:layout_width=“@dimen/fab_button_diameter” android:layout_height=“@dimen/fab_button_diameter” android:layout_alignParentEnd=“true” android:layout_alignParentBottom=“true” android:layout_marginBottom=“@dimen/fab_button_margin_bottom” android:layout_marginRight=“@dimen/fab_button_margin_right” android:background=“@drawable/oval_ripple” android:src=“@drawable/fab_ic_add” android:tint=“@android:color/white” android:elevation=“@dimen/elevation_low” android:stateListAnimator=“@anim/button_elevation”/>
</RelativeLayout> |
5. And the final step is to customize the theme for api level 21 too. So go to res – values-21 and create a new xml names styles.xml. Copy the following code:
1
2 3 4 5 6 7 8 9 10 11 12 |
<resources>
<!– Base application theme. –> <style name=”AppTheme” parent=”Theme.AppCompat.Light.DarkActionBar”> <!– Customize your theme here. –> <item name=”colorPrimary”>@color/primary</item> <item name=”colorPrimaryDark”>@color/primaryDark</item> <item name=”android:navigationBarColor”>@color/primary</item> <item name=”colorAccent”>@color/primary</item> </style>
</resources> |
And that’s it. This is how the floating action should look like: