From 2cdaf1d5b00afb4be6f621c542d7767577a071a6 Mon Sep 17 00:00:00 2001 From: Joel Steres Date: Fri, 22 Jun 2018 02:16:46 -0700 Subject: [PATCH 1/3] Add centeringView --- .../library/FloatingActionMenu.java | 42 ++++++++++++++++--- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/library/src/main/java/com/oguzdev/circularfloatingactionmenu/library/FloatingActionMenu.java b/library/src/main/java/com/oguzdev/circularfloatingactionmenu/library/FloatingActionMenu.java index c0764fc..6b6b6dd 100644 --- a/library/src/main/java/com/oguzdev/circularfloatingactionmenu/library/FloatingActionMenu.java +++ b/library/src/main/java/com/oguzdev/circularfloatingactionmenu/library/FloatingActionMenu.java @@ -35,6 +35,8 @@ public class FloatingActionMenu { /** Reference to the view (usually a button) to trigger the menu to show */ private View mainActionView; + /** Optional reference to the view around which to center the menu (if differs from mainActionView */ + private View centeringView; /** The angle (in degrees, modulus 360) which the circular menu starts from */ private int startAngle; /** The angle (in degrees, modulus 360) which the circular menu ends at */ @@ -61,14 +63,18 @@ public class FloatingActionMenu { /** * Constructor that takes the parameters collected using {@link FloatingActionMenu.Builder} * @param mainActionView + * @param centeringView * @param startAngle * @param endAngle * @param radius * @param subActionItems * @param animationHandler * @param animated + * @param stateChangeListener + * @param systemOverlay */ public FloatingActionMenu(final View mainActionView, + final View centeringView, int startAngle, int endAngle, int radius, @@ -78,6 +84,7 @@ public FloatingActionMenu(final View mainActionView, MenuStateChangeListener stateChangeListener, final boolean systemOverlay) { this.mainActionView = mainActionView; + this.centeringView = centeringView; this.startAngle = startAngle; this.endAngle = endAngle; this.radius = radius; @@ -308,10 +315,10 @@ public void updateItemPositions() { * such as when a user clicks the action button. * @return a Point containing x and y coordinates of the top left corner of action view */ - private Point getActionViewCoordinates() { + private Point getViewCoordinates(View view) { int[] coords = new int[2]; // This method returns a x and y values that can be larger than the dimensions of the device screen. - mainActionView.getLocationOnScreen(coords); + view.getLocationOnScreen(coords); // So, we need to deduce the offsets. if(systemOverlay) { @@ -331,12 +338,27 @@ private Point getActionViewCoordinates() { * @return the action view center point */ public Point getActionViewCenter() { - Point point = getActionViewCoordinates(); + Point point = getViewCoordinates(mainActionView); point.x += mainActionView.getMeasuredWidth() / 2; point.y += mainActionView.getMeasuredHeight() / 2; return point; } + /** + * Returns the center point of the centering view + * @return the action view center point + */ + public Point getMenuCenter() { + if (centeringView == null) { + return getActionViewCenter(); + } else { + Point point = getViewCoordinates(centeringView); + point.x += centeringView.getMeasuredWidth() / 2; + point.y += centeringView.getMeasuredHeight() / 2; + return point; + } + } + /** * Calculates the desired positions of all items. * @return getActionViewCenter() @@ -344,7 +366,8 @@ public Point getActionViewCenter() { private Point calculateItemPositions() { // Create an arc that starts from startAngle and ends at endAngle // in an area that is as large as 4*radius^2 - final Point center = getActionViewCenter(); + final Point origin = getActionViewCenter(); + final Point center = getMenuCenter(); RectF area = new RectF(center.x - radius, center.y - radius, center.x + radius, center.y + radius); Path orbit = new Path(); @@ -369,7 +392,7 @@ private Point calculateItemPositions() { subActionItems.get(i).x = (int) coords[0] - subActionItems.get(i).width / 2; subActionItems.get(i).y = (int) coords[1] - subActionItems.get(i).height / 2; } - return center; + return origin; } /** @@ -596,6 +619,7 @@ public static class Builder { private int endAngle; private int radius; private View actionView; + private View centeringView; private List subActionItems; private MenuAnimationHandler animationHandler; private boolean animated; @@ -705,8 +729,14 @@ public Builder attachTo(View actionView) { return this; } + public Builder centerAt(View centeringView) { + this.centeringView = centeringView; + return this; + } + public FloatingActionMenu build() { return new FloatingActionMenu(actionView, + centeringView, startAngle, endAngle, radius, @@ -730,4 +760,4 @@ public static WindowManager.LayoutParams getDefaultSystemWindowParams() { return params; } -} \ No newline at end of file +} From 28da9aac7985747f8248103743e14562edde7ea7 Mon Sep 17 00:00:00 2001 From: Joel Steres Date: Fri, 22 Jun 2018 02:50:46 -0700 Subject: [PATCH 2/3] Add centerAt demo to sample project --- samples/src/main/AndroidManifest.xml | 8 + .../samples/DemoActivity.java | 6 +- .../samples/MenuAltCenteredActivity.java | 172 ++++++++++++++++++ 3 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 samples/src/main/java/com/oguzdev/circularfloatingactionmenu/samples/MenuAltCenteredActivity.java diff --git a/samples/src/main/AndroidManifest.xml b/samples/src/main/AndroidManifest.xml index 0f5a625..00f0a97 100644 --- a/samples/src/main/AndroidManifest.xml +++ b/samples/src/main/AndroidManifest.xml @@ -60,6 +60,14 @@ android:name="android.support.PARENT_ACTIVITY" android:value="com.oguzdev.circularfloatingactionmenu.samples.DemoActivity" /> + + + simpleAdapter = new ArrayAdapter(getActivity(), android.R.layout.simple_list_item_1, items); demosListView = (ListView) rootView.findViewById(R.id.demosListView); @@ -92,6 +93,9 @@ public void onItemClick(AdapterView parent, View view, int position, long id) case 4: startActivity(new Intent(getActivity(), SystemOverlayMenuActivity.class)); break; + case 5: + startActivity(new Intent(getActivity(), MenuAltCenteredActivity.class)); + break; } } } diff --git a/samples/src/main/java/com/oguzdev/circularfloatingactionmenu/samples/MenuAltCenteredActivity.java b/samples/src/main/java/com/oguzdev/circularfloatingactionmenu/samples/MenuAltCenteredActivity.java new file mode 100644 index 0000000..fff7b57 --- /dev/null +++ b/samples/src/main/java/com/oguzdev/circularfloatingactionmenu/samples/MenuAltCenteredActivity.java @@ -0,0 +1,172 @@ +package com.oguzdev.circularfloatingactionmenu.samples; + +import android.animation.ObjectAnimator; +import android.animation.PropertyValuesHolder; +import android.os.Bundle; +import android.support.v7.app.ActionBarActivity; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ImageView; + +import com.oguzdev.circularfloatingactionmenu.library.FloatingActionButton; +import com.oguzdev.circularfloatingactionmenu.library.FloatingActionMenu; +import com.oguzdev.circularfloatingactionmenu.library.SubActionButton; + +public class MenuAltCenteredActivity extends ActionBarActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_menu_with_fab); + + // Set up the white button on the lower right corner + // more or less with default parameter + final ImageView fabIconNew = new ImageView(this); + fabIconNew.setImageDrawable(getResources().getDrawable(R.drawable.ic_action_new_light)); + final FloatingActionButton rightLowerButton = new FloatingActionButton.Builder(this) + .setContentView(fabIconNew) + .build(); + + // Set up the large red button on the center right side + // With custom button and content sizes and margins + int redActionButtonSize = getResources().getDimensionPixelSize(R.dimen.red_action_button_size); + int redActionButtonMargin = getResources().getDimensionPixelOffset(R.dimen.action_button_margin); + int redActionButtonContentSize = getResources().getDimensionPixelSize(R.dimen.red_action_button_content_size); + int redActionButtonContentMargin = getResources().getDimensionPixelSize(R.dimen.red_action_button_content_margin); + int redActionMenuRadius = getResources().getDimensionPixelSize(R.dimen.red_action_menu_radius); + int blueSubActionButtonSize = getResources().getDimensionPixelSize(R.dimen.blue_sub_action_button_size); + int blueSubActionButtonContentMargin = getResources().getDimensionPixelSize(R.dimen.blue_sub_action_button_content_margin); + + ImageView fabIconStar = new ImageView(this); + fabIconStar.setImageDrawable(getResources().getDrawable(R.drawable.ic_action_important)); + + FloatingActionButton.LayoutParams starParams = new FloatingActionButton.LayoutParams(redActionButtonSize, redActionButtonSize); + starParams.setMargins(redActionButtonMargin, + redActionButtonMargin, + redActionButtonMargin, + redActionButtonMargin); + fabIconStar.setLayoutParams(starParams); + + FloatingActionButton.LayoutParams fabIconStarParams = new FloatingActionButton.LayoutParams(redActionButtonContentSize, redActionButtonContentSize); + fabIconStarParams.setMargins(redActionButtonContentMargin, + redActionButtonContentMargin, + redActionButtonContentMargin, + redActionButtonContentMargin); + + final FloatingActionButton leftCenterButton = new FloatingActionButton.Builder(this) + .setContentView(fabIconStar, fabIconStarParams) + .setBackgroundDrawable(R.drawable.button_action_red_selector) + .setPosition(FloatingActionButton.POSITION_LEFT_CENTER) + .setLayoutParams(starParams) + .build(); + + + SubActionButton.Builder rLSubBuilder = new SubActionButton.Builder(this); + ImageView rlIcon1 = new ImageView(this); + ImageView rlIcon2 = new ImageView(this); + ImageView rlIcon3 = new ImageView(this); + ImageView rlIcon4 = new ImageView(this); + + rlIcon1.setImageDrawable(getResources().getDrawable(R.drawable.ic_action_chat_light)); + rlIcon2.setImageDrawable(getResources().getDrawable(R.drawable.ic_action_camera_light)); + rlIcon3.setImageDrawable(getResources().getDrawable(R.drawable.ic_action_video_light)); + rlIcon4.setImageDrawable(getResources().getDrawable(R.drawable.ic_action_place_light)); + + // Build the menu with default options: light theme, 90 degrees, 72dp radius. + // Set 4 default SubActionButtons + final FloatingActionMenu rightLowerMenu = new FloatingActionMenu.Builder(this) + .addSubActionView(rLSubBuilder.setContentView(rlIcon1).build()) + .addSubActionView(rLSubBuilder.setContentView(rlIcon2).build()) + .addSubActionView(rLSubBuilder.setContentView(rlIcon3).build()) + .addSubActionView(rLSubBuilder.setContentView(rlIcon4).build()) + .attachTo(leftCenterButton) + .centerAt(rightLowerButton) + .build(); + + // Listen menu open and close events to animate the button content view + rightLowerMenu.setStateChangeListener(new FloatingActionMenu.MenuStateChangeListener() { + @Override + public void onMenuOpened(FloatingActionMenu menu) { + // Rotate the icon of rightLowerButton 45 degrees clockwise + fabIconNew.setRotation(0); + PropertyValuesHolder pvhR = PropertyValuesHolder.ofFloat(View.ROTATION, 45); + ObjectAnimator animation = ObjectAnimator.ofPropertyValuesHolder(fabIconNew, pvhR); + animation.start(); + } + + @Override + public void onMenuClosed(FloatingActionMenu menu) { + // Rotate the icon of rightLowerButton 45 degrees counter-clockwise + fabIconNew.setRotation(45); + PropertyValuesHolder pvhR = PropertyValuesHolder.ofFloat(View.ROTATION, 0); + ObjectAnimator animation = ObjectAnimator.ofPropertyValuesHolder(fabIconNew, pvhR); + animation.start(); + } + }); + + + // Set up customized SubActionButtons for the right center menu + SubActionButton.Builder lCSubBuilder = new SubActionButton.Builder(this); + lCSubBuilder.setBackgroundDrawable(getResources().getDrawable(R.drawable.button_action_blue_selector)); + + FrameLayout.LayoutParams blueContentParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT); + blueContentParams.setMargins(blueSubActionButtonContentMargin, + blueSubActionButtonContentMargin, + blueSubActionButtonContentMargin, + blueSubActionButtonContentMargin); + lCSubBuilder.setLayoutParams(blueContentParams); + // Set custom layout params + FrameLayout.LayoutParams blueParams = new FrameLayout.LayoutParams(blueSubActionButtonSize, blueSubActionButtonSize); + lCSubBuilder.setLayoutParams(blueParams); + + ImageView lcIcon1 = new ImageView(this); + ImageView lcIcon2 = new ImageView(this); + ImageView lcIcon3 = new ImageView(this); + ImageView lcIcon4 = new ImageView(this); + ImageView lcIcon5 = new ImageView(this); + + lcIcon1.setImageDrawable(getResources().getDrawable(R.drawable.ic_action_camera)); + lcIcon2.setImageDrawable(getResources().getDrawable(R.drawable.ic_action_picture)); + lcIcon3.setImageDrawable(getResources().getDrawable(R.drawable.ic_action_video)); + lcIcon4.setImageDrawable(getResources().getDrawable(R.drawable.ic_action_location_found)); + lcIcon5.setImageDrawable(getResources().getDrawable(R.drawable.ic_action_headphones)); + + // Build another menu with custom options + final FloatingActionMenu leftCenterMenu = new FloatingActionMenu.Builder(this) + .addSubActionView(lCSubBuilder.setContentView(lcIcon1, blueContentParams).build()) + .addSubActionView(lCSubBuilder.setContentView(lcIcon2, blueContentParams).build()) + .addSubActionView(lCSubBuilder.setContentView(lcIcon3, blueContentParams).build()) + .addSubActionView(lCSubBuilder.setContentView(lcIcon4, blueContentParams).build()) + .addSubActionView(lCSubBuilder.setContentView(lcIcon5, blueContentParams).build()) + .setRadius(redActionMenuRadius) + .setStartAngle(70) + .setEndAngle(-70) + .attachTo(rightLowerButton) + .centerAt(leftCenterButton) + .build(); + + + } + + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + // Inflate the menu; this adds items to the action bar if it is present. + getMenuInflater().inflate(R.menu.menu_with_fab, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + // Handle action bar item clicks here. The action bar will + // automatically handle clicks on the Home/Up button, so long + // as you specify a parent activity in AndroidManifest.xml. + int id = item.getItemId(); + if (id == R.id.action_settings) { + return true; + } + return super.onOptionsItemSelected(item); + } +} From 649c48cf826898a996c3655d96da76bf1c3990ee Mon Sep 17 00:00:00 2001 From: Joel Steres Date: Tue, 3 Jul 2018 02:43:01 -0700 Subject: [PATCH 3/3] Add option to specify a specific centering Point --- .../library/FloatingActionMenu.java | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/library/src/main/java/com/oguzdev/circularfloatingactionmenu/library/FloatingActionMenu.java b/library/src/main/java/com/oguzdev/circularfloatingactionmenu/library/FloatingActionMenu.java index 6b6b6dd..e26efca 100644 --- a/library/src/main/java/com/oguzdev/circularfloatingactionmenu/library/FloatingActionMenu.java +++ b/library/src/main/java/com/oguzdev/circularfloatingactionmenu/library/FloatingActionMenu.java @@ -35,8 +35,10 @@ public class FloatingActionMenu { /** Reference to the view (usually a button) to trigger the menu to show */ private View mainActionView; - /** Optional reference to the view around which to center the menu (if differs from mainActionView */ + /** Optional reference to the view around which to center the menu (if differs from mainActionView) */ private View centeringView; + /** Optional reference to a point around which to center the menu. If specified this will take precedence over centeringView. */ + private Point centeringPoint; /** The angle (in degrees, modulus 360) which the circular menu starts from */ private int startAngle; /** The angle (in degrees, modulus 360) which the circular menu ends at */ @@ -64,6 +66,7 @@ public class FloatingActionMenu { * Constructor that takes the parameters collected using {@link FloatingActionMenu.Builder} * @param mainActionView * @param centeringView + * @param centeringPoint * @param startAngle * @param endAngle * @param radius @@ -75,6 +78,7 @@ public class FloatingActionMenu { */ public FloatingActionMenu(final View mainActionView, final View centeringView, + final Point centeringPoint, int startAngle, int endAngle, int radius, @@ -85,6 +89,7 @@ public FloatingActionMenu(final View mainActionView, final boolean systemOverlay) { this.mainActionView = mainActionView; this.centeringView = centeringView; + this.centeringPoint = centeringPoint; this.startAngle = startAngle; this.endAngle = endAngle; this.radius = radius; @@ -345,17 +350,19 @@ public Point getActionViewCenter() { } /** - * Returns the center point of the centering view + * Returns the center point of the centering view or point * @return the action view center point */ public Point getMenuCenter() { - if (centeringView == null) { - return getActionViewCenter(); - } else { + if (centeringPoint != null) { + return centeringPoint; + } else if (centeringView != null) { Point point = getViewCoordinates(centeringView); point.x += centeringView.getMeasuredWidth() / 2; point.y += centeringView.getMeasuredHeight() / 2; return point; + } else { + return getActionViewCenter(); } } @@ -620,6 +627,7 @@ public static class Builder { private int radius; private View actionView; private View centeringView; + private Point centeringPoint; private List subActionItems; private MenuAnimationHandler animationHandler; private boolean animated; @@ -734,9 +742,15 @@ public Builder centerAt(View centeringView) { return this; } + public Builder centerAt(Point centeringPoint) { + this.centeringPoint = centeringPoint; + return this; + } + public FloatingActionMenu build() { return new FloatingActionMenu(actionView, centeringView, + centeringPoint, startAngle, endAngle, radius,