pacakges: interfaces/utility/febmenu
******com.app.interfaces******
1)BackPressedEventListener.java
===============================
******com.app.interfaces******
1)BackPressedEventListener.java
===============================
package com.eppico.interfaces; public interface BackPressedEventListener { public void onBackPressed();}
2)ClickEventListener.java
==========================
package com.eppico.interfaces; /** * Created by ip4 on 15-06-2016. */import android.view.View; public interface ClickEventListener { public void clickEvent(View v);}3)LocationUpdateListener.java==============================package com.eppico.interfaces; import android.location.Location; public interface LocationUpdateListener { /**Called when got location of user*/ void onLocationUpdate(Location location); /**Called when user deny to request of enable Location permission*/ void onLocationPermissionDeny(); /**Called when user deny to request to enable GPS*/ void onGPSRequestDeny();}4)RecyclerViewItemClickListener.java=====================================package com.eppico.interfaces; import android.content.Context;import android.support.v7.widget.RecyclerView;import android.view.GestureDetector;import android.view.MotionEvent;import android.view.View; public class RecyclerViewItemClickListener implements RecyclerView.OnItemTouchListener { private OnItemClickListener mListener; public interface OnItemClickListener { public void onItemClick(View view, int position); } GestureDetector mGestureDetector; public RecyclerViewItemClickListener(Context context, OnItemClickListener listener) { mListener = listener; mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { @Override public boolean onSingleTapUp(MotionEvent e) { return true; } }); } @Override public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) { View childView = view.findChildViewUnder(e.getX(), e.getY()); if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) { mListener.onItemClick(childView, view.getChildAdapterPosition(childView)); } return false; } @Override public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) { } @Override public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { } }*********************com.app.utility*********************1)Constants.java======================package com.eppico.utility; import android.graphics.Bitmap;import android.net.Uri; /** * Created by manisha on 12/12/16. */ public class Constants { /*public static Uri IMAGE_URI; public static Bitmap CROPPED_BITMAP;*/ public static boolean BTN_OK_CLICKED = false; public final static int MY_PERMISSIONS_REQUEST_URI = 111; public final static int REQUEST_PERMISSION_SETTING = 112; public static final int TYPE_HEADER = 0; public static final int TYPE_ITEM = 1; public static final int TYPE_FOOTER = 2; public static final int FIRST_PAGE_NO=0; public static final int REQ_CODE_CAPTURE_IMAGE=50,REQ_CODE_GALLERY_IMAGE=51,REQ_CODE_RECORD_VIDEO=52,REQ_CODE_CROP_IMAGE=53; public enum SPOT_TYPE{PUBLIC,PRIVATE}; public enum POST_MEDIA_TYPE{IMAGE,VIDEO}; public enum SPOT_LIST_TYPE{INVITED_SPOT,MY_SPOT}; public enum FROM_SCREEN{CREATE_SPOT_MAP,SPOT_DETAIL,PROFILE,MENU}; public enum FOLLOW_STATUS{UNFOLLOW,FOLLOW}; public enum FOLLOW_LIST{FOLLOWERS,FOLLOWING}; public enum INVITATION_STATUS{NOT_INVITED,INVITED}; public enum SPOT_ACTIVE_STATUS{INACTIVE,ACITVE} public enum POPUP_TYPE{CATEGORY,RADIUS} public enum TAB_SEARCH{SPOT,USER} public enum CMS_PAGE{PRIVACY_POLICY,TERMS_CONDITION} public enum LEADER_SHIP_TYPE{LEADERSHIP,CHMAPIONSHIP};}2)CustomDialog.java======================package com.eppico.utility; import android.app.AlertDialog;import android.app.ProgressDialog;import android.content.Context;import android.content.DialogInterface;import android.support.annotation.NonNull; import com.eppico.R; public class CustomDialog { private static CustomDialog customDialog; ProgressDialog progressDialog; public static CustomDialog getInstance() { if (customDialog == null) { customDialog = new CustomDialog(); } return customDialog; } /** * Show progress dialog without message, Before show new dialog it is hide previous showing dialog * @param context Context of activity. * @param cancelable true: Hide out side touch or back press, false: Can not hide out side touch * */ public void show(@NonNull Context context, boolean cancelable) { try { //Before show new dialog hide previous showing dialog hide(); progressDialog = new ProgressDialog(context); progressDialog.setCancelable(cancelable); progressDialog.setMessage(context.getString(R.string.msgLoading)); progressDialog.show(); /*if (progressDialog != null) { if (!progressDialog.isShowing()) { progressDialog.show(); } }*/ } catch (Exception e) { e.printStackTrace(); } } /** * Show progress dialog without message, Before show new dialog it is hide previous showing dialog * @param context Context of activity. * @param message Message of dialog. * @param cancelable true: Hide out side touch or back press, false: Can not hide out side touch * */ public void show(@NonNull Context context,@NonNull String message,boolean cancelable) { try { //Before show new dialog hide previous showing dialog hide(); //Set default dialog message "Loading" message=(message!=null && message.trim().length()>0)?message:context.getString(R.string.msgLoading); progressDialog = new ProgressDialog(context); progressDialog.setMessage(message); progressDialog.setCancelable(cancelable); progressDialog.show(); /*if (progressDialog != null) { if (!progressDialog.isShowing()) { progressDialog.show(); } }*/ } catch (Exception e) { e.printStackTrace(); } } public void hide() { if (progressDialog != null && progressDialog.isShowing()) { progressDialog.dismiss(); } } public boolean isDialogShowing() { if (progressDialog != null) return progressDialog.isShowing(); else return false; } //Show alert dialog public void showMessageDialog(Context context, String title, String message) { /* if(title == null && title.equalsIgnoreCase("")){ title = "Eppico"; }*/ if (message != null && message.trim().length() > 0) { AlertDialog.Builder builder = new AlertDialog.Builder(context); //builder.setTitle(title); builder.setCancelable(true); builder.setMessage(message); builder.setPositiveButton(context.getString(R.string.btnOk), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.dismiss(); } }); // create alert dialog AlertDialog alertDialog = builder.create(); // show it alertDialog.show(); } } //Show alert dialog public void showMessageDialog(Context context,String message) { if (message != null && message.trim().length() > 0) { AlertDialog.Builder builder = new AlertDialog.Builder(context); //builder.setTitle(title); builder.setCancelable(true); builder.setMessage(message); builder.setPositiveButton(context.getString(R.string.btnOk), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.dismiss(); } }); // create alert dialog AlertDialog alertDialog = builder.create(); // show it alertDialog.show(); } } }3)FileUtils.java==================package com.eppico.utility; import android.content.Context;import android.graphics.Bitmap;import android.net.Uri;import android.os.Environment;import android.support.annotation.NonNull;import android.support.annotation.Nullable;import android.util.Log; import com.eppico.R; import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Locale; /** * Created by rushil on 14/12/16. */ public class FileUtils { private String TAG=FileUtils.class.getName(); private static FileUtils fileUtils; public enum MEDIA_TYPE{PICTURE,VIDEO} public static FileUtils getInstance() { if(fileUtils==null) fileUtils=new FileUtils(); return fileUtils; } /** * Save bitmap to Application name folder and return Path * @param context Context of activity or application * @param bitmap Bitmap image * @param subDir Sub directory name which will create under App name folder */ public String saveBitmap(@NonNull Context context,@NonNull Bitmap bitmap,@Nullable String subDir) { try { File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), context.getString(R.string.app_name)); File myDir; if (subDir != null && subDir.length() > 0) myDir = new File(mediaStorageDir + File.separator + subDir); else myDir = new File(mediaStorageDir + ""); if (!myDir.exists()) myDir.mkdirs(); String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date()); String imgName = "IMG-" + timeStamp + ".jpg"; File file = new File(myDir, imgName); if (file.exists()) file.delete(); if (bitmap != null) { FileOutputStream out = new FileOutputStream(file); bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out); out.flush(); out.close(); } return file.getPath(); } catch (Exception e) { e.printStackTrace(); } return ""; } public String saveBitmapWithPath(@NonNull Bitmap bitmap,String filePathWithName) { try { File file = new File(filePathWithName); if (file.exists()) file.delete(); if (bitmap != null) { FileOutputStream out = new FileOutputStream(file); bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out); out.flush(); out.close(); } return file.getPath(); } catch (Exception e) { e.printStackTrace(); } return ""; } /**Return File URI according media type*/ public Uri getFileUri(Context context,MEDIA_TYPE mediaType) { try { File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), context.getString(R.string.app_name)); //Create Media Directory File mediaDir=new File(mediaStorageDir + File.separator + context.getString(R.string.dirMedia)); if(!mediaDir.exists()) mediaDir.mkdirs(); String subDirName="",fileExtension=""; switch (mediaType) { case PICTURE: subDirName=context.getString(R.string.dirImages); fileExtension=".jpg"; break; case VIDEO: subDirName=context.getString(R.string.dirVideos); fileExtension=".mp4"; break; } File subDir = new File(mediaDir + File.separator + subDirName); if(!subDir.exists()) subDir.mkdirs(); String mediaFileName = System.currentTimeMillis() + fileExtension; File mediaFile = new File(subDir, mediaFileName); return Uri.fromFile(mediaFile); }catch (Exception e) { e.printStackTrace(); } return null; } /**Return File path according media type*/ public String getFilePath(Context context,MEDIA_TYPE mediaType) { try { File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), context.getString(R.string.app_name)); //Create Media Directory File mediaDir=new File(mediaStorageDir + File.separator + context.getString(R.string.dirMedia)); if(!mediaDir.exists()) mediaDir.mkdirs(); String subDirName="",fileExtension=""; switch (mediaType) { case PICTURE: subDirName=context.getString(R.string.dirImages); fileExtension=".jpg"; break; case VIDEO: subDirName=context.getString(R.string.dirVideos); fileExtension=".mp4"; break; } File subDir = new File(mediaDir + File.separator + subDirName); if(!subDir.exists()) subDir.mkdirs(); String mediaFileName = System.currentTimeMillis() + fileExtension; File mediaFile = new File(subDir, mediaFileName); return mediaFile.getAbsolutePath(); }catch (Exception e) { e.printStackTrace(); } return null; } /**Return File directory path*/ public String getFileDirPath(Context context,MEDIA_TYPE mediaType) { try { File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), context.getString(R.string.app_name)); //Create Media Directory File mediaDir=new File(mediaStorageDir + File.separator + context.getString(R.string.dirMedia)); if(!mediaDir.exists()) mediaDir.mkdirs(); String subDirName=""; switch (mediaType) { case PICTURE: subDirName=context.getString(R.string.dirImages); break; case VIDEO: subDirName=context.getString(R.string.dirVideos); break; } File subDir = new File(mediaDir + File.separator + subDirName); if(!subDir.exists()) subDir.mkdirs(); return subDir.getAbsolutePath(); }catch (Exception e) { e.printStackTrace(); } return null; } /**Copy file from source to target location with target file name and extension * @param sourcePath Source file path * @param targetPath Target File path with file name e.g path/filName.jpg * */ public String copyFile(String sourcePath,String targetPath) { InputStream in = null; OutputStream out = null; try { //create output directory if it doesn't exist /*File dir = new File (targetPath); if (!dir.exists()) { dir.mkdirs(); }*/ //File sourceFile=new File(inputPath); File outputFile=new File(targetPath);// File outputFile=new File(outputPath + File.separator + sourceFile.getName()); in = new FileInputStream(sourcePath); out = new FileOutputStream(outputFile.getAbsoluteFile()); byte[] buffer = new byte[1024]; int read; while ((read = in.read(buffer)) != -1) { out.write(buffer, 0, read); } in.close(); //in = null; // write the output file (You have now copied the file) out.flush(); out.close(); //out = null; return outputFile.getAbsolutePath(); } catch (FileNotFoundException fnfe1) { Log.e(TAG, fnfe1.getMessage()); } catch (Exception e) { Log.e(TAG, e.getMessage()); } return ""; } public void copyDirectory(File sourceLocation, File targetLocation) throws IOException { if (sourceLocation.isDirectory()) { if (!targetLocation.exists()) { targetLocation.mkdir(); } String[] children = sourceLocation.list(); for (int i = 0; i < sourceLocation.listFiles().length; i++) { copyDirectory(new File(sourceLocation, children[i]), new File(targetLocation, children[i])); } } else { InputStream in = new FileInputStream(sourceLocation); OutputStream out = new FileOutputStream(targetLocation); // Copy the bits from instream to outstream byte[] buf = new byte[1024]; int len; while ((len = in.read(buf)) > 0) { out.write(buf, 0, len); } in.close(); out.close(); } } }4)ItemClickSupport.java========================package com.eppico.utility; import android.support.v7.widget.RecyclerView;import android.view.View; import com.eppico.R; /** * Created by Admin on 13/12/2016. */ public class ItemClickSupport { private final RecyclerView mRecyclerView; private OnItemClickListener mOnItemClickListener; private OnItemLongClickListener mOnItemLongClickListener; private View.OnClickListener mOnClickListener = new View.OnClickListener() { @Override public void onClick(View v) { if (mOnItemClickListener != null) { RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v); mOnItemClickListener.onItemClicked(mRecyclerView, holder.getAdapterPosition(), v); } } }; private View.OnLongClickListener mOnLongClickListener = new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { if (mOnItemLongClickListener != null) { RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v); return mOnItemLongClickListener.onItemLongClicked(mRecyclerView, holder.getAdapterPosition(), v); } return false; } }; private RecyclerView.OnChildAttachStateChangeListener mAttachListener = new RecyclerView.OnChildAttachStateChangeListener() { @Override public void onChildViewAttachedToWindow(View view) { if (mOnItemClickListener != null) { view.setOnClickListener(mOnClickListener); } if (mOnItemLongClickListener != null) { view.setOnLongClickListener(mOnLongClickListener); } } @Override public void onChildViewDetachedFromWindow(View view) { } }; private ItemClickSupport(RecyclerView recyclerView) { mRecyclerView = recyclerView; mRecyclerView.setTag(R.id.item_click_support, this); mRecyclerView.addOnChildAttachStateChangeListener(mAttachListener); } public static ItemClickSupport addTo(RecyclerView view) { ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support); if (support == null) { support = new ItemClickSupport(view); } return support; } public static ItemClickSupport removeFrom(RecyclerView view) { ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support); if (support != null) { support.detach(view); } return support; } public ItemClickSupport setOnItemClickListener(OnItemClickListener listener) { mOnItemClickListener = listener; return this; } public ItemClickSupport setOnItemLongClickListener(OnItemLongClickListener listener) { mOnItemLongClickListener = listener; return this; } private void detach(RecyclerView view) { view.removeOnChildAttachStateChangeListener(mAttachListener); view.setTag(R.id.item_click_support, null); } public interface OnItemClickListener { void onItemClicked(RecyclerView recyclerView, int position, View v); } public interface OnItemLongClickListener { boolean onItemLongClicked(RecyclerView recyclerView, int position, View v); } }5)LocationHelper.java========================package com.eppico.utility; import android.Manifest;import android.app.Activity;import android.content.pm.PackageManager;import android.location.Location;import android.os.Bundle;import android.support.annotation.NonNull;import android.support.annotation.Nullable;import android.support.v4.app.ActivityCompat;import android.util.Log; import com.google.android.gms.common.ConnectionResult;import com.google.android.gms.common.GoogleApiAvailability;import com.google.android.gms.common.api.GoogleApiClient;import com.google.android.gms.location.LocationListener;import com.google.android.gms.location.LocationRequest;import com.google.android.gms.location.LocationServices; /** * Created by rushil on 13/12/16. */ public class LocationHelper implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener { private static LocationHelper locationHelper; private LocationRequest mLocationRequest; private GoogleApiClient mGoogleApiClient; private static final int REQUEST_CODE_RECOVER_PLAY_SERVICES = 101; private static final int REQUEST_CHECK_SETTINGS = 102; private static final int REQ_PERMISSION_LOCATION = 103; private Activity activity; Location mLastLocation; public static LocationHelper getInstance() { if (locationHelper == null) locationHelper = new LocationHelper(); return locationHelper; } private void getCurrentLatLong(Activity activity) { this.activity = activity; buildGoogleApiClient(activity); if (checkLocationPermission(activity)) { //Connect Google API client if (checkGooglePlayServices(activity)) { /**Note: This dialog is hide at getNearestLocation() and onLocationChanged()*/ //customDialog.show(getActivity(),getString(R.string.txtLoadingFindingLocation),false); CustomDialog.getInstance().show(activity,false); buildGoogleApiClient(activity); //prepare connection request createLocationRequest(); } } } private synchronized void buildGoogleApiClient(Activity activity) { mGoogleApiClient = new GoogleApiClient.Builder(activity) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .addApi(LocationServices.API) .build(); } private boolean checkLocationPermission(Activity activity) { // Check if the Location permission is already available. if (ActivityCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { // Camera permission has not been granted. requestLocationPermission(activity); } else { // Camera permissions is already available, show the camera preview. return true; } return false; } /** * Requests the Location permission. * If the permission has been denied previously, a SnackBar will prompt the user to grant the * permission, otherwise it is requested directly. */ private void requestLocationPermission(Activity activity) { ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQ_PERMISSION_LOCATION); } /** * Initialize location request */ protected void createLocationRequest() { mLocationRequest = new LocationRequest(); mLocationRequest.setInterval(20000); mLocationRequest.setFastestInterval(5000); mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY); if (checkLocationPermission(activity)) { LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this); } //settingsRequest(); } private boolean checkGooglePlayServices(Activity activity) { GoogleApiAvailability googleAPI = GoogleApiAvailability.getInstance(); int result = googleAPI.isGooglePlayServicesAvailable(activity); if (result != ConnectionResult.SUCCESS) { if (googleAPI.isUserResolvableError(result)) { googleAPI.getErrorDialog(activity, result, REQUEST_CODE_RECOVER_PLAY_SERVICES).show(); } return false; } return true; } protected void startLocationUpdates() { if (checkLocationPermission(activity)) { LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this); } } /** * Stop Location update listener */ private void stopLocationUpdates() { if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) { LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this); } } @Override public void onConnected(@Nullable Bundle bundle) { startLocationUpdates(); } @Override public void onConnectionSuspended(int i) { } @Override public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { } @Override public void onLocationChanged(Location location) { MyLog.v("onLocationChanged","Location: " + location.getLatitude() + " : " + location.getLongitude()); } }6)MyLog.java==============package com.eppico.utility; import android.os.Environment;import android.support.annotation.NonNull;import android.util.Log; import com.eppico.BuildConfig; import java.io.BufferedWriter;import java.io.File;import java.io.FileWriter;import java.io.IOException; public class MyLog { //private static final String TAG = "SKApp"; //public static boolean IS_DEBUG = BuildConfig.DEBUG; public static void i(@NonNull String tag, final String msg) { if (BuildConfig.DEBUG) Log.i(tag, msg); } public static void v(@NonNull String tag, final String msg) { if (BuildConfig.DEBUG) Log.v(tag, msg); } public static void d(@NonNull String tag, final String msg) { if (BuildConfig.DEBUG) Log.d(tag, msg); } public static void e(@NonNull String tag, final String msg) { if (BuildConfig.DEBUG) Log.e(tag, msg); } public static void w(@NonNull String tag, final String msg) { if (BuildConfig.DEBUG) Log.w(tag, msg); } public static void writeLogIntoFile(@NonNull String text,@NonNull String fileName) { final File logFile = new File(Environment.getExternalStorageDirectory() + fileName + ".txt"); if (!logFile.exists()) { try { logFile.createNewFile(); } catch (final IOException e) { e.printStackTrace(); } } try { // BufferedWriter for performance, true to set append to file flag final BufferedWriter buf = new BufferedWriter(new FileWriter(logFile, true)); buf.append(text); buf.newLine(); buf.close(); } catch (final IOException e) { e.printStackTrace(); } } }7)PermissionUtil.java=============================/** Copyright 2015 The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/ package com.eppico.utility; import android.Manifest;import android.app.Activity;import android.content.pm.PackageManager; import java.util.ArrayList; /** * Utility class that wraps access to the runtime permissions API in M and provides basic helper * methods. */public class PermissionUtil { static PermissionUtil permissionUtil; public static PermissionUtil getInstance() { if(permissionUtil==null) permissionUtil=new PermissionUtil(); return permissionUtil; } /** * Check that all given permissions have been granted by verifying that each entry in the * given array is of the value {@link PackageManager#PERMISSION_GRANTED}. * * @see Activity#onRequestPermissionsResult(int, String[], int[]) */ public static boolean verifyPermissions(int[] grantResults) { // At least one result must be checked. if(grantResults.length < 1){ return false; } // Verify that each required permission has been granted, otherwise return false. for (int result : grantResults) { if (result != PackageManager.PERMISSION_GRANTED) { return false; } } return true; } public ArrayList<String> verifyPermissions(String permissions[],int[] grantResults) { // At least one result must be checked. if(permissions!=null && grantResults!=null && permissions.length>0 && grantResults.length>0) { ArrayList<String> listPermissionsNotGranted=new ArrayList<String>(); // Verify that each required permission has been granted, otherwise return false. for (int i=0;i<grantResults.length;i++) { if (grantResults[i] != PackageManager.PERMISSION_GRANTED) { listPermissionsNotGranted.add(permissions[i]); } } return listPermissionsNotGranted; } return null; } public ArrayList<String> getCameraPermissionsList() { ArrayList<String> listPermissionsNeed=new ArrayList<String>(); listPermissionsNeed.add(Manifest.permission.CAMERA); listPermissionsNeed.add(Manifest.permission.WRITE_EXTERNAL_STORAGE); return listPermissionsNeed; } public ArrayList<String> getGalleryPermission() { ArrayList<String> listPermissionsNeed=new ArrayList<String>(); listPermissionsNeed.add(Manifest.permission.WRITE_EXTERNAL_STORAGE); return listPermissionsNeed; } }8)PrefHelper.java=====================package com.eppico.utility; import android.content.SharedPreferences.Editor;import android.util.Log; import com.eppico.MyApplication; import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.util.ArrayList;import java.util.Map; /** * This class is help to store/get data into preference * */public class PrefHelper { public static void setString(String key, String value) { final Editor editor = MyApplication.myPref.edit(); editor.putString(key, value); apply(editor); } public static String getString(String key,String defaultValue) { return MyApplication.myPref.getString(key, defaultValue); } public static void setInt(String key,int value) { final Editor editor = MyApplication.myPref.edit(); editor.putInt(key, value); apply(editor); } public static int getInt(String key,int defaultValue) { return MyApplication.myPref.getInt(key, defaultValue); } public static boolean getBoolean(String key,boolean defaultValue) { return MyApplication.myPref.getBoolean(key, defaultValue); } public static void setBoolean(String key,boolean value) { final Editor editor = MyApplication.myPref.edit(); editor.putBoolean(key, value); apply(editor); } public static long getLong(String key,long defaultValue) { return MyApplication.myPref.getLong(key, defaultValue); } public static void setLong(String key,long value) { final Editor editor = MyApplication.myPref.edit(); editor.putLong(key, value); apply(editor); } public static double getDouble(String key,double defaultValue) { // return MyApplication.myPref.getLong(key, defaultValue); return Double.longBitsToDouble(MyApplication.myPref.getLong(key, Double.doubleToLongBits(defaultValue))); } public static void setDouble(String key,double value) { final Editor editor = MyApplication.myPref.edit(); editor.putLong(key, Double.doubleToRawLongBits(value)); apply(editor); } public static void deletePreference(String key) { final Editor editor = MyApplication.myPref.edit(); editor.remove(key); apply(editor); } public static void deletePreferences(String[] keys) { if(keys!=null && keys.length>0) { // Editor editor = null; for(int i=0;i<keys.length;i++) { final Editor editor= MyApplication.myPref.edit(); editor.remove(keys[i]); apply(editor); } } } public static void deleteAllPreferences() { final Editor editor = MyApplication.myPref.edit(); editor.clear(); apply(editor); } /*Delete all preference of app except passed argument*/ public static void deletePreferencesExcept(ArrayList<String> keysNotDelete) { //SharedPreferences pref=PreferenceManager.getDefaultSharedPreferences(MyApplication.appInstance); Map<String,?> keys = MyApplication.myPref.getAll(); for(Map.Entry<String,?> entry : keys.entrySet()){ Log.d("map values", entry.getKey() + ": " + entry.getValue().toString()); if(!keysNotDelete.contains(entry.getKey())) { final Editor editor= MyApplication.myPref.edit(); editor.remove(entry.getKey()); apply(editor); } } } // Faster pref saving for high performance private static final Method sApplyMethod = findApplyMethod(); private static Method findApplyMethod() { try { final Class<Editor> cls = Editor.class; return cls.getMethod("apply"); } catch (final NoSuchMethodException unused) { // fall through } return null; } public static void apply(final Editor editor) { if (sApplyMethod != null) { try { sApplyMethod.invoke(editor); return; } catch (final InvocationTargetException unused) { // fall through } catch (final IllegalAccessException unused) { // fall through } } editor.commit(); } }9)TimeAgo.java================package com.eppico.utility; import android.content.Context;import com.eppico.R;import java.util.Arrays;import java.util.Calendar;import java.util.List;import java.util.concurrent.TimeUnit; public class TimeAgo { private static List<Long> times; private static List<String> timesString; private static TimeAgo timeAgo; public static TimeAgo getInstance(){ if(timeAgo == null){ timeAgo = new TimeAgo(); } return timeAgo; } public void init(Context context) { if(times == null) { times = Arrays.asList( TimeUnit.DAYS.toMillis(365), TimeUnit.DAYS.toMillis(30), TimeUnit.DAYS.toMillis(1), TimeUnit.HOURS.toMillis(1), TimeUnit.MINUTES.toMillis(1), TimeUnit.SECONDS.toMillis(1)); } if(timesString == null) { timesString = Arrays.asList(context.getString(R.string.strYear), context.getString(R.string.strMonth), context.getString(R.string.strDay), context.getString(R.string.strHour), context.getString(R.string.strMinute), context.getString(R.string.strSecond)); } } public String toDuration(Context context, long millisec) { init(context); long todayMilli= Calendar.getInstance().getTimeInMillis(); long duration=todayMilli-millisec; StringBuffer res = new StringBuffer(); for(int i=0;i< times.size(); i++) { Long current = times.get(i); long temp = duration/current; if(temp>0) { res.append(temp).append(" ").append( timesString.get(i)).append(temp > 1 ? context.getString(R.string.strS) : "") .append(" " + context.getString(R.string.strAgo)); break; } } if("".equals(res.toString())) return context.getString(R.string.strJustNow); else return res.toString(); } public static void main(String args[]) {} // /**// * Function to convert millisecond in human readable date format.// * @param millisec contains millisecond value.// * @return human readable format date.// */// public String toGetDuration(Context mContext,long millisec) {// init(mContext);// millisec= millisec * 1000;// long todayMilli= Calendar.getInstance().getTimeInMillis();// long duration=todayMilli-millisec;// StringBuffer res = new StringBuffer();// for(int i=0;i< times.size(); i++) {// Long current = times.get(i);// long temp = duration/current;//// if(temp>0) {// res.append(temp).append(" ").append(timesString.get(i) ).append(temp > 1 ? mContext.getString(R.string.strS) : "")// .append(" " + mContext.getString(R.string.strAgo));// break;// }// }//// if("".equals(res.toString()))// return mContext.getString(R.string.strJustNow);// else// return res.toString();// }}10)ToastHelper.java====================package com.eppico.utility; import android.content.Context;import android.support.annotation.NonNull;import android.widget.Toast; public class ToastHelper { private static Toast toast = null; private static ToastHelper toastHelper; public static ToastHelper getInstance() { if (toastHelper == null) toastHelper = new ToastHelper(); return toastHelper; } public void showToast(@NonNull Context context, String message) { if (toast != null) { toast.cancel(); } toast = Toast.makeText(context, message, Toast.LENGTH_SHORT); toast.show(); } public void showToast(@NonNull Context context, String message, int duration) { if (toast != null) { toast.cancel(); } toast = Toast.makeText(context, message, duration); toast.show(); } /*public void showToast(@NonNull Context context, String message, int duration, int gravity) { if (toast != null) { toast.cancel(); } toast = Toast.makeText(context, message, duration); toast.setGravity(gravity, 0, 0); toast.show(); }*/}11)Utils.java==============1)FloatingActionButton.javapackage com.eppico.utility; import android.annotation.SuppressLint;import android.app.AlertDialog;import android.content.Context;import android.content.DialogInterface;import android.content.SharedPreferences;import android.content.pm.PackageInfo;import android.content.pm.PackageManager;import android.content.pm.Signature;import android.database.Cursor;import android.net.ConnectivityManager;import android.net.Uri;import android.os.Environment;import android.provider.MediaStore;import android.support.annotation.NonNull;import android.support.design.widget.Snackbar;import android.util.Base64;import android.util.DisplayMetrics;import android.util.Log;import android.view.MotionEvent;import android.view.View;import android.view.ViewGroup;import android.view.WindowManager;import android.view.inputmethod.InputMethodManager;import android.widget.EditText;import android.widget.Toast; import com.eppico.R; import org.apache.commons.lang3.StringEscapeUtils; import java.io.File;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.Calendar;import java.util.Date;import java.util.regex.Matcher;import java.util.regex.Pattern; /** * Created by manisha on 12/12/16. */public class Utils { private static Utils utils; public static Utils getInstance() { if (utils == null) utils = new Utils(); return utils; } public boolean isEmailValid(String email) { String expression = "^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$"; CharSequence inputStr = email; boolean flag = false; Pattern pattern = Pattern.compile(expression, Pattern.CASE_INSENSITIVE); Matcher matcher = pattern.matcher(inputStr); if (matcher.matches()) { flag = true; } return flag; } public boolean checkInternetConnection(Context context) { ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); // test for connection if (cm.getActiveNetworkInfo() != null && cm.getActiveNetworkInfo().isAvailable() && cm.getActiveNetworkInfo().isConnected()) { return true; } else { Log.v("", "Internet Connection Not Available"); //Toast.makeText(context, context.getResources().getString(R.string.network_connectivity_not_available), Toast.LENGTH_SHORT).show(); return false; } } public String generateHashKey(Context context) { String hashKey = ""; try { PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES); for (Signature signature : info.signatures) { MessageDigest md = MessageDigest.getInstance("SHA"); md.update(signature.toByteArray()); hashKey = Base64.encodeToString(md.digest(), Base64.DEFAULT); MyLog.v("TAG", "Hash Key:" + hashKey); } } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return hashKey; } @SuppressLint("NewApi") public static boolean validateString(String object) { boolean flag = false; if (object != null && !object.equalsIgnoreCase("null") && !object.equalsIgnoreCase("(null)") && !object.isEmpty() && !object.equalsIgnoreCase("(null)")) { flag = true; } return flag; } /** * Images is stored in share directory while sharing, or profile images while change profile image, delete those images */ public void deleteTempImagesDirectory(@NonNull Context context) { try { // File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), Constants.DIR_MAIN); File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), context.getString(R.string.app_name)); if (mediaStorageDir.exists()) { // File shareDirectory = new File(mediaStorageDir + File.separator + Constants.DIR_SHARE); //Delete Settings directory where we save logged in user image while login File shareDirectory = new File(mediaStorageDir + File.separator + context.getString(R.string.dirSettings)); if (shareDirectory.exists()) deleteRecursive(shareDirectory); //Delete Media directory. Which contain all images and videos use for upload spot and post File dirMedia = new File(mediaStorageDir + File.separator + context.getString(R.string.dirMedia)); if (dirMedia.exists()) deleteRecursive(dirMedia); } } catch (Exception e) { e.printStackTrace(); } } /** * Delete all files and directory itself */ private void deleteRecursive(File fileOrDirectory) { if (fileOrDirectory.isDirectory()) for (File child : fileOrDirectory.listFiles()) deleteRecursive(child); fileOrDirectory.delete(); } public void hideKeyboard(View v, Context context) { InputMethodManager mgr = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); mgr.hideSoftInputFromWindow(v.getWindowToken(), 0); } public void showKeyboard(View v, Context context) { /* * InputMethodManager mgr = * (InputMethodManager)context.getSystemService( * Context.INPUT_METHOD_SERVICE); mgr.showSoftInput(v, 0); */ InputMethodManager inputMethodManager = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); inputMethodManager.toggleSoftInputFromWindow(v.getApplicationWindowToken(), InputMethodManager.SHOW_FORCED, 0); } /** * Function is used to hide keyboard while user click outside of keyboard on screen. * @param view contains parent view id to get all child views. */ @SuppressLint("ClickableViewAccessibility") public void setupOutSideTouchHideKeyboard(final View view) { if(view==null) return; // Set up touch listener for non-text box views to hide keyboard. if (!(view instanceof EditText)) { view.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { hideKeyboard(view,view.getContext()); return false; } }); } // If a layout container, iterate over children and seed recursion. if (view instanceof ViewGroup) { for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) { View innerView = ((ViewGroup) view).getChildAt(i); setupOutSideTouchHideKeyboard(innerView); } } } public int[] getScreenWidthHeight(Context context) { WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); /*Display display = wm.getDefaultDisplay(); int width = display.getWidth(); // deprecated int height = display.getHeight(); // deprecated*/ DisplayMetrics displaymetrics = new DisplayMetrics(); wm.getDefaultDisplay().getMetrics(displaymetrics); int screenWidth = displaymetrics.widthPixels; int screenHeight = displaymetrics.heightPixels; int[] wh = { screenWidth, screenHeight };// int[] wh = { width, height }; return wh; } public float getFileSizeInMb(File file) { try{ if(!file.exists()) return 0; // Get length of file in bytes long fileSizeInBytes = file.length(); // Convert the bytes to Kilobytes (1 KB = 1024 Bytes) float fileSizeInKB = fileSizeInBytes / 1024; // Convert the KB to MegaBytes (1 MB = 1024 KBytes) float fileSizeInMB = fileSizeInKB / 1024; return fileSizeInMB; }catch (Exception e) { e.printStackTrace(); } return 0; } /**Return image path of given URI*/ public String getRealPathFromURI(Context context,Uri contentURI) { // Cursor cursor = getActivity().getContentResolver().query(contentURI, null, null, null, null); String[] projection = { MediaStore.Images.Media.DATA }; Cursor cursor = context.getContentResolver().query(contentURI, projection, null, null, null); //Some of gallery application is return null if (cursor == null) { return contentURI.getPath(); } else { cursor.moveToFirst(); int columnIndex = cursor.getColumnIndex(projection[0]); String picturePath = cursor.getString(columnIndex); cursor.close(); return picturePath; } } /**It will encode the unicode characters properly before sending to web server.*/ public String escapeJava(String text) { if(text!=null && text.length()>0) return StringEscapeUtils.escapeJava(text); return ""; } /**it will decode the unicode characters properly after receiving the response from web server.*/ public String unescapeJava(String text) { if(text!=null && text.length()>0) return StringEscapeUtils.unescapeJava(text); return ""; } /**Return formatted date.*/ public String getFormattedDate(Context context,String date) { try { SimpleDateFormat sdfInput = new SimpleDateFormat(context.getString(R.string.dateFormatOfAPI)); SimpleDateFormat sdfOutput = new SimpleDateFormat(context.getString(R.string.dateFormatOfApp)); return sdfOutput.format(sdfInput.parse(date)); } catch (Exception e) { e.printStackTrace(); } return ""; } /**Return formatted date of passed output format*/ public String getFormattedDate(String date, String input, String output) { try { SimpleDateFormat sdfInput = new SimpleDateFormat(input); SimpleDateFormat sdfOutput = new SimpleDateFormat(output); return sdfOutput.format(sdfInput.parse(date)); } catch (Exception e) { e.printStackTrace(); } return ""; } public String getDateDifference(Context context,String date) { Date thenDate = covertStringToDate(date); //getFormattedDate(thenDate); String displayDate = Utils.getInstance().getFormattedDate(context,date); Calendar now = Calendar.getInstance(); Calendar then = Calendar.getInstance(); now.setTime(new Date()); then.setTime(thenDate); // Get the represented date in milliseconds long nowMs = now.getTimeInMillis(); long thenMs = then.getTimeInMillis(); // Calculate difference in milliseconds long diff = nowMs - thenMs; // Calculate difference in seconds long diffSeconds = diff / 1000; long diffMinutes = diff / (60 * 1000); long diffHours = diff / (60 * 60 * 1000); long diffDays = diff / (24 * 60 * 60 * 1000); if (diffMinutes < 60) { if (diffMinutes < 0) return displayDate; else if (diffMinutes == 0) return context.getResources().getString(R.string.just_now); return diffMinutes + " " + context.getResources().getQuantityString(R.plurals.minuteAgo, (int) diffMinutes); /*if (diffMinutes == 1) return diffMinutes + " " + mContext.getResources().getString(R.string.minute_ago); else return diffMinutes + " " + mContext.getResources().getString(R.string.minutes_ago);*/ } else if (diffHours < 24) { /*if (diffHours == 1) return diffHours + " " + mContext.getResources().getString(R.string.hour_ago); else return diffHours + " " + mContext.getResources().getString(R.string.hours_ago);*/ return diffHours + " " + context.getResources().getQuantityString(R.plurals.hourAgo, (int) diffHours); } else if (diffDays < 30) { /*if (diffDays == 1) return diffDays + " " + mContext.getResources().getString(R.string.day_ago); else return diffDays + " " + mContext.getResources().getString(R.string.days_ago);*/ return diffDays + " " + context.getResources().getQuantityString(R.plurals.dayAgo, (int) diffDays); } else { return displayDate; } } public Date covertStringToDate(String strDate) { SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss"); Date date = null; try { date = formatter.parse(strDate); } catch (ParseException e) { e.printStackTrace(); } return date; } }*******************com.app.febmenu*********************===========================package com.eppico.fabmenu; import android.annotation.TargetApi;import android.content.Context;import android.content.res.ColorStateList;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.ColorFilter;import android.graphics.Outline;import android.graphics.Paint;import android.graphics.PorterDuff;import android.graphics.PorterDuffXfermode;import android.graphics.RectF;import android.graphics.Xfermode;import android.graphics.drawable.ColorDrawable;import android.graphics.drawable.Drawable;import android.graphics.drawable.LayerDrawable;import android.graphics.drawable.RippleDrawable;import android.graphics.drawable.ShapeDrawable;import android.graphics.drawable.StateListDrawable;import android.graphics.drawable.shapes.OvalShape;import android.graphics.drawable.shapes.Shape;import android.os.Build;import android.os.Parcel;import android.os.Parcelable;import android.os.SystemClock;import android.util.AttributeSet;import android.view.GestureDetector;import android.view.MotionEvent;import android.view.View;import android.view.ViewGroup;import android.view.ViewOutlineProvider;import android.view.animation.Animation;import android.view.animation.AnimationUtils;import android.widget.ImageButton;import android.widget.TextView; import com.eppico.R; public class FloatingActionButton extends ImageButton { public static final int SIZE_NORMAL = 0; public static final int SIZE_MINI = 1; int mFabSize; boolean mShowShadow; int mShadowColor; int mShadowRadius = Util.dpToPx(getContext(), 4f); int mShadowXOffset = Util.dpToPx(getContext(), 1f); int mShadowYOffset = Util.dpToPx(getContext(), 3f); private static final Xfermode PORTER_DUFF_CLEAR = new PorterDuffXfermode(PorterDuff.Mode.CLEAR); private static final long PAUSE_GROWING_TIME = 200; private static final double BAR_SPIN_CYCLE_TIME = 500; private static final int BAR_MAX_LENGTH = 270; private int mColorNormal; private int mColorPressed; private int mColorDisabled; private int mColorRipple; private Drawable mIcon; private int mIconSize = Util.dpToPx(getContext(), 24f); private Animation mShowAnimation; private Animation mHideAnimation; private String mLabelText; private OnClickListener mClickListener; private Drawable mBackgroundDrawable; private boolean mUsingElevation; private boolean mUsingElevationCompat; // Progress private boolean mProgressBarEnabled; private int mProgressWidth = Util.dpToPx(getContext(), 6f); private int mProgressColor; private int mProgressBackgroundColor; private boolean mShouldUpdateButtonPosition; private float mOriginalX = -1; private float mOriginalY = -1; private boolean mButtonPositionSaved; private RectF mProgressCircleBounds = new RectF(); private Paint mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private Paint mProgressPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private boolean mProgressIndeterminate; private long mLastTimeAnimated; private float mSpinSpeed = 195.0f; //The amount of degrees per second private long mPausedTimeWithoutGrowing = 0; private double mTimeStartGrowing; private boolean mBarGrowingFromFront = true; private int mBarLength = 16; private float mBarExtraLength; private float mCurrentProgress; private float mTargetProgress; private int mProgress; private boolean mAnimateProgress; private boolean mShouldProgressIndeterminate; private boolean mShouldSetProgress; private int mProgressMax = 100; private boolean mShowProgressBackground; public FloatingActionButton(Context context) { this(context, null); } public FloatingActionButton(Context context, AttributeSet attrs) { this(context, attrs, 0); } public FloatingActionButton(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context, attrs, defStyleAttr); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) public FloatingActionButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); init(context, attrs, defStyleAttr); } private void init(Context context, AttributeSet attrs, int defStyleAttr) { TypedArray attr = context.obtainStyledAttributes(attrs, R.styleable.FloatingActionButton, defStyleAttr, 0); mColorNormal = attr.getColor(R.styleable.FloatingActionButton_fab_colorNormal, 0xFFDA4336); mColorPressed = attr.getColor(R.styleable.FloatingActionButton_fab_colorPressed, 0xFFE75043); mColorDisabled = attr.getColor(R.styleable.FloatingActionButton_fab_colorDisabled, 0xFFAAAAAA); mColorRipple = attr.getColor(R.styleable.FloatingActionButton_fab_colorRipple, 0x99FFFFFF); mShowShadow = attr.getBoolean(R.styleable.FloatingActionButton_fab_showShadow, true); mShadowColor = attr.getColor(R.styleable.FloatingActionButton_fab_shadowColor, 0x66000000); mShadowRadius = attr.getDimensionPixelSize(R.styleable.FloatingActionButton_fab_shadowRadius, mShadowRadius); mShadowXOffset = attr.getDimensionPixelSize(R.styleable.FloatingActionButton_fab_shadowXOffset, mShadowXOffset); mShadowYOffset = attr.getDimensionPixelSize(R.styleable.FloatingActionButton_fab_shadowYOffset, mShadowYOffset); mFabSize = attr.getInt(R.styleable.FloatingActionButton_fab_size, SIZE_NORMAL); mLabelText = attr.getString(R.styleable.FloatingActionButton_fab_label); mShouldProgressIndeterminate = attr.getBoolean(R.styleable.FloatingActionButton_fab_progress_indeterminate, false); mProgressColor = attr.getColor(R.styleable.FloatingActionButton_fab_progress_color, 0xFF009688); mProgressBackgroundColor = attr.getColor(R.styleable.FloatingActionButton_fab_progress_backgroundColor, 0x4D000000); mProgressMax = attr.getInt(R.styleable.FloatingActionButton_fab_progress_max, mProgressMax); mShowProgressBackground = attr.getBoolean(R.styleable.FloatingActionButton_fab_progress_showBackground, true); if (attr.hasValue(R.styleable.FloatingActionButton_fab_progress)) { mProgress = attr.getInt(R.styleable.FloatingActionButton_fab_progress, 0); mShouldSetProgress = true; } if (attr.hasValue(R.styleable.FloatingActionButton_fab_elevationCompat)) { float elevation = attr.getDimensionPixelOffset(R.styleable.FloatingActionButton_fab_elevationCompat, 0); if (isInEditMode()) { setElevation(elevation); } else { setElevationCompat(elevation); } } initShowAnimation(attr); initHideAnimation(attr); attr.recycle(); if (isInEditMode()) { if (mShouldProgressIndeterminate) { setIndeterminate(true); } else if (mShouldSetProgress) { saveButtonOriginalPosition(); setProgress(mProgress, false); } } // updateBackground(); setClickable(true); } private void initShowAnimation(TypedArray attr) { int resourceId = attr.getResourceId(R.styleable.FloatingActionButton_fab_showAnimation, R.anim.fab_scale_up); mShowAnimation = AnimationUtils.loadAnimation(getContext(), resourceId); } private void initHideAnimation(TypedArray attr) { int resourceId = attr.getResourceId(R.styleable.FloatingActionButton_fab_hideAnimation, R.anim.fab_scale_down); mHideAnimation = AnimationUtils.loadAnimation(getContext(), resourceId); } private int getCircleSize() { return getResources().getDimensionPixelSize(mFabSize == SIZE_NORMAL ? R.dimen.fab_size_normal : R.dimen.fab_size_mini); } private int calculateMeasuredWidth() { int width = getCircleSize() + calculateShadowWidth(); if (mProgressBarEnabled) { width += mProgressWidth * 2; } return width; } private int calculateMeasuredHeight() { int height = getCircleSize() + calculateShadowHeight(); if (mProgressBarEnabled) { height += mProgressWidth * 2; } return height; } int calculateShadowWidth() { return hasShadow() ? getShadowX() * 2 : 0; } int calculateShadowHeight() { return hasShadow() ? getShadowY() * 2 : 0; } private int getShadowX() { return mShadowRadius + Math.abs(mShadowXOffset); } private int getShadowY() { return mShadowRadius + Math.abs(mShadowYOffset); } private float calculateCenterX() { return (float) (getMeasuredWidth() / 2); } private float calculateCenterY() { return (float) (getMeasuredHeight() / 2); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // super.onMeasure(widthMeasureSpec, heightMeasureSpec); setMeasuredDimension(calculateMeasuredWidth(), calculateMeasuredHeight()); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (mProgressBarEnabled) { if (mShowProgressBackground) { canvas.drawArc(mProgressCircleBounds, 360, 360, false, mBackgroundPaint); } boolean shouldInvalidate = false; if (mProgressIndeterminate) { shouldInvalidate = true; long deltaTime = SystemClock.uptimeMillis() - mLastTimeAnimated; float deltaNormalized = deltaTime * mSpinSpeed / 1000.0f; updateProgressLength(deltaTime); mCurrentProgress += deltaNormalized; if (mCurrentProgress > 360f) { mCurrentProgress -= 360f; } mLastTimeAnimated = SystemClock.uptimeMillis(); float from = mCurrentProgress - 90; float to = mBarLength + mBarExtraLength; if (isInEditMode()) { from = 0; to = 135; } canvas.drawArc(mProgressCircleBounds, from, to, false, mProgressPaint); } else { if (mCurrentProgress != mTargetProgress) { shouldInvalidate = true; float deltaTime = (float) (SystemClock.uptimeMillis() - mLastTimeAnimated) / 1000; float deltaNormalized = deltaTime * mSpinSpeed; if (mCurrentProgress > mTargetProgress) { mCurrentProgress = Math.max(mCurrentProgress - deltaNormalized, mTargetProgress); } else { mCurrentProgress = Math.min(mCurrentProgress + deltaNormalized, mTargetProgress); } mLastTimeAnimated = SystemClock.uptimeMillis(); } canvas.drawArc(mProgressCircleBounds, -90, mCurrentProgress, false, mProgressPaint); } if (shouldInvalidate) { invalidate(); } } } private void updateProgressLength(long deltaTimeInMillis) { if (mPausedTimeWithoutGrowing >= PAUSE_GROWING_TIME) { mTimeStartGrowing += deltaTimeInMillis; if (mTimeStartGrowing > BAR_SPIN_CYCLE_TIME) { mTimeStartGrowing -= BAR_SPIN_CYCLE_TIME; mPausedTimeWithoutGrowing = 0; mBarGrowingFromFront = !mBarGrowingFromFront; } float distance = (float) Math.cos((mTimeStartGrowing / BAR_SPIN_CYCLE_TIME + 1) * Math.PI) / 2 + 0.5f; float length = BAR_MAX_LENGTH - mBarLength; if (mBarGrowingFromFront) { mBarExtraLength = distance * length; } else { float newLength = length * (1 - distance); mCurrentProgress += (mBarExtraLength - newLength); mBarExtraLength = newLength; } } else { mPausedTimeWithoutGrowing += deltaTimeInMillis; } } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { saveButtonOriginalPosition(); if (mShouldProgressIndeterminate) { setIndeterminate(true); mShouldProgressIndeterminate = false; } else if (mShouldSetProgress) { setProgress(mProgress, mAnimateProgress); mShouldSetProgress = false; } else if (mShouldUpdateButtonPosition) { updateButtonPosition(); mShouldUpdateButtonPosition = false; } super.onSizeChanged(w, h, oldw, oldh); setupProgressBounds(); setupProgressBarPaints(); updateBackground(); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override public void setLayoutParams(ViewGroup.LayoutParams params) { if (params instanceof ViewGroup.MarginLayoutParams && mUsingElevationCompat) { ((ViewGroup.MarginLayoutParams) params).leftMargin += getShadowX(); ((ViewGroup.MarginLayoutParams) params).topMargin += getShadowY(); ((ViewGroup.MarginLayoutParams) params).rightMargin += getShadowX(); ((ViewGroup.MarginLayoutParams) params).bottomMargin += getShadowY(); } super.setLayoutParams(params); } void updateBackground() { LayerDrawable layerDrawable; if (hasShadow()) { layerDrawable = new LayerDrawable(new Drawable[]{ new Shadow(), createFillDrawable(), getIconDrawable() }); } else { layerDrawable = new LayerDrawable(new Drawable[]{ createFillDrawable(), getIconDrawable() }); } int iconSize = -1; if (getIconDrawable() != null) { iconSize = Math.max(getIconDrawable().getIntrinsicWidth(), getIconDrawable().getIntrinsicHeight()); } int iconOffset = (getCircleSize() - (iconSize > 0 ? iconSize : mIconSize)) / 2; int circleInsetHorizontal = hasShadow() ? mShadowRadius + Math.abs(mShadowXOffset) : 0; int circleInsetVertical = hasShadow() ? mShadowRadius + Math.abs(mShadowYOffset) : 0; if (mProgressBarEnabled) { circleInsetHorizontal += mProgressWidth; circleInsetVertical += mProgressWidth; } /*layerDrawable.setLayerInset( mShowShadow ? 1 : 0, circleInsetHorizontal, circleInsetVertical, circleInsetHorizontal, circleInsetVertical );*/ layerDrawable.setLayerInset( hasShadow() ? 2 : 1, circleInsetHorizontal + iconOffset, circleInsetVertical + iconOffset, circleInsetHorizontal + iconOffset, circleInsetVertical + iconOffset ); setBackgroundCompat(layerDrawable); } protected Drawable getIconDrawable() { if (mIcon != null) { return mIcon; } else { return new ColorDrawable(Color.TRANSPARENT); } } @TargetApi(Build.VERSION_CODES.LOLLIPOP) private Drawable createFillDrawable() { StateListDrawable drawable = new StateListDrawable(); drawable.addState(new int[]{-android.R.attr.state_enabled}, createCircleDrawable(mColorDisabled)); drawable.addState(new int[]{android.R.attr.state_pressed}, createCircleDrawable(mColorPressed)); drawable.addState(new int[]{}, createCircleDrawable(mColorNormal)); if (Util.hasLollipop()) { RippleDrawable ripple = new RippleDrawable(new ColorStateList(new int[][]{{}}, new int[]{mColorRipple}), drawable, null); setOutlineProvider(new ViewOutlineProvider() { @Override public void getOutline(View view, Outline outline) { outline.setOval(0, 0, view.getWidth(), view.getHeight()); } }); setClipToOutline(true); mBackgroundDrawable = ripple; return ripple; } mBackgroundDrawable = drawable; return drawable; } private Drawable createCircleDrawable(int color) { CircleDrawable shapeDrawable = new CircleDrawable(new OvalShape()); shapeDrawable.getPaint().setColor(color); return shapeDrawable; } @SuppressWarnings("deprecation") @TargetApi(Build.VERSION_CODES.JELLY_BEAN) private void setBackgroundCompat(Drawable drawable) { if (Util.hasJellyBean()) { setBackground(drawable); } else { setBackgroundDrawable(drawable); } } private void saveButtonOriginalPosition() { if (!mButtonPositionSaved) { if (mOriginalX == -1) { mOriginalX = getX(); } if (mOriginalY == -1) { mOriginalY = getY(); } mButtonPositionSaved = true; } } private void updateButtonPosition() { float x; float y; if (mProgressBarEnabled) { x = mOriginalX > getX() ? getX() + mProgressWidth : getX() - mProgressWidth; y = mOriginalY > getY() ? getY() + mProgressWidth : getY() - mProgressWidth; } else { x = mOriginalX; y = mOriginalY; } setX(x); setY(y); } private void setupProgressBarPaints() { mBackgroundPaint.setColor(mProgressBackgroundColor); mBackgroundPaint.setStyle(Paint.Style.STROKE); mBackgroundPaint.setStrokeWidth(mProgressWidth); mProgressPaint.setColor(mProgressColor); mProgressPaint.setStyle(Paint.Style.STROKE); mProgressPaint.setStrokeWidth(mProgressWidth); } private void setupProgressBounds() { int circleInsetHorizontal = hasShadow() ? getShadowX() : 0; int circleInsetVertical = hasShadow() ? getShadowY() : 0; mProgressCircleBounds = new RectF( circleInsetHorizontal + mProgressWidth / 2, circleInsetVertical + mProgressWidth / 2, calculateMeasuredWidth() - circleInsetHorizontal - mProgressWidth / 2, calculateMeasuredHeight() - circleInsetVertical - mProgressWidth / 2 ); } Animation getShowAnimation() { return mShowAnimation; } Animation getHideAnimation() { return mHideAnimation; } void playShowAnimation() { mHideAnimation.cancel(); startAnimation(mShowAnimation); } void playHideAnimation() { mShowAnimation.cancel(); startAnimation(mHideAnimation); } OnClickListener getOnClickListener() { return mClickListener; } Label getLabelView() { return (Label) getTag(R.id.fab_label); } void setColors(int colorNormal, int colorPressed, int colorRipple) { mColorNormal = colorNormal; mColorPressed = colorPressed; mColorRipple = colorRipple; } @TargetApi(Build.VERSION_CODES.LOLLIPOP) void onActionDown() { if (mBackgroundDrawable instanceof StateListDrawable) { StateListDrawable drawable = (StateListDrawable) mBackgroundDrawable; drawable.setState(new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed}); } else if (Util.hasLollipop()) { RippleDrawable ripple = (RippleDrawable) mBackgroundDrawable; ripple.setState(new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed}); ripple.setHotspot(calculateCenterX(), calculateCenterY()); ripple.setVisible(true, true); } } @TargetApi(Build.VERSION_CODES.LOLLIPOP) void onActionUp() { if (mBackgroundDrawable instanceof StateListDrawable) { StateListDrawable drawable = (StateListDrawable) mBackgroundDrawable; drawable.setState(new int[]{android.R.attr.state_enabled}); } else if (Util.hasLollipop()) { RippleDrawable ripple = (RippleDrawable) mBackgroundDrawable; ripple.setState(new int[]{android.R.attr.state_enabled}); ripple.setHotspot(calculateCenterX(), calculateCenterY()); ripple.setVisible(true, true); } } @Override public boolean onTouchEvent(MotionEvent event) { if (mClickListener != null && isEnabled()) { Label label = (Label) getTag(R.id.fab_label); if (label == null) return super.onTouchEvent(event); int action = event.getAction(); switch (action) { case MotionEvent.ACTION_UP: if (label != null) { label.onActionUp(); } onActionUp(); break; case MotionEvent.ACTION_CANCEL: if (label != null) { label.onActionUp(); } onActionUp(); break; } mGestureDetector.onTouchEvent(event); } return super.onTouchEvent(event); } GestureDetector mGestureDetector = new GestureDetector(getContext(), new GestureDetector.SimpleOnGestureListener() { @Override public boolean onDown(MotionEvent e) { Label label = (Label) getTag(R.id.fab_label); if (label != null) { label.onActionDown(); } onActionDown(); return super.onDown(e); } @Override public boolean onSingleTapUp(MotionEvent e) { Label label = (Label) getTag(R.id.fab_label); if (label != null) { label.onActionUp(); } onActionUp(); return super.onSingleTapUp(e); } }); @Override public Parcelable onSaveInstanceState() { Parcelable superState = super.onSaveInstanceState(); ProgressSavedState ss = new ProgressSavedState(superState); ss.mCurrentProgress = this.mCurrentProgress; ss.mTargetProgress = this.mTargetProgress; ss.mSpinSpeed = this.mSpinSpeed; ss.mProgressWidth = this.mProgressWidth; ss.mProgressColor = this.mProgressColor; ss.mProgressBackgroundColor = this.mProgressBackgroundColor; ss.mShouldProgressIndeterminate = this.mProgressIndeterminate; ss.mShouldSetProgress = this.mProgressBarEnabled && mProgress > 0 && !this.mProgressIndeterminate; ss.mProgress = this.mProgress; ss.mAnimateProgress = this.mAnimateProgress; ss.mShowProgressBackground = this.mShowProgressBackground; return ss; } @Override public void onRestoreInstanceState(Parcelable state) { if (!(state instanceof ProgressSavedState)) { super.onRestoreInstanceState(state); return; } ProgressSavedState ss = (ProgressSavedState) state; super.onRestoreInstanceState(ss.getSuperState()); this.mCurrentProgress = ss.mCurrentProgress; this.mTargetProgress = ss.mTargetProgress; this.mSpinSpeed = ss.mSpinSpeed; this.mProgressWidth = ss.mProgressWidth; this.mProgressColor = ss.mProgressColor; this.mProgressBackgroundColor = ss.mProgressBackgroundColor; this.mShouldProgressIndeterminate = ss.mShouldProgressIndeterminate; this.mShouldSetProgress = ss.mShouldSetProgress; this.mProgress = ss.mProgress; this.mAnimateProgress = ss.mAnimateProgress; this.mShowProgressBackground = ss.mShowProgressBackground; this.mLastTimeAnimated = SystemClock.uptimeMillis(); } private class CircleDrawable extends ShapeDrawable { private int circleInsetHorizontal; private int circleInsetVertical; private CircleDrawable() { } private CircleDrawable(Shape s) { super(s); circleInsetHorizontal = hasShadow() ? mShadowRadius + Math.abs(mShadowXOffset) : 0; circleInsetVertical = hasShadow() ? mShadowRadius + Math.abs(mShadowYOffset) : 0; if (mProgressBarEnabled) { circleInsetHorizontal += mProgressWidth; circleInsetVertical += mProgressWidth; } } @Override public void draw(Canvas canvas) { setBounds(circleInsetHorizontal, circleInsetVertical, calculateMeasuredWidth() - circleInsetHorizontal, calculateMeasuredHeight() - circleInsetVertical); super.draw(canvas); } } private class Shadow extends Drawable { private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private Paint mErase = new Paint(Paint.ANTI_ALIAS_FLAG); private float mRadius; private Shadow() { this.init(); } private void init() { setLayerType(LAYER_TYPE_SOFTWARE, null); mPaint.setStyle(Paint.Style.FILL); mPaint.setColor(mColorNormal); mErase.setXfermode(PORTER_DUFF_CLEAR); if (!isInEditMode()) { mPaint.setShadowLayer(mShadowRadius, mShadowXOffset, mShadowYOffset, mShadowColor); } mRadius = getCircleSize() / 2; if (mProgressBarEnabled && mShowProgressBackground) { mRadius += mProgressWidth; } } @Override public void draw(Canvas canvas) { canvas.drawCircle(calculateCenterX(), calculateCenterY(), mRadius, mPaint); canvas.drawCircle(calculateCenterX(), calculateCenterY(), mRadius, mErase); } @Override public void setAlpha(int alpha) { } @Override public void setColorFilter(ColorFilter cf) { } @Override public int getOpacity() { return 0; } } static class ProgressSavedState extends BaseSavedState { float mCurrentProgress; float mTargetProgress; float mSpinSpeed; int mProgress; int mProgressWidth; int mProgressColor; int mProgressBackgroundColor; boolean mProgressBarEnabled; boolean mProgressBarVisibilityChanged; boolean mProgressIndeterminate; boolean mShouldProgressIndeterminate; boolean mShouldSetProgress; boolean mAnimateProgress; boolean mShowProgressBackground; ProgressSavedState(Parcelable superState) { super(superState); } private ProgressSavedState(Parcel in) { super(in); this.mCurrentProgress = in.readFloat(); this.mTargetProgress = in.readFloat(); this.mProgressBarEnabled = in.readInt() != 0; this.mSpinSpeed = in.readFloat(); this.mProgress = in.readInt(); this.mProgressWidth = in.readInt(); this.mProgressColor = in.readInt(); this.mProgressBackgroundColor = in.readInt(); this.mProgressBarVisibilityChanged = in.readInt() != 0; this.mProgressIndeterminate = in.readInt() != 0; this.mShouldProgressIndeterminate = in.readInt() != 0; this.mShouldSetProgress = in.readInt() != 0; this.mAnimateProgress = in.readInt() != 0; this.mShowProgressBackground = in.readInt() != 0; } @Override public void writeToParcel(Parcel out, int flags) { super.writeToParcel(out, flags); out.writeFloat(this.mCurrentProgress); out.writeFloat(this.mTargetProgress); out.writeInt((mProgressBarEnabled ? 1 : 0)); out.writeFloat(this.mSpinSpeed); out.writeInt(this.mProgress); out.writeInt(this.mProgressWidth); out.writeInt(this.mProgressColor); out.writeInt(this.mProgressBackgroundColor); out.writeInt(this.mProgressBarVisibilityChanged ? 1 : 0); out.writeInt(this.mProgressIndeterminate ? 1 : 0); out.writeInt(this.mShouldProgressIndeterminate ? 1 : 0); out.writeInt(this.mShouldSetProgress ? 1 : 0); out.writeInt(this.mAnimateProgress ? 1 : 0); out.writeInt(this.mShowProgressBackground ? 1 : 0); } public static final Parcelable.Creator<ProgressSavedState> CREATOR = new Parcelable.Creator<ProgressSavedState>() { public ProgressSavedState createFromParcel(Parcel in) { return new ProgressSavedState(in); } public ProgressSavedState[] newArray(int size) { return new ProgressSavedState[size]; } }; } /* ===== API methods ===== */ @Override public void setImageDrawable(Drawable drawable) { if (mIcon != drawable) { mIcon = drawable; updateBackground(); } } @Override public void setImageResource(int resId) { Drawable drawable = getResources().getDrawable(resId); if (mIcon != drawable) { mIcon = drawable; updateBackground(); } } @Override public void setOnClickListener(final OnClickListener l) { super.setOnClickListener(l); mClickListener = l; View label = (View) getTag(R.id.fab_label); if (label != null) { label.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (mClickListener != null) { mClickListener.onClick(FloatingActionButton.this); } } }); } } /** * Sets the size of the <b>FloatingActionButton</b> and invalidates its layout. * * @param size size of the <b>FloatingActionButton</b>. Accepted values: SIZE_NORMAL, SIZE_MINI. */ public void setButtonSize(int size) { if (size != SIZE_NORMAL && size != SIZE_MINI) { throw new IllegalArgumentException("Use @FabSize constants only!"); } if (mFabSize != size) { mFabSize = size; updateBackground(); } } public int getButtonSize() { return mFabSize; } public void setColorNormal(int color) { if (mColorNormal != color) { mColorNormal = color; updateBackground(); } } public void setColorNormalResId(int colorResId) { setColorNormal(getResources().getColor(colorResId)); } public int getColorNormal() { return mColorNormal; } public void setColorPressed(int color) { if (color != mColorPressed) { mColorPressed = color; updateBackground(); } } public void setColorPressedResId(int colorResId) { setColorPressed(getResources().getColor(colorResId)); } public int getColorPressed() { return mColorPressed; } public void setColorRipple(int color) { if (color != mColorRipple) { mColorRipple = color; updateBackground(); } } public void setColorRippleResId(int colorResId) { setColorRipple(getResources().getColor(colorResId)); } public int getColorRipple() { return mColorRipple; } public void setColorDisabled(int color) { if (color != mColorDisabled) { mColorDisabled = color; updateBackground(); } } public void setColorDisabledResId(int colorResId) { setColorDisabled(getResources().getColor(colorResId)); } public int getColorDisabled() { return mColorDisabled; } public void setShowShadow(boolean show) { if (mShowShadow != show) { mShowShadow = show; updateBackground(); } } public boolean hasShadow() { return !mUsingElevation && mShowShadow; } /** * Sets the shadow radius of the <b>FloatingActionButton</b> and invalidates its layout. * * @param dimenResId the resource identifier of the dimension */ public void setShadowRadius(int dimenResId) { int shadowRadius = getResources().getDimensionPixelSize(dimenResId); if (mShadowRadius != shadowRadius) { mShadowRadius = shadowRadius; requestLayout(); updateBackground(); } } /** * Sets the shadow radius of the <b>FloatingActionButton</b> and invalidates its layout. * <p> * Must be specified in density-independent (dp) pixels, which are then converted into actual * pixels (px). * * @param shadowRadiusDp shadow radius specified in density-independent (dp) pixels */ public void setShadowRadius(float shadowRadiusDp) { mShadowRadius = Util.dpToPx(getContext(), shadowRadiusDp); requestLayout(); updateBackground(); } public int getShadowRadius() { return mShadowRadius; } /** * Sets the shadow x offset of the <b>FloatingActionButton</b> and invalidates its layout. * * @param dimenResId the resource identifier of the dimension */ public void setShadowXOffset(int dimenResId) { int shadowXOffset = getResources().getDimensionPixelSize(dimenResId); if (mShadowXOffset != shadowXOffset) { mShadowXOffset = shadowXOffset; requestLayout(); updateBackground(); } } /** * Sets the shadow x offset of the <b>FloatingActionButton</b> and invalidates its layout. * <p> * Must be specified in density-independent (dp) pixels, which are then converted into actual * pixels (px). * * @param shadowXOffsetDp shadow radius specified in density-independent (dp) pixels */ public void setShadowXOffset(float shadowXOffsetDp) { mShadowXOffset = Util.dpToPx(getContext(), shadowXOffsetDp); requestLayout(); updateBackground(); } public int getShadowXOffset() { return mShadowXOffset; } /** * Sets the shadow y offset of the <b>FloatingActionButton</b> and invalidates its layout. * * @param dimenResId the resource identifier of the dimension */ public void setShadowYOffset(int dimenResId) { int shadowYOffset = getResources().getDimensionPixelSize(dimenResId); if (mShadowYOffset != shadowYOffset) { mShadowYOffset = shadowYOffset; requestLayout(); updateBackground(); } } /** * Sets the shadow y offset of the <b>FloatingActionButton</b> and invalidates its layout. * <p> * Must be specified in density-independent (dp) pixels, which are then converted into actual * pixels (px). * * @param shadowYOffsetDp shadow radius specified in density-independent (dp) pixels */ public void setShadowYOffset(float shadowYOffsetDp) { mShadowYOffset = Util.dpToPx(getContext(), shadowYOffsetDp); requestLayout(); updateBackground(); } public int getShadowYOffset() { return mShadowYOffset; } public void setShadowColorResource(int colorResId) { int shadowColor = getResources().getColor(colorResId); if (mShadowColor != shadowColor) { mShadowColor = shadowColor; updateBackground(); } } public void setShadowColor(int color) { if (mShadowColor != color) { mShadowColor = color; updateBackground(); } } public int getShadowColor() { return mShadowColor; } /** * Checks whether <b>FloatingActionButton</b> is hidden * * @return true if <b>FloatingActionButton</b> is hidden, false otherwise */ public boolean isHidden() { return getVisibility() == INVISIBLE; } /** * Makes the <b>FloatingActionButton</b> to appear and sets its visibility to {@link #VISIBLE} * * @param animate if true - plays "show animation" */ public void show(boolean animate) { if (isHidden()) { if (animate) { playShowAnimation(); } super.setVisibility(VISIBLE); } } /** * Makes the <b>FloatingActionButton</b> to disappear and sets its visibility to {@link #INVISIBLE} * * @param animate if true - plays "hide animation" */ public void hide(boolean animate) { if (!isHidden()) { if (animate) { playHideAnimation(); } super.setVisibility(INVISIBLE); } } public void toggle(boolean animate) { if (isHidden()) { show(animate); } else { hide(animate); } } public void setLabelText(String text) { mLabelText = text; TextView labelView = getLabelView(); if (labelView != null) { labelView.setText(text); } } public String getLabelText() { return mLabelText; } public void setShowAnimation(Animation showAnimation) { mShowAnimation = showAnimation; } public void setHideAnimation(Animation hideAnimation) { mHideAnimation = hideAnimation; } public void setLabelVisibility(int visibility) { Label labelView = getLabelView(); if (labelView != null) { labelView.setVisibility(visibility); labelView.setHandleVisibilityChanges(visibility == VISIBLE); } } public int getLabelVisibility() { TextView labelView = getLabelView(); if (labelView != null) { return labelView.getVisibility(); } return -1; } @Override public void setElevation(float elevation) { if (Util.hasLollipop() && elevation > 0) { super.setElevation(elevation); if (!isInEditMode()) { mUsingElevation = true; mShowShadow = false; } updateBackground(); } } /** * Sets the shadow color and radius to mimic the native elevation. * * <p><b>API 21+</b>: Sets the native elevation of this view, in pixels. Updates margins to * make the view hold its position in layout across different platform versions.</p> */ @TargetApi(Build.VERSION_CODES.LOLLIPOP) public void setElevationCompat(float elevation) { mShadowColor = 0x26000000; mShadowRadius = Math.round(elevation / 2); mShadowXOffset = 0; mShadowYOffset = Math.round(mFabSize == SIZE_NORMAL ? elevation : elevation / 2); if (Util.hasLollipop()) { super.setElevation(elevation); mUsingElevationCompat = true; mShowShadow = false; updateBackground(); ViewGroup.LayoutParams layoutParams = getLayoutParams(); if (layoutParams != null) { setLayoutParams(layoutParams); } } else { mShowShadow = true; updateBackground(); } } /** * <p>Change the indeterminate mode for the progress bar. In indeterminate * mode, the progress is ignored and the progress bar shows an infinite * animation instead.</p> * * @param indeterminate true to enable the indeterminate mode */ public synchronized void setIndeterminate(boolean indeterminate) { if (!indeterminate) { mCurrentProgress = 0.0f; } mProgressBarEnabled = indeterminate; mShouldUpdateButtonPosition = true; mProgressIndeterminate = indeterminate; mLastTimeAnimated = SystemClock.uptimeMillis(); setupProgressBounds();// saveButtonOriginalPosition(); updateBackground(); } public synchronized void setMax(int max) { mProgressMax = max; } public synchronized int getMax() { return mProgressMax; } public synchronized void setProgress(int progress, boolean animate) { if (mProgressIndeterminate) return; mProgress = progress; mAnimateProgress = animate; if (!mButtonPositionSaved) { mShouldSetProgress = true; return; } mProgressBarEnabled = true; mShouldUpdateButtonPosition = true; setupProgressBounds(); saveButtonOriginalPosition(); updateBackground(); if (progress < 0) { progress = 0; } else if (progress > mProgressMax) { progress = mProgressMax; } if (progress == mTargetProgress) { return; } mTargetProgress = mProgressMax > 0 ? (progress / (float) mProgressMax) * 360 : 0; mLastTimeAnimated = SystemClock.uptimeMillis(); if (!animate) { mCurrentProgress = mTargetProgress; } invalidate(); } public synchronized int getProgress() { return mProgressIndeterminate ? 0 : mProgress; } public synchronized void hideProgress() { mProgressBarEnabled = false; mShouldUpdateButtonPosition = true; updateBackground(); } public synchronized void setShowProgressBackground(boolean show) { mShowProgressBackground = show; } public synchronized boolean isProgressBackgroundShown() { return mShowProgressBackground; } @Override public void setEnabled(boolean enabled) { super.setEnabled(enabled); Label label = (Label) getTag(R.id.fab_label); if (label != null) { label.setEnabled(enabled); } } @Override public void setVisibility(int visibility) { super.setVisibility(visibility); Label label = (Label) getTag(R.id.fab_label); if (label != null) { label.setVisibility(visibility); } } /** * <b>This will clear all AnimationListeners.</b> */ public void hideButtonInMenu(boolean animate) { if (!isHidden() && getVisibility() != GONE) { hide(animate); Label label = getLabelView(); if (label != null) { label.hide(animate); } getHideAnimation().setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { setVisibility(GONE); getHideAnimation().setAnimationListener(null); } @Override public void onAnimationRepeat(Animation animation) { } }); } } public void showButtonInMenu(boolean animate) { if (getVisibility() == VISIBLE) return; setVisibility(INVISIBLE); show(animate); Label label = getLabelView(); if (label != null) { label.show(animate); } } /** * Set the label's background colors */ public void setLabelColors(int colorNormal, int colorPressed, int colorRipple) { Label label = getLabelView(); int left = label.getPaddingLeft(); int top = label.getPaddingTop(); int right = label.getPaddingRight(); int bottom = label.getPaddingBottom(); label.setColors(colorNormal, colorPressed, colorRipple); label.updateBackground(); label.setPadding(left, top, right, bottom); } public void setLabelTextColor(int color) { getLabelView().setTextColor(color); } public void setLabelTextColor(ColorStateList colors) { getLabelView().setTextColor(colors); } }2)FloatingActionMenu.java=========================package com.eppico.fabmenu; import android.animation.AnimatorSet;import android.animation.ObjectAnimator;import android.animation.ValueAnimator;import android.content.Context;import android.content.res.ColorStateList;import android.content.res.TypedArray;import android.graphics.Color;import android.graphics.Typeface;import android.graphics.drawable.Drawable;import android.os.Handler;import android.text.TextUtils;import android.util.AttributeSet;import android.util.TypedValue;import android.view.ContextThemeWrapper;import android.view.MotionEvent;import android.view.View;import android.view.ViewGroup;import android.view.animation.Animation;import android.view.animation.AnimationUtils;import android.view.animation.AnticipateInterpolator;import android.view.animation.Interpolator;import android.view.animation.OvershootInterpolator;import android.widget.ImageView; import com.eppico.R; import java.util.ArrayList;import java.util.List; public class FloatingActionMenu extends ViewGroup { private static final int ANIMATION_DURATION = 300; private static final float CLOSED_PLUS_ROTATION = 0f; private static final float OPENED_PLUS_ROTATION_LEFT = -90f - 45f; private static final float OPENED_PLUS_ROTATION_RIGHT = 90f + 45f; private static final int OPEN_UP = 0; private static final int OPEN_DOWN = 1; private static final int LABELS_POSITION_LEFT = 0; private static final int LABELS_POSITION_RIGHT = 1; private AnimatorSet mOpenAnimatorSet = new AnimatorSet(); private AnimatorSet mCloseAnimatorSet = new AnimatorSet(); private AnimatorSet mIconToggleSet; private int mButtonSpacing = Util.dpToPx(getContext(), 0f); private FloatingActionButton mMenuButton; private int mMaxButtonWidth; private int mLabelsMargin = Util.dpToPx(getContext(), 0f); private int mLabelsVerticalOffset = Util.dpToPx(getContext(), 0f); private int mButtonsCount; private boolean mMenuOpened; private boolean mIsMenuOpening; private Handler mUiHandler = new Handler(); private int mLabelsShowAnimation; private int mLabelsHideAnimation; private int mLabelsPaddingTop = Util.dpToPx(getContext(), 4f); private int mLabelsPaddingRight = Util.dpToPx(getContext(), 8f); private int mLabelsPaddingBottom = Util.dpToPx(getContext(), 4f); private int mLabelsPaddingLeft = Util.dpToPx(getContext(), 8f); private ColorStateList mLabelsTextColor; private float mLabelsTextSize; private int mLabelsCornerRadius = Util.dpToPx(getContext(), 3f); private boolean mLabelsShowShadow; private int mLabelsColorNormal; private int mLabelsColorPressed; private int mLabelsColorRipple; private boolean mMenuShowShadow; private int mMenuShadowColor; private float mMenuShadowRadius = 4f; private float mMenuShadowXOffset = 1f; private float mMenuShadowYOffset = 3f; private int mMenuColorNormal; private int mMenuColorPressed; private int mMenuColorRipple; private Drawable mIcon; private int mAnimationDelayPerItem; private Interpolator mOpenInterpolator; private Interpolator mCloseInterpolator; private boolean mIsAnimated = true; private boolean mLabelsSingleLine; private int mLabelsEllipsize; private int mLabelsMaxLines; private int mMenuFabSize; private int mLabelsStyle; private Typeface mCustomTypefaceFromFont; private boolean mIconAnimated = true; private ImageView mImageToggle; private Animation mMenuButtonShowAnimation; private Animation mMenuButtonHideAnimation; private Animation mImageToggleShowAnimation; private Animation mImageToggleHideAnimation; private boolean mIsMenuButtonAnimationRunning; private boolean mIsSetClosedOnTouchOutside; private int mOpenDirection; private OnMenuToggleListener mToggleListener; private ValueAnimator mShowBackgroundAnimator; private ValueAnimator mHideBackgroundAnimator; private int mBackgroundColor; private int mLabelsPosition; private Context mLabelsContext; private String mMenuLabelText; private boolean mUsingMenuLabel; public interface OnMenuToggleListener { void onMenuToggle(boolean opened); } public FloatingActionMenu(Context context) { this(context, null); } public FloatingActionMenu(Context context, AttributeSet attrs) { this(context, attrs, 0); } public FloatingActionMenu(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context, attrs); } private void init(Context context, AttributeSet attrs) { TypedArray attr = context.obtainStyledAttributes(attrs, R.styleable.FloatingActionMenu, 0, 0); mButtonSpacing = attr.getDimensionPixelSize(R.styleable.FloatingActionMenu_menu_buttonSpacing, mButtonSpacing); mLabelsMargin = attr.getDimensionPixelSize(R.styleable.FloatingActionMenu_menu_labels_margin, mLabelsMargin); mLabelsPosition = attr.getInt(R.styleable.FloatingActionMenu_menu_labels_position, LABELS_POSITION_LEFT); mLabelsShowAnimation = attr.getResourceId(R.styleable.FloatingActionMenu_menu_labels_showAnimation, mLabelsPosition == LABELS_POSITION_LEFT ? R.anim.fab_slide_in_from_right : R.anim.fab_slide_in_from_left); mLabelsHideAnimation = attr.getResourceId(R.styleable.FloatingActionMenu_menu_labels_hideAnimation, mLabelsPosition == LABELS_POSITION_LEFT ? R.anim.fab_slide_out_to_right : R.anim.fab_slide_out_to_left); mLabelsPaddingTop = attr.getDimensionPixelSize(R.styleable.FloatingActionMenu_menu_labels_paddingTop, mLabelsPaddingTop); mLabelsPaddingRight = attr.getDimensionPixelSize(R.styleable.FloatingActionMenu_menu_labels_paddingRight, mLabelsPaddingRight); mLabelsPaddingBottom = attr.getDimensionPixelSize(R.styleable.FloatingActionMenu_menu_labels_paddingBottom, mLabelsPaddingBottom); mLabelsPaddingLeft = attr.getDimensionPixelSize(R.styleable.FloatingActionMenu_menu_labels_paddingLeft, mLabelsPaddingLeft); mLabelsTextColor = attr.getColorStateList(R.styleable.FloatingActionMenu_menu_labels_textColor); // set default value if null same as for textview if (mLabelsTextColor == null) { mLabelsTextColor = ColorStateList.valueOf(Color.WHITE); } mLabelsTextSize = attr.getDimension(R.styleable.FloatingActionMenu_menu_labels_textSize, getResources().getDimension(R.dimen.labels_text_size)); mLabelsCornerRadius = attr.getDimensionPixelSize(R.styleable.FloatingActionMenu_menu_labels_cornerRadius, mLabelsCornerRadius); mLabelsShowShadow = attr.getBoolean(R.styleable.FloatingActionMenu_menu_labels_showShadow, true); mLabelsColorNormal = attr.getColor(R.styleable.FloatingActionMenu_menu_labels_colorNormal, 0xFF333333); mLabelsColorPressed = attr.getColor(R.styleable.FloatingActionMenu_menu_labels_colorPressed, 0xFF444444); mLabelsColorRipple = attr.getColor(R.styleable.FloatingActionMenu_menu_labels_colorRipple, 0x66FFFFFF); mMenuShowShadow = attr.getBoolean(R.styleable.FloatingActionMenu_menu_showShadow, true); mMenuShadowColor = attr.getColor(R.styleable.FloatingActionMenu_menu_shadowColor, 0x66000000); mMenuShadowRadius = attr.getDimension(R.styleable.FloatingActionMenu_menu_shadowRadius, mMenuShadowRadius); mMenuShadowXOffset = attr.getDimension(R.styleable.FloatingActionMenu_menu_shadowXOffset, mMenuShadowXOffset); mMenuShadowYOffset = attr.getDimension(R.styleable.FloatingActionMenu_menu_shadowYOffset, mMenuShadowYOffset); mMenuColorNormal = attr.getColor(R.styleable.FloatingActionMenu_menu_colorNormal, 0xFFDA4336); mMenuColorPressed = attr.getColor(R.styleable.FloatingActionMenu_menu_colorPressed, 0xFFE75043); mMenuColorRipple = attr.getColor(R.styleable.FloatingActionMenu_menu_colorRipple, 0x99FFFFFF); mAnimationDelayPerItem = attr.getInt(R.styleable.FloatingActionMenu_menu_animationDelayPerItem, 50); mIcon = attr.getDrawable(R.styleable.FloatingActionMenu_menu_icon); if (mIcon == null) { mIcon = getResources().getDrawable(R.mipmap.ic_add); } mLabelsSingleLine = attr.getBoolean(R.styleable.FloatingActionMenu_menu_labels_singleLine, false); mLabelsEllipsize = attr.getInt(R.styleable.FloatingActionMenu_menu_labels_ellipsize, 0); mLabelsMaxLines = attr.getInt(R.styleable.FloatingActionMenu_menu_labels_maxLines, -1); mMenuFabSize = attr.getInt(R.styleable.FloatingActionMenu_menu_fab_size, FloatingActionButton.SIZE_NORMAL); mLabelsStyle = attr.getResourceId(R.styleable.FloatingActionMenu_menu_labels_style, 0); String customFont = attr.getString(R.styleable.FloatingActionMenu_menu_labels_customFont); try { if (!TextUtils.isEmpty(customFont)) { mCustomTypefaceFromFont = Typeface.createFromAsset(getContext().getAssets(), customFont); } } catch (RuntimeException ex) { throw new IllegalArgumentException("Unable to load specified custom font: " + customFont, ex); } mOpenDirection = attr.getInt(R.styleable.FloatingActionMenu_menu_openDirection, OPEN_UP); mBackgroundColor = attr.getColor(R.styleable.FloatingActionMenu_menu_backgroundColor, Color.TRANSPARENT); if (attr.hasValue(R.styleable.FloatingActionMenu_menu_fab_label)) { mUsingMenuLabel = true; mMenuLabelText = attr.getString(R.styleable.FloatingActionMenu_menu_fab_label); } if (attr.hasValue(R.styleable.FloatingActionMenu_menu_labels_padding)) { int padding = attr.getDimensionPixelSize(R.styleable.FloatingActionMenu_menu_labels_padding, 0); initPadding(padding); } mOpenInterpolator = new OvershootInterpolator(); mCloseInterpolator = new AnticipateInterpolator(); mLabelsContext = new ContextThemeWrapper(getContext(), mLabelsStyle); initBackgroundDimAnimation(); createMenuButton(); initMenuButtonAnimations(attr); attr.recycle(); } private void initMenuButtonAnimations(TypedArray attr) { int showResId = attr.getResourceId(R.styleable.FloatingActionMenu_menu_fab_show_animation, R.anim.fab_scale_up); setMenuButtonShowAnimation(AnimationUtils.loadAnimation(getContext(), showResId)); mImageToggleShowAnimation = AnimationUtils.loadAnimation(getContext(), showResId); int hideResId = attr.getResourceId(R.styleable.FloatingActionMenu_menu_fab_hide_animation, R.anim.fab_scale_down); setMenuButtonHideAnimation(AnimationUtils.loadAnimation(getContext(), hideResId)); mImageToggleHideAnimation = AnimationUtils.loadAnimation(getContext(), hideResId); } private void initBackgroundDimAnimation() { final int maxAlpha = Color.alpha(mBackgroundColor); final int red = Color.red(mBackgroundColor); final int green = Color.green(mBackgroundColor); final int blue = Color.blue(mBackgroundColor); mShowBackgroundAnimator = ValueAnimator.ofInt(0, maxAlpha); mShowBackgroundAnimator.setDuration(ANIMATION_DURATION); mShowBackgroundAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { Integer alpha = (Integer) animation.getAnimatedValue(); setBackgroundColor(Color.argb(alpha, red, green, blue)); } }); mHideBackgroundAnimator = ValueAnimator.ofInt(maxAlpha, 0); mHideBackgroundAnimator.setDuration(ANIMATION_DURATION); mHideBackgroundAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { Integer alpha = (Integer) animation.getAnimatedValue(); setBackgroundColor(Color.argb(alpha, red, green, blue)); } }); } private boolean isBackgroundEnabled() { return mBackgroundColor != Color.TRANSPARENT; } private void initPadding(int padding) { mLabelsPaddingTop = padding; mLabelsPaddingRight = padding; mLabelsPaddingBottom = padding; mLabelsPaddingLeft = padding; } private void createMenuButton() { mMenuButton = new FloatingActionButton(getContext()); mMenuButton.mShowShadow = mMenuShowShadow; if (mMenuShowShadow) { mMenuButton.mShadowRadius = Util.dpToPx(getContext(), mMenuShadowRadius); mMenuButton.mShadowXOffset = Util.dpToPx(getContext(), mMenuShadowXOffset); mMenuButton.mShadowYOffset = Util.dpToPx(getContext(), mMenuShadowYOffset); } mMenuButton.setColors(mMenuColorNormal, mMenuColorPressed, mMenuColorRipple); mMenuButton.mShadowColor = mMenuShadowColor; mMenuButton.mFabSize = mMenuFabSize; mMenuButton.updateBackground(); mMenuButton.setLabelText(mMenuLabelText); mImageToggle = new ImageView(getContext()); mImageToggle.setImageDrawable(mIcon); addView(mMenuButton, super.generateDefaultLayoutParams()); addView(mImageToggle); createDefaultIconAnimation(); } private void createDefaultIconAnimation() { float collapseAngle; float expandAngle; if (mOpenDirection == OPEN_UP) { collapseAngle = mLabelsPosition == LABELS_POSITION_LEFT ? OPENED_PLUS_ROTATION_LEFT : OPENED_PLUS_ROTATION_RIGHT; expandAngle = mLabelsPosition == LABELS_POSITION_LEFT ? OPENED_PLUS_ROTATION_LEFT : OPENED_PLUS_ROTATION_RIGHT; } else { collapseAngle = mLabelsPosition == LABELS_POSITION_LEFT ? OPENED_PLUS_ROTATION_RIGHT : OPENED_PLUS_ROTATION_LEFT; expandAngle = mLabelsPosition == LABELS_POSITION_LEFT ? OPENED_PLUS_ROTATION_RIGHT : OPENED_PLUS_ROTATION_LEFT; } ObjectAnimator collapseAnimator = ObjectAnimator.ofFloat( mImageToggle, "rotation", collapseAngle, CLOSED_PLUS_ROTATION ); ObjectAnimator expandAnimator = ObjectAnimator.ofFloat( mImageToggle, "rotation", CLOSED_PLUS_ROTATION, expandAngle ); mOpenAnimatorSet.play(expandAnimator); mCloseAnimatorSet.play(collapseAnimator); mOpenAnimatorSet.setInterpolator(mOpenInterpolator); mCloseAnimatorSet.setInterpolator(mCloseInterpolator); mOpenAnimatorSet.setDuration(ANIMATION_DURATION); mCloseAnimatorSet.setDuration(ANIMATION_DURATION); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = 0; int height = 0; mMaxButtonWidth = 0; int maxLabelWidth = 0; measureChildWithMargins(mImageToggle, widthMeasureSpec, 0, heightMeasureSpec, 0); for (int i = 0; i < mButtonsCount; i++) { View child = getChildAt(i); if (child.getVisibility() == GONE || child == mImageToggle) continue; measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0); mMaxButtonWidth = Math.max(mMaxButtonWidth, child.getMeasuredWidth()); } for (int i = 0; i < mButtonsCount; i++) { int usedWidth = 0; View child = getChildAt(i); if (child.getVisibility() == GONE || child == mImageToggle) continue; usedWidth += child.getMeasuredWidth(); height += child.getMeasuredHeight(); Label label = (Label) child.getTag(R.id.fab_label); if (label != null) { int labelOffset = (mMaxButtonWidth - child.getMeasuredWidth()) / (mUsingMenuLabel ? 1 : 2); int labelUsedWidth = child.getMeasuredWidth() + label.calculateShadowWidth() + mLabelsMargin + labelOffset; measureChildWithMargins(label, widthMeasureSpec, labelUsedWidth, heightMeasureSpec, 0); usedWidth += label.getMeasuredWidth(); maxLabelWidth = Math.max(maxLabelWidth, usedWidth + labelOffset); } } width = Math.max(mMaxButtonWidth, maxLabelWidth + mLabelsMargin) + getPaddingLeft() + getPaddingRight(); height += mButtonSpacing * (mButtonsCount - 1) + getPaddingTop() + getPaddingBottom(); height = adjustForOvershoot(height); if (getLayoutParams().width == LayoutParams.MATCH_PARENT) { width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec); } if (getLayoutParams().height == LayoutParams.MATCH_PARENT) { height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec); } setMeasuredDimension(width, height); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int buttonsHorizontalCenter = mLabelsPosition == LABELS_POSITION_LEFT ? r - l - mMaxButtonWidth / 2 - getPaddingRight() : mMaxButtonWidth / 2 + getPaddingLeft(); boolean openUp = mOpenDirection == OPEN_UP; int menuButtonTop = openUp ? b - t - mMenuButton.getMeasuredHeight() - getPaddingBottom() : getPaddingTop(); int menuButtonLeft = buttonsHorizontalCenter - mMenuButton.getMeasuredWidth() / 2; mMenuButton.layout(menuButtonLeft, menuButtonTop, menuButtonLeft + mMenuButton.getMeasuredWidth(), menuButtonTop + mMenuButton.getMeasuredHeight()); int imageLeft = buttonsHorizontalCenter - mImageToggle.getMeasuredWidth() / 2; int imageTop = menuButtonTop + mMenuButton.getMeasuredHeight() / 2 - mImageToggle.getMeasuredHeight() / 2; mImageToggle.layout(imageLeft, imageTop, imageLeft + mImageToggle.getMeasuredWidth(), imageTop + mImageToggle.getMeasuredHeight()); int nextY = openUp ? menuButtonTop + mMenuButton.getMeasuredHeight() + mButtonSpacing : menuButtonTop; for (int i = mButtonsCount - 1; i >= 0; i--) { View child = getChildAt(i); if (child == mImageToggle) continue; FloatingActionButton fab = (FloatingActionButton) child; if (fab.getVisibility() == GONE) continue; int childX = buttonsHorizontalCenter - fab.getMeasuredWidth() / 2; int childY = openUp ? nextY - fab.getMeasuredHeight() - mButtonSpacing : nextY; if (fab != mMenuButton) { fab.layout(childX, childY, childX + fab.getMeasuredWidth(), childY + fab.getMeasuredHeight()); if (!mIsMenuOpening) { fab.hide(false); } } View label = (View) fab.getTag(R.id.fab_label); if (label != null) { int labelsOffset = (mUsingMenuLabel ? mMaxButtonWidth / 2 : fab.getMeasuredWidth() / 2) + mLabelsMargin; int labelXNearButton = mLabelsPosition == LABELS_POSITION_LEFT ? buttonsHorizontalCenter - labelsOffset : buttonsHorizontalCenter + labelsOffset; int labelXAwayFromButton = mLabelsPosition == LABELS_POSITION_LEFT ? labelXNearButton - label.getMeasuredWidth() : labelXNearButton + label.getMeasuredWidth(); int labelLeft = mLabelsPosition == LABELS_POSITION_LEFT ? labelXAwayFromButton : labelXNearButton; int labelRight = mLabelsPosition == LABELS_POSITION_LEFT ? labelXNearButton : labelXAwayFromButton; int labelTop = childY - mLabelsVerticalOffset + (fab.getMeasuredHeight() - label.getMeasuredHeight()) / 2; label.layout(labelLeft, labelTop, labelRight, labelTop + label.getMeasuredHeight()); if (!mIsMenuOpening) { label.setVisibility(INVISIBLE); } } nextY = openUp ? childY - mButtonSpacing : childY + child.getMeasuredHeight() + mButtonSpacing; } } private int adjustForOvershoot(int dimension) { return (int) (dimension * 0.03 + dimension); } @Override protected void onFinishInflate() { super.onFinishInflate(); bringChildToFront(mMenuButton); bringChildToFront(mImageToggle); mButtonsCount = getChildCount(); createLabels(); } private void createLabels() { for (int i = 0; i < mButtonsCount; i++) { if (getChildAt(i) == mImageToggle) continue; final FloatingActionButton fab = (FloatingActionButton) getChildAt(i); if (fab.getTag(R.id.fab_label) != null) continue; addLabel(fab); if (fab == mMenuButton) { mMenuButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { toggle(mIsAnimated); } }); } } } private void addLabel(FloatingActionButton fab) { String text = fab.getLabelText(); if (TextUtils.isEmpty(text)) return; final Label label = new Label(mLabelsContext); label.setClickable(true); label.setFab(fab); label.setShowAnimation(AnimationUtils.loadAnimation(getContext(), mLabelsShowAnimation)); label.setHideAnimation(AnimationUtils.loadAnimation(getContext(), mLabelsHideAnimation)); if (mLabelsStyle > 0) { label.setTextAppearance(getContext(), mLabelsStyle); label.setShowShadow(false); label.setUsingStyle(true); } else { label.setColors(mLabelsColorNormal, mLabelsColorPressed, mLabelsColorRipple); label.setShowShadow(mLabelsShowShadow); label.setCornerRadius(mLabelsCornerRadius); if (mLabelsEllipsize > 0) { setLabelEllipsize(label); } label.setMaxLines(mLabelsMaxLines); label.updateBackground(); label.setTextSize(TypedValue.COMPLEX_UNIT_PX, mLabelsTextSize); label.setTextColor(mLabelsTextColor); int left = mLabelsPaddingLeft; int top = mLabelsPaddingTop; if (mLabelsShowShadow) { left += fab.getShadowRadius() + Math.abs(fab.getShadowXOffset()); top += fab.getShadowRadius() + Math.abs(fab.getShadowYOffset()); } label.setPadding( left, top, mLabelsPaddingLeft, mLabelsPaddingTop ); if (mLabelsMaxLines < 0 || mLabelsSingleLine) { label.setSingleLine(mLabelsSingleLine); } } if (mCustomTypefaceFromFont != null) { label.setTypeface(mCustomTypefaceFromFont); } label.setText(text); label.setOnClickListener(fab.getOnClickListener()); addView(label); fab.setTag(R.id.fab_label, label); } private void setLabelEllipsize(Label label) { switch (mLabelsEllipsize) { case 1: label.setEllipsize(TextUtils.TruncateAt.START); break; case 2: label.setEllipsize(TextUtils.TruncateAt.MIDDLE); break; case 3: label.setEllipsize(TextUtils.TruncateAt.END); break; case 4: label.setEllipsize(TextUtils.TruncateAt.MARQUEE); break; } } @Override public MarginLayoutParams generateLayoutParams(AttributeSet attrs) { return new MarginLayoutParams(getContext(), attrs); } @Override protected MarginLayoutParams generateLayoutParams(LayoutParams p) { return new MarginLayoutParams(p); } @Override protected MarginLayoutParams generateDefaultLayoutParams() { return new MarginLayoutParams(MarginLayoutParams.WRAP_CONTENT, MarginLayoutParams.WRAP_CONTENT); } @Override protected boolean checkLayoutParams(LayoutParams p) { return p instanceof MarginLayoutParams; } private void hideMenuButtonWithImage(boolean animate) { if (!isMenuButtonHidden()) { mMenuButton.hide(animate); if (animate) { mImageToggle.startAnimation(mImageToggleHideAnimation); } mImageToggle.setVisibility(INVISIBLE); mIsMenuButtonAnimationRunning = false; } } private void showMenuButtonWithImage(boolean animate) { if (isMenuButtonHidden()) { mMenuButton.show(animate); if (animate) { mImageToggle.startAnimation(mImageToggleShowAnimation); } mImageToggle.setVisibility(VISIBLE); } } @Override public boolean onTouchEvent(MotionEvent event) { if (mIsSetClosedOnTouchOutside) { boolean handled = false; switch (event.getAction()) { case MotionEvent.ACTION_DOWN: handled = isOpened(); break; case MotionEvent.ACTION_UP: close(mIsAnimated); handled = true; } return handled; } return super.onTouchEvent(event); } /* ===== API methods ===== */ public boolean isOpened() { return mMenuOpened; } public void toggle(boolean animate) { if (isOpened()) { close(animate); } else { open(animate); } } public void open(final boolean animate) { if (!isOpened()) { if (isBackgroundEnabled()) { mShowBackgroundAnimator.start(); } if (mIconAnimated) { if (mIconToggleSet != null) { mIconToggleSet.start(); } else { mCloseAnimatorSet.cancel(); mOpenAnimatorSet.start(); } } int delay = 0; int counter = 0; mIsMenuOpening = true; for (int i = getChildCount() - 1; i >= 0; i--) { View child = getChildAt(i); if (child instanceof FloatingActionButton && child.getVisibility() != GONE) { counter++; final FloatingActionButton fab = (FloatingActionButton) child; mUiHandler.postDelayed(new Runnable() { @Override public void run() { if (isOpened()) return; if (fab != mMenuButton) { fab.show(animate); } Label label = (Label) fab.getTag(R.id.fab_label); if (label != null && label.isHandleVisibilityChanges()) { label.show(animate); } } }, delay); delay += mAnimationDelayPerItem; } } mUiHandler.postDelayed(new Runnable() { @Override public void run() { mMenuOpened = true; if (mToggleListener != null) { mToggleListener.onMenuToggle(true); } } }, ++counter * mAnimationDelayPerItem); } } public void close(final boolean animate) { if (isOpened()) { if (isBackgroundEnabled()) { mHideBackgroundAnimator.start(); } if (mIconAnimated) { if (mIconToggleSet != null) { mIconToggleSet.start(); } else { mCloseAnimatorSet.start(); mOpenAnimatorSet.cancel(); } } int delay = 0; int counter = 0; mIsMenuOpening = false; for (int i = 0; i < getChildCount(); i++) { View child = getChildAt(i); if (child instanceof FloatingActionButton && child.getVisibility() != GONE) { counter++; final FloatingActionButton fab = (FloatingActionButton) child; mUiHandler.postDelayed(new Runnable() { @Override public void run() { if (!isOpened()) return; if (fab != mMenuButton) { fab.hide(animate); } Label label = (Label) fab.getTag(R.id.fab_label); if (label != null && label.isHandleVisibilityChanges()) { label.hide(animate); } } }, delay); delay += mAnimationDelayPerItem; } } mUiHandler.postDelayed(new Runnable() { @Override public void run() { mMenuOpened = false; if (mToggleListener != null) { mToggleListener.onMenuToggle(false); } } }, ++counter * mAnimationDelayPerItem); } } /** * Sets the {@link android.view.animation.Interpolator} for <b>FloatingActionButton's</b> icon animation. * * @param interpolator the Interpolator to be used in animation */ public void setIconAnimationInterpolator(Interpolator interpolator) { mOpenAnimatorSet.setInterpolator(interpolator); mCloseAnimatorSet.setInterpolator(interpolator); } public void setIconAnimationOpenInterpolator(Interpolator openInterpolator) { mOpenAnimatorSet.setInterpolator(openInterpolator); } public void setIconAnimationCloseInterpolator(Interpolator closeInterpolator) { mCloseAnimatorSet.setInterpolator(closeInterpolator); } /** * Sets whether open and close actions should be animated * * @param animated if <b>false</b> - menu items will appear/disappear instantly without any animation */ public void setAnimated(boolean animated) { mIsAnimated = animated; mOpenAnimatorSet.setDuration(animated ? ANIMATION_DURATION : 0); mCloseAnimatorSet.setDuration(animated ? ANIMATION_DURATION : 0); } public boolean isAnimated() { return mIsAnimated; } public void setAnimationDelayPerItem(int animationDelayPerItem) { mAnimationDelayPerItem = animationDelayPerItem; } public int getAnimationDelayPerItem() { return mAnimationDelayPerItem; } public void setOnMenuToggleListener(OnMenuToggleListener listener) { mToggleListener = listener; } public void setIconAnimated(boolean animated) { mIconAnimated = animated; } public boolean isIconAnimated() { return mIconAnimated; } public ImageView getMenuIconView() { return mImageToggle; } public void setIconToggleAnimatorSet(AnimatorSet toggleAnimatorSet) { mIconToggleSet = toggleAnimatorSet; } public AnimatorSet getIconToggleAnimatorSet() { return mIconToggleSet; } public void setMenuButtonShowAnimation(Animation showAnimation) { mMenuButtonShowAnimation = showAnimation; mMenuButton.setShowAnimation(showAnimation); } public void setMenuButtonHideAnimation(Animation hideAnimation) { mMenuButtonHideAnimation = hideAnimation; mMenuButton.setHideAnimation(hideAnimation); } public boolean isMenuHidden() { return getVisibility() == INVISIBLE; } public boolean isMenuButtonHidden() { return mMenuButton.isHidden(); } /** * Makes the whole {@link #FloatingActionMenu} to appear and sets its visibility to {@link #VISIBLE} * * @param animate if true - plays "show animation" */ public void showMenu(boolean animate) { if (isMenuHidden()) { if (animate) { startAnimation(mMenuButtonShowAnimation); } setVisibility(VISIBLE); } } /** * Makes the {@link #FloatingActionMenu} to disappear and sets its visibility to {@link #INVISIBLE} * * @param animate if true - plays "hide animation" */ public void hideMenu(final boolean animate) { if (!isMenuHidden() && !mIsMenuButtonAnimationRunning) { mIsMenuButtonAnimationRunning = true; if (isOpened()) { close(animate); mUiHandler.postDelayed(new Runnable() { @Override public void run() { if (animate) { startAnimation(mMenuButtonHideAnimation); } setVisibility(INVISIBLE); mIsMenuButtonAnimationRunning = false; } }, mAnimationDelayPerItem * mButtonsCount); } else { if (animate) { startAnimation(mMenuButtonHideAnimation); } setVisibility(INVISIBLE); mIsMenuButtonAnimationRunning = false; } } } public void toggleMenu(boolean animate) { if (isMenuHidden()) { showMenu(animate); } else { hideMenu(animate); } } /** * Makes the {@link FloatingActionButton} to appear inside the {@link #FloatingActionMenu} and * sets its visibility to {@link #VISIBLE} * * @param animate if true - plays "show animation" */ public void showMenuButton(boolean animate) { if (isMenuButtonHidden()) { showMenuButtonWithImage(animate); } } /** * Makes the {@link FloatingActionButton} to disappear inside the {@link #FloatingActionMenu} and * sets its visibility to {@link #INVISIBLE} * * @param animate if true - plays "hide animation" */ public void hideMenuButton(final boolean animate) { if (!isMenuButtonHidden() && !mIsMenuButtonAnimationRunning) { mIsMenuButtonAnimationRunning = true; if (isOpened()) { close(animate); mUiHandler.postDelayed(new Runnable() { @Override public void run() { hideMenuButtonWithImage(animate); } }, mAnimationDelayPerItem * mButtonsCount); } else { hideMenuButtonWithImage(animate); } } } public void toggleMenuButton(boolean animate) { if (isMenuButtonHidden()) { showMenuButton(animate); } else { hideMenuButton(animate); } } public void setClosedOnTouchOutside(boolean close) { mIsSetClosedOnTouchOutside = close; } public void setMenuButtonColorNormal(int color) { mMenuColorNormal = color; mMenuButton.setColorNormal(color); } public void setMenuButtonColorNormalResId(int colorResId) { mMenuColorNormal = getResources().getColor(colorResId); mMenuButton.setColorNormalResId(colorResId); } public int getMenuButtonColorNormal() { return mMenuColorNormal; } public void setMenuButtonColorPressed(int color) { mMenuColorPressed = color; mMenuButton.setColorPressed(color); } public void setMenuButtonColorPressedResId(int colorResId) { mMenuColorPressed = getResources().getColor(colorResId); mMenuButton.setColorPressedResId(colorResId); } public int getMenuButtonColorPressed() { return mMenuColorPressed; } public void setMenuButtonColorRipple(int color) { mMenuColorRipple = color; mMenuButton.setColorRipple(color); } public void setMenuButtonColorRippleResId(int colorResId) { mMenuColorRipple = getResources().getColor(colorResId); mMenuButton.setColorRippleResId(colorResId); } public int getMenuButtonColorRipple() { return mMenuColorRipple; } public void addMenuButton(FloatingActionButton fab) { addView(fab, mButtonsCount - 2); mButtonsCount++; addLabel(fab); } public void removeMenuButton(FloatingActionButton fab) { removeView(fab.getLabelView()); removeView(fab); mButtonsCount--; } public void addMenuButton(FloatingActionButton fab, int index) { int size = mButtonsCount - 2; if (index < 0) { index = 0; } else if (index > size) { index = size; } addView(fab, index); mButtonsCount++; addLabel(fab); } public void removeAllMenuButtons() { close(true); List<FloatingActionButton> viewsToRemove = new ArrayList<>(); for (int i = 0; i < getChildCount(); i++) { View v = getChildAt(i); if (v != mMenuButton && v != mImageToggle && v instanceof FloatingActionButton) { viewsToRemove.add((FloatingActionButton) v); } } for (FloatingActionButton v : viewsToRemove) { removeMenuButton(v); } } public void setMenuButtonLabelText(String text) { mMenuButton.setLabelText(text); } public String getMenuButtonLabelText() { return mMenuLabelText; } public void setOnMenuButtonClickListener(OnClickListener clickListener) { mMenuButton.setOnClickListener(clickListener); } public void setOnMenuButtonLongClickListener(OnLongClickListener longClickListener) { mMenuButton.setOnLongClickListener(longClickListener); } }3)Label.java=======================
package com.eppico.fabmenu; import android.annotation.TargetApi;import android.content.Context;import android.content.res.ColorStateList;import android.graphics.Canvas;import android.graphics.ColorFilter;import android.graphics.Outline;import android.graphics.Paint;import android.graphics.PorterDuff;import android.graphics.PorterDuffXfermode;import android.graphics.RectF;import android.graphics.Xfermode;import android.graphics.drawable.Drawable;import android.graphics.drawable.LayerDrawable;import android.graphics.drawable.RippleDrawable;import android.graphics.drawable.ShapeDrawable;import android.graphics.drawable.StateListDrawable;import android.graphics.drawable.shapes.RoundRectShape;import android.os.Build;import android.util.AttributeSet;import android.view.GestureDetector;import android.view.MotionEvent;import android.view.View;import android.view.ViewOutlineProvider;import android.view.animation.Animation;import android.widget.TextView; public class Label extends TextView { private static final Xfermode PORTER_DUFF_CLEAR = new PorterDuffXfermode(PorterDuff.Mode.CLEAR); private int mShadowRadius; private int mShadowXOffset; private int mShadowYOffset; private int mShadowColor; private Drawable mBackgroundDrawable; private boolean mShowShadow = true; private int mRawWidth; private int mRawHeight; private int mColorNormal; private int mColorPressed; private int mColorRipple; private int mCornerRadius; private FloatingActionButton mFab; private Animation mShowAnimation; private Animation mHideAnimation; private boolean mUsingStyle; private boolean mHandleVisibilityChanges = true; public Label(Context context) { super(context); } public Label(Context context, AttributeSet attrs) { super(context, attrs); } public Label(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); setMeasuredDimension(calculateMeasuredWidth(), calculateMeasuredHeight()); } private int calculateMeasuredWidth() { if (mRawWidth == 0) { mRawWidth = getMeasuredWidth(); } return getMeasuredWidth() + calculateShadowWidth(); } private int calculateMeasuredHeight() { if (mRawHeight == 0) { mRawHeight = getMeasuredHeight(); } return getMeasuredHeight() + calculateShadowHeight(); } int calculateShadowWidth() { return mShowShadow ? (mShadowRadius + Math.abs(mShadowXOffset)) : 0; } int calculateShadowHeight() { return mShowShadow ? (mShadowRadius + Math.abs(mShadowYOffset)) : 0; } void updateBackground() { LayerDrawable layerDrawable; if (mShowShadow) { layerDrawable = new LayerDrawable(new Drawable[]{ new Shadow(), createFillDrawable() }); int leftInset = mShadowRadius + Math.abs(mShadowXOffset); int topInset = mShadowRadius + Math.abs(mShadowYOffset); int rightInset = (mShadowRadius + Math.abs(mShadowXOffset)); int bottomInset = (mShadowRadius + Math.abs(mShadowYOffset)); layerDrawable.setLayerInset( 1, leftInset, topInset, rightInset, bottomInset ); } else { layerDrawable = new LayerDrawable(new Drawable[]{ createFillDrawable() }); } setBackgroundCompat(layerDrawable); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) private Drawable createFillDrawable() { StateListDrawable drawable = new StateListDrawable(); drawable.addState(new int[]{android.R.attr.state_pressed}, createRectDrawable(mColorPressed)); drawable.addState(new int[]{}, createRectDrawable(mColorNormal)); if (Util.hasLollipop()) { RippleDrawable ripple = new RippleDrawable(new ColorStateList(new int[][]{{}}, new int[]{mColorRipple}), drawable, null); setOutlineProvider(new ViewOutlineProvider() { @Override public void getOutline(View view, Outline outline) { outline.setOval(0, 0, view.getWidth(), view.getHeight()); } }); setClipToOutline(true); mBackgroundDrawable = ripple; return ripple; } mBackgroundDrawable = drawable; return drawable; } private Drawable createRectDrawable(int color) { RoundRectShape shape = new RoundRectShape( new float[]{ mCornerRadius, mCornerRadius, mCornerRadius, mCornerRadius, mCornerRadius, mCornerRadius, mCornerRadius, mCornerRadius }, null, null); ShapeDrawable shapeDrawable = new ShapeDrawable(shape); shapeDrawable.getPaint().setColor(color); return shapeDrawable; } private void setShadow(FloatingActionButton fab) { mShadowColor = fab.getShadowColor(); mShadowRadius = fab.getShadowRadius(); mShadowXOffset = fab.getShadowXOffset(); mShadowYOffset = fab.getShadowYOffset(); mShowShadow = fab.hasShadow(); } @SuppressWarnings("deprecation") @TargetApi(Build.VERSION_CODES.LOLLIPOP) private void setBackgroundCompat(Drawable drawable) { if (Util.hasJellyBean()) { setBackground(drawable); } else { setBackgroundDrawable(drawable); } } private void playShowAnimation() { if (mShowAnimation != null) { mHideAnimation.cancel(); startAnimation(mShowAnimation); } } private void playHideAnimation() { if (mHideAnimation != null) { mShowAnimation.cancel(); startAnimation(mHideAnimation); } } @TargetApi(Build.VERSION_CODES.LOLLIPOP) void onActionDown() { if (mUsingStyle) { mBackgroundDrawable = getBackground(); } if (mBackgroundDrawable instanceof StateListDrawable) { StateListDrawable drawable = (StateListDrawable) mBackgroundDrawable; drawable.setState(new int[]{android.R.attr.state_pressed}); } else if (Util.hasLollipop() && mBackgroundDrawable instanceof RippleDrawable) { RippleDrawable ripple = (RippleDrawable) mBackgroundDrawable; ripple.setState(new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed}); ripple.setHotspot(getMeasuredWidth() / 2, getMeasuredHeight() / 2); ripple.setVisible(true, true); } // setPressed(true); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) void onActionUp() { if (mUsingStyle) { mBackgroundDrawable = getBackground(); } if (mBackgroundDrawable instanceof StateListDrawable) { StateListDrawable drawable = (StateListDrawable) mBackgroundDrawable; drawable.setState(new int[]{}); } else if (Util.hasLollipop() && mBackgroundDrawable instanceof RippleDrawable) { RippleDrawable ripple = (RippleDrawable) mBackgroundDrawable; ripple.setState(new int[]{}); ripple.setHotspot(getMeasuredWidth() / 2, getMeasuredHeight() / 2); ripple.setVisible(true, true); } // setPressed(false); } void setFab(FloatingActionButton fab) { mFab = fab; setShadow(fab); } void setShowShadow(boolean show) { mShowShadow = show; } void setCornerRadius(int cornerRadius) { mCornerRadius = cornerRadius; } void setColors(int colorNormal, int colorPressed, int colorRipple) { mColorNormal = colorNormal; mColorPressed = colorPressed; mColorRipple = colorRipple; } void show(boolean animate) { if (animate) { playShowAnimation(); } setVisibility(VISIBLE); } void hide(boolean animate) { if (animate) { playHideAnimation(); } setVisibility(INVISIBLE); } void setShowAnimation(Animation showAnimation) { mShowAnimation = showAnimation; } void setHideAnimation(Animation hideAnimation) { mHideAnimation = hideAnimation; } void setUsingStyle(boolean usingStyle) { mUsingStyle = usingStyle; } void setHandleVisibilityChanges(boolean handle) { mHandleVisibilityChanges = handle; } boolean isHandleVisibilityChanges() { return mHandleVisibilityChanges; } @Override public boolean onTouchEvent(MotionEvent event) { if (mFab == null || mFab.getOnClickListener() == null || !mFab.isEnabled()) { return super.onTouchEvent(event); } int action = event.getAction(); switch (action) { case MotionEvent.ACTION_UP: onActionUp(); mFab.onActionUp(); break; case MotionEvent.ACTION_CANCEL: onActionUp(); mFab.onActionUp(); break; } mGestureDetector.onTouchEvent(event); return super.onTouchEvent(event); } GestureDetector mGestureDetector = new GestureDetector(getContext(), new GestureDetector.SimpleOnGestureListener() { @Override public boolean onDown(MotionEvent e) { onActionDown(); if (mFab != null) { mFab.onActionDown(); } return super.onDown(e); } @Override public boolean onSingleTapUp(MotionEvent e) { onActionUp(); if (mFab != null) { mFab.onActionUp(); } return super.onSingleTapUp(e); } }); private class Shadow extends Drawable { private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private Paint mErase = new Paint(Paint.ANTI_ALIAS_FLAG); private Shadow() { this.init(); } private void init() { setLayerType(LAYER_TYPE_SOFTWARE, null); mPaint.setStyle(Paint.Style.FILL); mPaint.setColor(mColorNormal); mErase.setXfermode(PORTER_DUFF_CLEAR); if (!isInEditMode()) { mPaint.setShadowLayer(mShadowRadius, mShadowXOffset, mShadowYOffset, mShadowColor); } } @Override public void draw(Canvas canvas) { RectF shadowRect = new RectF( mShadowRadius + Math.abs(mShadowXOffset), mShadowRadius + Math.abs(mShadowYOffset), mRawWidth, mRawHeight ); canvas.drawRoundRect(shadowRect, mCornerRadius, mCornerRadius, mPaint); canvas.drawRoundRect(shadowRect, mCornerRadius, mCornerRadius, mErase); } @Override public void setAlpha(int alpha) { } @Override public void setColorFilter(ColorFilter cf) { } @Override public int getOpacity() { return 0; } } }4)Util.java==============package com.eppico.fabmenu; import android.content.Context;import android.os.Build; final class Util { private Util() { } static int dpToPx(Context context, float dp) { final float scale = context.getResources().getDisplayMetrics().density; return Math.round(dp * scale); } static boolean hasJellyBean() { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN; } static boolean hasLollipop() { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP; } }
No comments:
Post a Comment