├── FloatiesDemo ├── .gitignore ├── app │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── bezyapps │ │ │ └── floatiesdemo │ │ │ └── ApplicationTest.java │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── bezyapps │ │ │ │ └── floatiesdemo │ │ │ │ └── MainActivity.java │ │ └── res │ │ │ ├── drawable │ │ │ └── float_icon.png │ │ │ ├── layout │ │ │ ├── activity_main.xml │ │ │ ├── float_body.xml │ │ │ └── float_head.xml │ │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxxhdpi │ │ │ └── ic_launcher.png │ │ │ ├── values-w820dp │ │ │ └── dimens.xml │ │ │ └── values │ │ │ ├── colors.xml │ │ │ ├── dimens.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ └── test │ │ └── java │ │ └── com │ │ └── bezy │ │ └── floatiesdemo │ │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── FloatiesLibrary ├── .gitignore ├── build.gradle ├── floaties │ ├── .gitignore │ ├── build.gradle │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── bezyapps │ │ │ └── floatieslibrary │ │ │ └── ApplicationTest.java │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── bezyapps │ │ │ └── floatieslibrary │ │ │ ├── Floaty.java │ │ │ └── FloatyOrientationListener.java │ │ └── res │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── LICENSE └── README.md /FloatiesDemo/.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | 15 | # Gradle files 16 | .gradle/ 17 | build/ 18 | /*/build/ 19 | 20 | # Local configuration file (sdk path, etc) 21 | local.properties 22 | 23 | # Proguard folder generated by Eclipse 24 | proguard/ 25 | 26 | # Log Files 27 | *.log 28 | 29 | #IntelliJ IDEA 30 | .idea 31 | *.iml 32 | *.ipr 33 | *.iws 34 | 35 | *.iml 36 | .gradle 37 | /local.properties 38 | /.idea/workspace.xml 39 | /.idea/libraries 40 | .DS_Store 41 | /build 42 | /captures 43 | -------------------------------------------------------------------------------- /FloatiesDemo/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /FloatiesDemo/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "22.0.1" 6 | 7 | defaultConfig { 8 | applicationId "com.bezy.floatiesdemo" 9 | minSdkVersion 11 10 | targetSdkVersion 23 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | testCompile 'junit:junit:4.12' 25 | compile 'com.android.support:appcompat-v7:23.1.1' 26 | compile 'com.bezyapps.floatieslibrary:floaties:1.0.1' 27 | } 28 | -------------------------------------------------------------------------------- /FloatiesDemo/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /home/ericbhatti/android-sdk-linux/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /FloatiesDemo/app/src/androidTest/java/com/bezyapps/floatiesdemo/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.bezyapps.floatiesdemo; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /FloatiesDemo/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /FloatiesDemo/app/src/main/java/com/bezyapps/floatiesdemo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.bezyapps.floatiesdemo; 2 | 3 | import android.Manifest; 4 | import android.annotation.TargetApi; 5 | import android.app.Notification; 6 | import android.app.PendingIntent; 7 | import android.content.DialogInterface; 8 | import android.content.Intent; 9 | import android.content.pm.PackageManager; 10 | import android.net.Uri; 11 | import android.os.Build; 12 | import android.provider.Settings; 13 | import android.support.v4.app.ActivityCompat; 14 | import android.support.v4.content.ContextCompat; 15 | import android.support.v7.app.AlertDialog; 16 | import android.support.v7.app.AppCompatActivity; 17 | import android.os.Bundle; 18 | import android.text.Html; 19 | import android.text.Spanned; 20 | import android.view.LayoutInflater; 21 | import android.view.View; 22 | import android.widget.AdapterView; 23 | import android.widget.ArrayAdapter; 24 | import android.widget.Button; 25 | import android.widget.EditText; 26 | import android.widget.ListView; 27 | import android.widget.Toast; 28 | 29 | import com.bezy.floatiesdemo.R; 30 | import com.bezyapps.floatieslibrary.Floaty; 31 | import com.bezyapps.floatieslibrary.FloatyOrientationListener; 32 | 33 | import java.util.ArrayList; 34 | 35 | public class MainActivity extends AppCompatActivity { 36 | 37 | Floaty floaty; 38 | Button button_start, button_stop; 39 | private static final int NOTIFICATION_ID = 1500; 40 | public static final int PERMISSION_REQUEST_CODE = 16; 41 | 42 | @Override 43 | protected void onCreate(Bundle savedInstanceState) { 44 | super.onCreate(savedInstanceState); 45 | setContentView(R.layout.activity_main); 46 | button_start = (Button) findViewById(R.id.button_start); 47 | button_stop = (Button) findViewById(R.id.button_stop); 48 | Intent intent = new Intent(this, MainActivity.class); 49 | PendingIntent resultPendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); 50 | Notification notification = Floaty.createNotification(this, "Floaty Demo", "Service Running", R.drawable.float_icon, resultPendingIntent); 51 | 52 | // Inflate the Views that are to be used as HEAD and BODY of The Window 53 | View head = LayoutInflater.from(this).inflate(R.layout.float_head, null); 54 | // You should not add click listeners to head as it will be overridden, but the purpose of not making head just 55 | // an ImageView is so you can add multiple views in it, and show and hide the relevant views to notify user etc. 56 | View body = LayoutInflater.from(this).inflate(R.layout.float_body, null); 57 | 58 | // Access child views of body 59 | final ListView listView = (ListView) body.findViewById(R.id.listViewTasks); 60 | final EditText editText = (EditText) body.findViewById(R.id.editText_task); 61 | Button button = (Button) body.findViewById(R.id.button_save); 62 | 63 | ArrayList strings = new ArrayList<>(); 64 | final ArrayAdapter arrayAdapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, strings); 65 | 66 | listView.setAdapter(arrayAdapter); 67 | 68 | // Get the instance of the Floaty 69 | floaty = Floaty.createInstance(this, head, body, NOTIFICATION_ID, notification, new FloatyOrientationListener() { 70 | @Override 71 | public void beforeOrientationChange(Floaty floaty) { 72 | Toast.makeText(MainActivity.this, "Orientation Change Start", Toast.LENGTH_SHORT).show(); 73 | } 74 | 75 | @Override 76 | public void afterOrientationChange(Floaty floaty) { 77 | Toast.makeText(MainActivity.this, "Orientation Change End", Toast.LENGTH_SHORT).show(); 78 | } 79 | }); 80 | 81 | 82 | // Set your domain specific logic to body's children 83 | button.setOnClickListener(new View.OnClickListener() { 84 | @Override 85 | public void onClick(View v) { 86 | String item = editText.getText().toString().trim(); 87 | if (!item.isEmpty()) { 88 | editText.setText(""); 89 | arrayAdapter.add(item); 90 | arrayAdapter.notifyDataSetChanged(); 91 | } 92 | } 93 | }); 94 | 95 | listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { 96 | @Override 97 | public boolean onItemLongClick(AdapterView parent, View view, int position, long id) { 98 | arrayAdapter.remove(arrayAdapter.getItem(position)); 99 | arrayAdapter.notifyDataSetChanged(); 100 | return false; 101 | } 102 | }); 103 | 104 | 105 | button_start.setOnClickListener(new View.OnClickListener() { 106 | @Override 107 | public void onClick(View v) { 108 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 109 | startFloatyForAboveAndroidL(); 110 | } else { 111 | floaty.startService(); 112 | } 113 | } 114 | }); 115 | 116 | button_stop.setOnClickListener(new View.OnClickListener() { 117 | @Override 118 | public void onClick(View v) { 119 | floaty.stopService(); 120 | } 121 | }); 122 | } 123 | 124 | 125 | @TargetApi(Build.VERSION_CODES.M) 126 | public void startFloatyForAboveAndroidL() { 127 | if (!Settings.canDrawOverlays(this)) { 128 | Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, 129 | Uri.parse("package:" + getPackageName())); 130 | startActivityForResult(intent, PERMISSION_REQUEST_CODE); 131 | } else { 132 | floaty.startService(); 133 | } 134 | } 135 | 136 | 137 | @TargetApi(Build.VERSION_CODES.M) 138 | @Override 139 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 140 | if (requestCode == PERMISSION_REQUEST_CODE) { 141 | if (Settings.canDrawOverlays(this)) { 142 | floaty.startService(); 143 | } else { 144 | Spanned message = Html.fromHtml("Please allow this permission, so Floaties could be drawn."); 145 | Toast.makeText(this, message, Toast.LENGTH_LONG).show(); 146 | } 147 | } 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /FloatiesDemo/app/src/main/res/drawable/float_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericbhatti/floaties/1012b302c87eec0614bb65d99b9d57251c08bad1/FloatiesDemo/app/src/main/res/drawable/float_icon.png -------------------------------------------------------------------------------- /FloatiesDemo/app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 |