FloatMenu Android Library

repository·master·Indexed 20 days ago

https://github.com/crosg/floatmenusample

A lightweight, customizable Android library for creating floating menus. It supports docking, auto-shrinking, red-dot notifications, and can be implemented within an Activity or as a persistent desktop floating window via a Service using the SYSTEM_ALERT_WINDOW permission. Features include a builder pattern for configuration, custom FloatItem definitions, and a BaseFloatDialog for custom floating windows.

Tokens
9.5K
Snippets
28
Records
33
Agent score
71%

What's inside FloatMenu

  1. Use FloatLogoMenu interaction patterns

    master

    The FloatLogoMenu implements smart interaction logic based on its current state:

    1. Shrunk State (at screen edge): Clicking the logo restores it to its full position (100% visibility) but does not open the menu.
    2. Normal State (floating): Clicking the logo expands the menu.
    3. Expanded State: Clicking the logo again closes the menu.

    Additionally, the menu includes built-in boundary constraints to prevent the logo from being dragged outside the screen boundaries (X-axis: [0, screenWidth - logoWidth]; Y-axis: [statusBarHeight, screenHeight - logoHeight]).

  2. Implement dynamic icon status for DotImageView

    master

    To support dynamic icon states (such as showing different icons for 'Muted', 'Vibrating', or 'Calling'), you can implement a status management pattern. While the full implementation details for DotImageView are part of the library's internal updates, the suggested pattern involves using a status constant set and notifying listeners when the state changes.

    public class DotStatus {
        public static final int STATUS_NORMAL = 0;     // Normal
        public static final int STATUS_MUTED = 1;       // Muted
        public static final int STATUS_VIBRATE = 2;      // Vibrating
        public static final int STATUS_CALLING = 3;    // Calling
    
        private int currentStatus = STATUS_NORMAL;
    
        public void updateStatus(int newStatus) {
            this.currentStatus = newStatus;
            notifyListeners();
        }
    
        public int getCurrentStatus() {
            return currentStatus;
        }
    }
  3. Compare Maven Publishing Options

    master
    FeatureGitHub PackagesJitPackMaven Central
    Difficulty⭐⭐⭐⭐⭐⭐⭐
    SpeedFastFastSlow
    StabilityHighMediumHighest
    Recommendation⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐

    Recommendation: Use GitHub Packages for a balance of ease of use and stability, especially if you are already using GitHub and want to automate with GitHub Actions.

  4. Publish to GitHub Packages

    master

    To publish the library to GitHub Packages, follow these steps:

    1. Configure build.gradle: Add the maven-publish plugin and define the publishing block. Ensure you set the groupId (typically your GitHub username), artifactId, and version.
    2. Set Credentials: Add your GitHub username and a Personal Access Token (with repo and write:packages permissions) to your local.properties file using the keys gpr.user and gpr.key.
    3. Execute Publication: Run the Gradle publish command.

    Credentials in local.properties:

    gpr.user=YOUR_GITHUB_USERNAME
    gpr.key=YOUR_GITHUB_TOKEN
    // 1. Add plugins to build.gradle
    plugins {
        id 'com.android.library'
        id 'maven-publish'
    }
    
    version = "2.4.0"
    group = "com.github.fanofdemo"
    
    // 2. Configure publishing
    afterEvaluate {
        publishing {
            publications {
                release(MavenPublication) {
                    from components.release
                    groupId = 'com.github.fanofdemo'
                    artifactId = 'FloatMenu'
                    version = '2.4.0'
                    // ... pom configuration
                }
            }
            repositories {
                maven {
                    name = "GitHubPackages"
                    url = "https://maven.pkg.github.com/fanOfdemo/FloatMenuSample"
                    credentials {
                        username = System.getenv("GITHUB_USER") || project.findProperty("gpr.user") ?: System.getenv("USERNAME")
                        password = System.getenv("GITHUB_TOKEN") || project.findProperty("gpr.key") ?: System.getenv("TOKEN")
                    }
                }
            }
        }
    }
    # 3. Run the publish command
    ./gradlew publish
  5. Manage FloatMenu lifecycle in Activity

    master

    To prevent memory leaks and ensure proper cleanup, manage the FloatMenu instance within the Activity lifecycle:

    1. onResume(): Initialize and show the menu if it hasn't been created.
    2. onPause(): Call .hide() to hide the menu when the activity is not in focus.
    3. onDestroy(): Call .destroyFloat() to completely remove the menu and clean up resources.
    @Override
    protected void onResume() {
        super.onResume();
        if (mFloatMenu == null) {
            mFloatMenu = FloatMenu.create(this)
                    .logo(R.drawable.logo)
                    .items(items)
                    .show();
        }
    }
    
    @Override
    protected void onPause() {
        super.onPause();
        if (mFloatMenu != null) {
            mFloatMenu.hide();
        }
    }
    
    @Override
    protected void onDestroy() {
        if (mFloatMenu != null) {
            mFloatMenu.destroyFloat();
            mFloatMenu = null;
        }
        super.onDestroy();
    }
  6. Install FloatMenu via Module Integration

    master

    Clone the repository and copy the FloatMenu module directly into your project.

    1. Clone the project: git clone https://github.com/ColdBrando/FloatMenuSample.git
    2. Copy the FloatMenu module to your project folder.
    3. Include it in settings.gradle: include ':FloatMenu'
    4. Add it to your build.gradle dependencies: implementation project(':FloatMenu')
    git clone https://github.com/ColdBrando/FloatMenuSample.git
    cp -r FloatMenuSample/FloatMenu your-project/
    // settings.gradle
    include ':FloatMenu'
    
    // build.gradle
    dependencies {
        implementation project(':FloatMenu')
    }
  7. Consume FloatMenu via GitHub Packages

    master

    To use FloatMenu in your Android project via GitHub Packages, you must configure your repository settings and add the dependency.

    1. Configure Repositories

    In your project's settings.gradle file, add the GitHub Packages Maven URL within the dependencyResolutionManagement block. It is highly recommended to use environment variables for credentials to avoid exposing your GitHub Token.

    2. Add Dependency

    Add the FloatMenu implementation to your module's build.gradle file using the specific group and version.

    3. Public Access

    If the package is not public, users must provide credentials. To make the package accessible without authentication, change the package visibility to 'Public' in the GitHub Package settings under the 'Danger Zone'.

    // settings.gradle
    dependencyResolutionManagement {
        repositories {
            maven {
                url = "https://maven.pkg.github.com/fanOfDemo/FloatMenuSample"
                credentials {
                    // Recommended: Use environment variables
                    username = System.getenv("GITHUB_USER")
                    password = System.getenv("GITHUB_TOKEN")
                }
            }
        }
    }
    
    // build.gradle
    dependencies {
        implementation 'com.github.fanofdemo:FloatMenu:2.4.0'
    }
  8. Automate publishing with GitHub Actions

    master

    You can automate the release process to GitHub Packages using GitHub Actions. This workflow triggers whenever a new tag matching v*.*.* is pushed to the repository.

    Create a workflow file at .github/workflows/release.yml to handle the checkout, JDK setup, and the Gradle publish task using the built-in GITHUB_TOKEN secret.

    name: Release to GitHub Packages
    
    on:
      push:
        tags:
          - 'v*.*.*'
    
    jobs:
      release:
        runs-on: ubuntu-latest
        steps:
          - name: Checkout code
            uses: actions/checkout@v4
    
          - name: Set up JDK 17
            uses: actions/setup-java@v4
            with:
              java-version: '17'
              distribution: 'temurin'
    
          - name: Grant execute permission for gradlew
            run: chmod +x gradlew
    
          - name: Publish to GitHub Packages
            run: ./gradlew :FloatMenu:publish
            env:
              GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  9. Manage FloatMenu lifecycle in Service

    master

    When using FloatMenu in a Service, use getApplicationContext() to create the menu. Ensure you call .destroyFloat() in the Service's onDestroy() method to clean up the overlay.

    public class FloatMenuService extends Service {
        private FloatLogoMenu mFloatMenu;
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            if (mFloatMenu == null) {
                mFloatMenu = FloatMenu.create(getApplicationContext())
                        .logo(R.drawable.logo)
                        .items(items)
                        .location(FloatMenu.LEFT)
                        .show();
            }
            return START_STICKY;
        }
    
        @Override
        public void onDestroy() {
            if (mFloatMenu != null) {
                mFloatMenu.destroyFloat();
                mFloatMenu = null;
            }
            super.onDestroy();
        }
    }
  10. Use FloatMenu in a Service (Desktop Floating)

    master

    To show the menu outside the application context (on the desktop), you must use a Service and request the SYSTEM_ALERT_WINDOW permission.

    1. Add Permission to AndroidManifest.xml: <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

    2. Implement Service: In onCreate, initialize the menu using FloatMenu.create(getApplicationContext()). In onDestroy, call mFloatMenu.destroyFloat() to clean up.

    3. Register Service in AndroidManifest.xml:

      <service android:name=".FloatMenuService" android:enabled="true" android:exported="false" />
    4. Start/Stop Service from your Activity: startService(new Intent(this, FloatMenuService.class));

    public class FloatMenuService extends Service {
        private FloatMenu mFloatMenu;
    
        @Override
        public void onCreate() {
            super.onCreate();
            initFloatMenu();
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            if (mFloatMenu != null) {
                mFloatMenu.show();
            }
            return START_STICKY;
        }
    
        @Override
        public void onDestroy() {
            if (mFloatMenu != null) {
                mFloatMenu.destroyFloat();
            }
            super.onDestroy();
        }
    
        private void initFloatMenu() {
            List<FloatItem> items = new ArrayList<>();
            items.add(new FloatItem("首页", R.drawable.icon_home));
    
            mFloatMenu = FloatMenu.create(getApplicationContext())
                .logo(R.drawable.logo)
                .items(items)
                .location(FloatMenu.LEFT)
                .show();
        }
    }
  11. Use JitPack for easy dependency management

    master

    JitPack is the simplest way to use the library. It builds directly from your GitHub tags/releases without manual Maven configuration.

    1. Add JitPack repository to your Gradle files.
    2. Add the dependency using the format com.github.USER:REPO:TAG.

    Example:

    repositories {
        maven { url 'https://jitpack.io' }
    }
    
    dependencies {
        implementation 'com.github.fanOfdemo:FloatMenuSample:v2.4.0'
    }
    repositories {
        maven { url 'https://jitpack.io' }
    }
    
    dependencies {
        implementation 'com.github.fanofdemo:FloatMenuSample:v2.4.0'
    }