Giter Club home page Giter Club logo

floating-bubble-view's Introduction

πŸ€Floating Bubble View

An Android library that adds floating bubbles to your home screen 🎨, supports both XML and πŸ’˜ Jetpack Compose


Find this library useful? Don't forget to show some love by giving a Star⭐ πŸ₯°

Bubble Custom

Β 

Variants

  • Flutter

    If you are looking for a Flutter version of this library, check dash_bubble, a Flutter plugin that allows you to create a floating bubble on the screen. by Moaz El-sawaf.

Table of Contents πŸ“

  1. Getting started
  2. Setup
  3. Usage
  4. Contribution guide
  5. WIP Note 🚧
  6. License

I, Getting started πŸ•πŸ”πŸŸ

Ensure your app’s minimum SDK version is 21+ and `mavenCentral()` included
1. Ensure your app’s minimum SDK version is 21+. This is declared in the module-level `build.gradle` file
android {
    defaultConfig {
        ...
        minSdk 21
    }
  1. Ensure the mavenCentral() repository is declared in the project-level build.gradle/setting.gradle file:

    settings.gradle
    pluginManagement {
        repositories {
            ...
            mavenCentral()
        }
    }
    dependencyResolutionManagement {
        ...
        repositories {
            ...
            mavenCentral()
        }
    }
    build.gradle (project-level) (on old gradle versions)
        allprojects {
            repositories {
                mavenCentral()
                ...
            }
            ...
        }

Declare the dependencies in the module-level build.gradle file πŸ€

dependencies {
    implementation("io.github.torrydo:floating-bubble-view:<LATEST_VERSION>")
}

II, Setup πŸš€βœˆπŸ›°

1, extends ExpandableBubbleService() and call expand() or minimize() 1️⃣

Java
Java docs is not completed yet because the author is (really) busy and (a little) tired πŸ˜ͺ
Kotlin
class MyService: ExpandableBubbleService() {

    override fun onCreate() {
        super.onCreate()
        minimize()
    }

   // optional, only required if you want to call minimize()
   override fun configBubble(): BubbleBuilder? {
       return ...
   }

   // optional, only required if you want to call expand()
   override fun configExpandedBubble(): ExpandedBubbleBuilder? {
       return ...
   }
}

2, add bubble service to the manifest file 2️⃣

<application>
     <!-- these two permissions are added by default -->
     <!-- <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> -->
     <!-- <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/> -->

     <!-- You can find more permissions, use cases here: https://developer.android.com/about/versions/14/changes/fgs-types-required  -->
     <uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
     
     <service
         android:name="<YOUR_PACKAGE>.MyService"
         android:foregroundServiceType="specialUse"
         >
         <property android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE" android:value="foo"/>  <!-- optional -->
     </service>

</application>
Android 13 and earlier
    <!-- these two permissions are added by default -->
    <!-- <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> -->
    <!-- <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/> -->

    <application>
        ...
        <service android:name="<YOUR_PACKAGE>.MyService" />

    </application>

3, start bubble service and enjoy 3️⃣ πŸŽ‰πŸ€

Make sure "display over other apps" permission is granted, otherwise the app will crash βš β—πŸ’₯

Java
    Intent intent = new Intent(context, MyService.class);
    
    ContextCompat.startForegroundService(this, intent);
    // or
    // startService(intent);           // for android version lower than 8.0 (android O)
    // startForegroundService(intent); // for android 8.0 and higher
Kotlin
    val intent = Intent(context, MyService::class.java)
    
    ContextCompat.startForegroundService(this, intent)
    // or
    // startService(intent)           // for android version lower than 8.0 (android O)
    // startForegroundService(intent) // for android 8.0 and higher

III, Usage πŸ”₯

1, configBubble() and configExpandedBubble()

Java
public class MyServiceJava extends ExpandableBubbleService {

    @Override
    public void onCreate() {
        super.onCreate();
        minimize();
    }

    @Nullable
    @Override
    public BubbleBuilder configBubble() {
        View imgView = ViewHelper.fromDrawable(this, R.drawable.ic_rounded_blue_diamond, 60, 60);
        imgView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                expand();
            }
        });
        return new BubbleBuilder(this)
                .bubbleView(imgView)
                .bubbleStyle(R.style.default_bubble_style)
                .bubbleDraggable(true)
                .forceDragging(true)
                .closeBubbleView(ViewHelper.fromDrawable(this, R.drawable.ic_close_bubble))
                .closeBubbleStyle(R.style.default_close_bubble_style)
                .distanceToClose(100)
                .closeBehavior(CloseBubbleBehavior.FIXED_CLOSE_BUBBLE)
                .startLocation(100, 100)
                .enableAnimateToEdge(true)
                .bottomBackground(false)
                .addFloatingBubbleListener(new FloatingBubbleListener() {
                    @Override
                    public void onFingerDown(float x, float y) {}
                    @Override
                    public void onFingerUp(float x, float y) {}
                    @Override
                    public void onFingerMove(float x, float y) {}
                })
                ;
                
    }

    @Nullable
    @Override
    public ExpandedBubbleBuilder configExpandedBubble() {
        View expandedView = LayoutInflater.from(this).inflate(R.layout.layout_view_test, null);

        expandedView.findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                minimize();
            }
        });
        return new ExpandedBubbleBuilder(this)
                .expandedView(expandedView)
                .startLocation(0, 0)
                .draggable(true)
                .style(R.style.default_bubble_style)
                .fillMaxWidth(true)
                .enableAnimateToEdge(true)
                .dimAmount(0.5f);
    }
}
Kotlin
class MyServiceKt : ExpandableBubbleService() {

