Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/ShamylZakariya/FlyoutMenus
Simple material-style flyout menus for Android. There are many flyout type menus for Android, but this one is mine.
https://github.com/ShamylZakariya/FlyoutMenus
android menus
Last synced: 1 day ago
JSON representation
Simple material-style flyout menus for Android. There are many flyout type menus for Android, but this one is mine.
- Host: GitHub
- URL: https://github.com/ShamylZakariya/FlyoutMenus
- Owner: ShamylZakariya
- License: mit
- Created: 2016-07-06T15:10:42.000Z (almost 8 years ago)
- Default Branch: master
- Last Pushed: 2019-04-21T23:09:41.000Z (about 5 years ago)
- Last Synced: 2024-03-20T13:30:36.229Z (3 months ago)
- Topics: android, menus
- Language: Java
- Size: 8.26 MB
- Stars: 994
- Watchers: 19
- Forks: 89
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Lists
- awesome-github-android-ui - FlyoutMenus - Android简易MD风格弹出菜单 (菜单(Menu))
- awesome-github-android-ui - FlyoutMenus - Android简易MD风格弹出菜单 (菜单(Menu))
README
# FlyoutMenus
Simple material-style flyout menus for Android. There are many flyout type menus for Android, but this one is mine.```gradle
compile 'org.zakariya.flyoutmenus:flyoutmenu:0.5.3'
```- minSdkVersion: 14
*Note: when running on SDK less than 18, hardware rendering is disabled. This means that button shadows are clipped. To work around this, add a bit of padding to the view.*---
![BasicDemo](readme-assets/flyoutmenus-big.gif)
---
## XML
```xml
```
FlyoutMenuView attributes (all have `fm` prefix) are:
```xml
// the size of the button
// the background color of the trigger button
// the background color of the menu
// the color drawn behind the selected menu item
// width of items in the menu
// height of items in the menu
// margin around items in the menu
// menu anchoring position (see below)
// margin around the menu - menu will be positioned this far away from the button, but
// will also use this to respect screen edges// if provided, the trigger button will use this as a drawable
// elevation for the trigger button. if 0, no shadow is drawn
// elevation for the menu. if 0, no shadow is drawn
// if true, a shield (like for dialogs) is drawn behind the menu
// color of shield drawn behind menu, if shieldVisible == true
// if true, menu operates in "tap to open", "tap to select and dismiss" mode
```
The `fmMenuAnchor` attribute takes the following values:
* `top` : menu attached above the button
* `right` | `end` : menu attached to right of button
* `bottom` : menu attached beneath button
* `left` | `start` : menu attached to left of button
* `center` : menu centered on top of button## Java
To use a FlyoutMenuView, you must provide a `FlyoutMenuView.Adapter` (which provides `FlyoutMenuView.MenuItem` instances) and a `FlyoutMenuView.Layout` which describes how to position the items in the menu.
You must also provide a subclass of `FlyoutMenuView.MenuItem` to render your items. You may also subclass `FlyoutMenuView.ButtonRenderer` to render your trigger button, if you don't want to assign a `Drawable`.
Here's an example implementation of `FlyoutMenuView.MenuItem` and `FlyoutmenuView.ButtonRenderer` which draws a simple unicode character. I use it in the demo app to render emoji.```java
public class EmojiFlyoutMenu {static String getEmojiByUnicode(int unicode){
return new String(Character.toChars(unicode));
}public static class MenuItem extends FlyoutMenuView.MenuItem {
int emojiCode;
String emojiString;
TextPaint textPaint;public MenuItem(int id, int emojiCode, float size, @ColorInt int color) {
super(id);
this.emojiCode = emojiCode;
this.emojiString = getEmojiByUnicode(emojiCode);textPaint = new TextPaint();
textPaint.setTextSize(size);
textPaint.setTextAlign(Paint.Align.CENTER);
textPaint.setStyle(Paint.Style.FILL);
textPaint.setColor(color);
}public int getEmojiCode() {
return emojiCode;
}@Override
public void onDraw(Canvas canvas, RectF bounds, float degreeSelected) {
canvas.drawText(emojiString, bounds.centerX(), bounds.centerY() - ((textPaint.descent() + textPaint.ascent()) / 2), textPaint);
}
}public static class ButtonRenderer extends FlyoutMenuView.ButtonRenderer {
int emojiCode;
String emojiString;
Paint paint;
TextPaint textPaint;public ButtonRenderer(int emojiCode, float size, @ColorInt int color) {
super();this.setEmojiCode(emojiCode);
paint = new Paint();
paint.setAntiAlias(true);textPaint = new TextPaint();
textPaint.setTextSize(size);
textPaint.setTextAlign(Paint.Align.CENTER);
textPaint.setStyle(Paint.Style.FILL);
textPaint.setColor(color);
}public int getEmojiCode() {
return emojiCode;
}public void setEmojiCode(int emojiCode) {
this.emojiCode = emojiCode;
this.emojiString = getEmojiByUnicode(this.emojiCode);
}@Override
public void onDrawButtonContent(Canvas canvas, RectF buttonBounds, @ColorInt int buttonColor, float alpha) {
textPaint.setAlpha((int) (alpha * 255f));
canvas.drawText(emojiString, buttonBounds.centerX(), buttonBounds.centerY() - ((textPaint.descent() + textPaint.ascent()) / 2), textPaint);
}
}
}
```To use the above:
```java
FlyoutMenuView smileyFlyoutMenu = findViewById(R.id.smileyFlyoutMenu);int[] emojiCodes = {
0x1F60D, //smiling face heart shaped eyes
0x1F605, // smiling face with open mouth and cold sweat
0x1F60A, // smiling face
0x1F613, // face with cold sweat
0x1F61E, // disappointed face
0x1F620, // angry face
0x1F62D, // loudly crying face
0x1F4A9, // pile of poo
};@ColorInt int color = ContextCompat.getColor(this, R.color.smileyMenuCharColor);
float fontSizeInMenu = getResources().getDimension(R.dimen.smiley_menu_item_size) * 0.5f;
float fontSizeInButton = getResources().getDimension(R.dimen.flyout_menu_button_size) * 0.5f;// build a List<> of EmojiFlyoutMenu.MenuItem
List menuItems = new ArrayList<>();
for (int code : emojiCodes) {
menuItems.add(new EmojiFlyoutMenu.MenuItem(menuItems.size(), code, fontSizeInMenu, color));
}// assign a GridLayout with 2 columns and unspecified rows (allows menu to grow vertically)
smileyFlyoutMenu.setLayout(new FlyoutMenuView.GridLayout(2, FlyoutMenuView.GridLayout.UNSPECIFIED));// assign the menuItems via an ArrayAdapter
smileyFlyoutMenu.setAdapter(new FlyoutMenuView.ArrayAdapter<>(menuItems));// create and assign the button renderer. we'll change the button renderer's emoji in the callback below
final EmojiFlyoutMenu.ButtonRenderer renderer = new EmojiFlyoutMenu.ButtonRenderer(emojiCodes[0], fontSizeInButton, color);
smileyFlyoutMenu.setButtonRenderer(renderer);smileyFlyoutMenu.setSelectionListener(new FlyoutMenuView.SelectionListener() {
@Override
public void onItemSelected(FlyoutMenuView flyoutMenuView, FlyoutMenuView.MenuItem item) {
// user has selected an item. update the button renderer's emoji to match
renderer.setEmojiCode(((EmojiFlyoutMenu.MenuItem) item).getEmojiCode());
}@Override
public void onDismissWithoutSelection(FlyoutMenuView flyoutMenuView) {
}
});
```