    override fun onCreate() {
        super.onCreate()
        minimize()
    }

    override fun configBubble(): BubbleBuilder? {
        val imgView = ViewHelper.fromDrawable(this, R.drawable.ic_rounded_blue_diamond, 60, 60)
        imgView.setOnClickListener {
            expand()
        }

        return BubbleBuilder(this)
            
            // set bubble view
            .bubbleView(imgView)
            
            // or our sweetie, Jetpack Compose
            .bubbleCompose {
                BubbleCompose()
            }
            
            // set style for the bubble, fade animation by default
            .bubbleStyle(null)
            
            // set start location for the bubble, (x=0, y=0) is the top-left
            .startLocation(100, 100)    // in dp
            .startLocationPx(100, 100)  // in px
            
            // enable auto animate bubble to the left/right side when release, true by default
            .enableAnimateToEdge(true)
            
            // set close-bubble view
            .closeBubbleView(ViewHelper.fromDrawable(this, R.drawable.ic_close_bubble, 60, 60))
            
            // set style for close-bubble, null by default
            .closeBubbleStyle(null)
            
            // DYNAMIC_CLOSE_BUBBLE: close-bubble moving based on the bubble's location
            // FIXED_CLOSE_BUBBLE (default): bubble will automatically move to the close-bubble when it reaches the closable-area
            .closeBehavior(CloseBubbleBehavior.DYNAMIC_CLOSE_BUBBLE)
            
            // the more value (dp), the larger closeable-area
            .distanceToClose(100)
            
            // enable bottom background, false by default
            .bottomBackground(true)
            
            .addFloatingBubbleListener(object : FloatingBubbleListener {
                override fun onFingerMove(x: Float, y: Float) {} // The location of the finger on the screen which triggers the movement of the bubble.
                override fun onFingerUp(x: Float, y: Float) {}   // ..., when finger release from bubble
                override fun onFingerDown(x: Float, y: Float) {} // ..., when finger tap the bubble
            })

    }

    override fun configExpandedBubble(): ExpandedBubbleBuilder? {

        val expandedView = LayoutInflater.from(this).inflate(R.layout.layout_view_test, null)
        expandedView.findViewById<View>(R.id.btn).setOnClickListener {
            minimize()
        }

        return ExpandedBubbleBuilder(this)
            .expandedView(expandedView)
            .expandedCompose { 
                ExpandedCompose()
            }
            // handle key code
            .onDispatchKeyEvent {
                if(it.keyCode == KeyEvent.KEYCODE_BACK){
                    minimize()
                }
                null
            }
            // set start location in dp
            .startLocation(0, 0)
            // allow expanded bubble can be draggable or not
            .draggable(true)
            // fade animation by default
            .style(null)
            // 
            .fillMaxWidth(true)
            // animate to the left/right side when release, trfalseue by default 
            .enableAnimateToEdge(true)
            // set background dimmer
            .dimAmount(0.6f)
    }
}

2, Override default Notification

Java
public class MyService extends ExpandableBubbleService {
    @Override
    public void startNotificationForeground() {
        startForeground(...);

        // or you can use NotificationHelper class
        // val noti = NotificationHelper(this)
        // noti.createNotificationChannel()
        // startForeground(noti.notificationId, noti.defaultNotification())
    }
}
Kotlin
class MyService : FloatingBubbleService() {
    override fun startNotificationForeground() {
        startForeground(...)

        // or you can use NotificationHelper class
        // val noti = NotificationHelper(this)
        // noti.createNotificationChannel()
        // startForeground(noti.notificationId, noti.defaultNotification())
    }
}
Notice since Android 13 ⚠

Starting in Android 13 (API level 33), notifications are only visible if the "POST_NOTIFICATIONS" permission is granted.

The service will run normally even if the notification is not visible. πŸ€

P/s: You still need to initialize the notification before showing any view.


3, Methods in ExpandableBubbleService

Name Description
removeAll() remove all bubbles
expand() show expanded-bubble
minimize() show bubble
enableBubbleDragging() enable bubble dragging or not
enableExpandedBubbleDragging() enable expanded-bubble dragging or not
animateBubbleToEdge() animate bubble to edge of the screen
animateExpandedBubbleToEdge() animate expanded-bubble to edge of the screen

4, Helper Class

  • ViewHelper()

    • fromBitmap(context, bitmap): View
    • fromBitmap(context, bitmap, widthDp, heightDp): View
    • fromDrawable(context, drawableRes): View
    • fromDrawable(context, drawableRes, widthDp, heightDp)
  • NotificationHelper(context, channelId, channelName, notificationId)

    • notify(Notification): update notification based on notificationId
    • createNotificationChannel(): create notification channel from android 8 and above
    • defaultNotification(): return default notification

IV, Contribution Guide πŸ‘

Contributions are welcome! πŸ™Œ

  • If you come across a bug or have an idea for a new feature, please let us know by creating an Issue πŸ›πŸ’‘
  • If you've already fixed a bug or implemented a feature, feel free to submit a Pull request πŸš€
  • Having questions, ideas, or feedback? Don't worry, I gotchu. Simply open a Discussion πŸ”Š
  • Find this project useful? Don't forget to show some love by giving a star ⭐

Thank you! πŸ’–


V, Work in Progress 🚧

This library is still under heavy development. There is still a lot of code cleanup to do, so expect breaking API changes over time.

Please refer to the following page to check out the change-log: Releases

Everything's gonna be ok! πŸ€


VI, License


    Copyright 2022 TorryDo

    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.

floating-bubble-view's People

Contributors

torrydo avatar fluffyspace avatar kumpello avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.