mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-11-17 14:25:08 -05:00
Added AppMsg library to the librarys-folder
This commit is contained in:
parent
4839172f5b
commit
15757a2a32
36
libraries/Android-AppMsg/.gitignore
vendored
Normal file
36
libraries/Android-AppMsg/.gitignore
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
#Android generated
|
||||
bin
|
||||
gen
|
||||
|
||||
#Eclipse
|
||||
.project
|
||||
.classpath
|
||||
.settings
|
||||
|
||||
#IntelliJ IDEA
|
||||
.idea
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
out
|
||||
|
||||
#Maven
|
||||
target
|
||||
release.properties
|
||||
pom.xml.*
|
||||
|
||||
#Ant
|
||||
build.xml
|
||||
local.properties
|
||||
proguard.cfg
|
||||
proguard-project.txt
|
||||
|
||||
#Gradle
|
||||
.gradle
|
||||
build
|
||||
|
||||
#OSX
|
||||
.DS_Store
|
||||
|
||||
#Personal Files
|
||||
signing.properties
|
202
libraries/Android-AppMsg/LICENSE.txt
Normal file
202
libraries/Android-AppMsg/LICENSE.txt
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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.
|
117
libraries/Android-AppMsg/README.md
Normal file
117
libraries/Android-AppMsg/README.md
Normal file
@ -0,0 +1,117 @@
|
||||
Android AppMsg (Crouton) Library
|
||||
================================
|
||||
|
||||
Implementation of in-layout notifications. Based on [Toast](http://developer.android.com/reference/android/widget/Toast.html) notifications and article [The making of Prixing #4: in-layout notifications](http://android.cyrilmottier.com/?p=773) by [Cyril Mottier](http://www.cyrilmottier.com/).
|
||||
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
Toast is far from being perfect and I am not entirely satisfied with it.
|
||||
Toast can be un-accurate in some cases. Indeed, Toast has one major drawback: it completely breaks contexts.
|
||||
This issue can be reproduced effortless. Let’s say a user is currently in an app firing a Toast and wants to switch to another application using the dedicated “multitask” button.
|
||||
The Toast will remain on screen even if the brought-to-front application has nothing do to with the previously shown app as described on the following figure:
|
||||
![Example Image][1]
|
||||
|
||||
As you can easily notice, the problem with Toasts is they are persistent.
|
||||
Once a Toast has been fired, it is displayed on top of any screen and remains visible for the duration specified at its creation.
|
||||
|
||||
In order to bypass the Toast persistence problem and ensure information is displayed in the correct context, we decided to create a new notification system:
|
||||
Activity-bound notifications. This is what it looks like in the current version of Prixing:
|
||||
![Example Image][2]
|
||||
|
||||
Crouton overcomes the main issue of having a Toast being shown while the menu is open.
|
||||
It sticks to the current screen sliding with it and leaving the menu completely free of any information that would have not been related to it.
|
||||
|
||||
<b>Copyright (C) by Cyril Mottier</b>
|
||||
|
||||
Sample
|
||||
------
|
||||
|
||||
A sample application is available on Google Play:
|
||||
|
||||
<a href="http://play.google.com/store/apps/details?id=com.devspark.appmsg.sample">
|
||||
<img alt="Get it on Google Play"
|
||||
src="http://www.android.com/images/brand/get_it_on_play_logo_small.png" />
|
||||
</a>
|
||||
|
||||
![Example Image][3]
|
||||
|
||||
The source code is available in this repository.
|
||||
|
||||
Compatibility
|
||||
-------------
|
||||
|
||||
This library is compatible from API 4 (Android 1.6).
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
The sample project requires:
|
||||
|
||||
* The library project
|
||||
* [ActionBarSherlock](https://github.com/JakeWharton/ActionBarSherlock)
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Android AppMsg is presented as an [Android library project](http://developer.android.com/guide/developing/projects/projects-eclipse.html).
|
||||
You can include this project by [referencing it as a library project](http://developer.android.com/guide/developing/projects/projects-eclipse.html#ReferencingLibraryProject) in Eclipse or ant.
|
||||
|
||||
To display the item you need the following code:
|
||||
|
||||
* Show AppMsg:
|
||||
|
||||
``` java
|
||||
AppMsg.makeText(/*Activity*/, /*CharSequence*/, /*AppMsg.Style*/).show();
|
||||
```
|
||||
|
||||
Gradle
|
||||
------
|
||||
|
||||
Android-AppMsg Library is now pushed to Maven Central as a AAR, so you just need to add the following dependency to your build.gradle.
|
||||
|
||||
``` xml
|
||||
dependencies {
|
||||
compile 'com.github.johnkil.android-appmsg:appmsg:1.2.0'
|
||||
}
|
||||
```
|
||||
|
||||
Example Gradle project using Android-AppMsg:
|
||||
|
||||
* [Android-AppMsg-Gradle-Sample](https://github.com/johnkil/Android-AppMsg-Gradle-Sample)
|
||||
|
||||
|
||||
Contribution
|
||||
------------
|
||||
|
||||
Please fork [dev](https://github.com/johnkil/Android-AppMsg/tree/dev) repository and contribute back using [pull requests](https://github.com/johnkil/Android-AppMsg/pulls).
|
||||
|
||||
Contributors are recommended to follow the Android [Code Style Guidelines](http://source.android.com/source/code-style.html).
|
||||
|
||||
Any contributions, large or small, major features, bug fixes, additional language translations, unit/integration tests are welcomed and appreciated but will be thoroughly reviewed and discussed.
|
||||
|
||||
Developed By
|
||||
------------
|
||||
* Evgeny Shishkin - <johnkil78@gmail.com>
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
Copyright 2012 Evgeny Shishkin
|
||||
|
||||
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.
|
||||
|
||||
[1]: http://cyrilmottier.com/media/2012/07/the-making-of-prixing-4-activity-tied-notifications/toast_user_flow_fail.png
|
||||
[2]: http://cyrilmottier.com/media/2012/07/the-making-of-prixing-4-activity-tied-notifications/in_layout_notification.png
|
||||
[3]: http://i46.tinypic.com/21kywit.png
|
12
libraries/Android-AppMsg/library/AndroidManifest.xml
Normal file
12
libraries/Android-AppMsg/library/AndroidManifest.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.devspark.appmsg"
|
||||
android:versionCode="5"
|
||||
android:versionName="1.2.0">
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="4"
|
||||
android:targetSdkVersion="19"/>
|
||||
|
||||
<application/>
|
||||
|
||||
</manifest>
|
22
libraries/Android-AppMsg/library/build.gradle
Normal file
22
libraries/Android-AppMsg/library/build.gradle
Normal file
@ -0,0 +1,22 @@
|
||||
apply plugin: 'android-library'
|
||||
|
||||
android {
|
||||
compileSdkVersion 19
|
||||
buildToolsVersion '19.0.1'
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 4
|
||||
}
|
||||
sourceSets {
|
||||
main {
|
||||
manifest.srcFile 'AndroidManifest.xml'
|
||||
java.srcDirs = ['src']
|
||||
res.srcDirs = ['res']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (project.hasProperty('nexusUsername')) {
|
||||
// Used to push in maven
|
||||
apply from: '../maven_push.gradle'
|
||||
}
|
71
libraries/Android-AppMsg/library/pom.xml
Normal file
71
libraries/Android-AppMsg/library/pom.xml
Normal file
@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.devspark</groupId>
|
||||
<artifactId>appmsg</artifactId>
|
||||
<version>1.0.1</version>
|
||||
<packaging>apklib</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.google.android</groupId>
|
||||
<artifactId>android</artifactId>
|
||||
<version>4.1.1.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<sourceDirectory>src</sourceDirectory>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-pmd-plugin</artifactId>
|
||||
<version>2.7.1</version>
|
||||
<configuration>
|
||||
<linkXref>true</linkXref>
|
||||
<sourceEncoding>utf-8</sourceEncoding>
|
||||
<minimumTokens>100</minimumTokens>
|
||||
<targetJdk>1.6</targetJdk>
|
||||
<excludes>
|
||||
<exclude>**/*Bean.java</exclude>
|
||||
<exclude>**/generated/*.java</exclude>
|
||||
</excludes>
|
||||
<excludeRoots>
|
||||
<excludeRoot>target/generated-sources/stubs</excludeRoot>
|
||||
</excludeRoots>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>com.jayway.maven.plugins.android.generation2</groupId>
|
||||
<artifactId>android-maven-plugin</artifactId>
|
||||
<version>3.6.0</version>
|
||||
<configuration>
|
||||
<androidManifestFile>${project.basedir}/AndroidManifest.xml</androidManifestFile>
|
||||
<assetsDirectory>${project.basedir}/assets</assetsDirectory>
|
||||
<resourceDirectory>${project.basedir}/res</resourceDirectory>
|
||||
<nativeLibrariesDirectory>${project.basedir}/src/main/native</nativeLibrariesDirectory>
|
||||
<sdk>
|
||||
<platform>16</platform>
|
||||
</sdk>
|
||||
<undeployBeforeDeploy>true</undeployBeforeDeploy>
|
||||
</configuration>
|
||||
<extensions>true</extensions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>2.3.2</version>
|
||||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
15
libraries/Android-AppMsg/library/project.properties
Normal file
15
libraries/Android-AppMsg/library/project.properties
Normal file
@ -0,0 +1,15 @@
|
||||
# This file is automatically generated by Android Tools.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file must be checked in Version Control Systems.
|
||||
#
|
||||
# To customize properties used by the Ant build system edit
|
||||
# "ant.properties", and override values to adapt the script to your
|
||||
# project structure.
|
||||
#
|
||||
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
|
||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||
|
||||
# Project target.
|
||||
target=android-19
|
||||
android.library=true
|
20
libraries/Android-AppMsg/library/res/layout/app_msg.xml
Normal file
20
libraries/Android-AppMsg/library/res/layout/app_msg.xml
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:minHeight="48dp"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/message"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:padding="8dp"
|
||||
android:textColor="?android:textColorPrimaryInverse"
|
||||
android:textIsSelectable="false"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
8
libraries/Android-AppMsg/library/res/values/colors.xml
Normal file
8
libraries/Android-AppMsg/library/res/values/colors.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<color name="alert">#CC0000</color>
|
||||
<color name="confirm">#FF8800</color>
|
||||
<color name="info">#669900</color>
|
||||
|
||||
</resources>
|
@ -0,0 +1,587 @@
|
||||
/*
|
||||
* Copyright 2012 Evgeny Shishkin
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.devspark.appmsg;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewGroup.LayoutParams;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
/**
|
||||
* In-layout notifications. Based on {@link android.widget.Toast} notifications
|
||||
* and article by Cyril Mottier (http://android.cyrilmottier.com/?p=773).
|
||||
*
|
||||
* @author e.shishkin
|
||||
*/
|
||||
public class AppMsg {
|
||||
|
||||
/**
|
||||
* Show the view or text notification for a short period of time. This time
|
||||
* could be user-definable. This is the default.
|
||||
*
|
||||
* @see #setDuration
|
||||
*/
|
||||
public static final int LENGTH_SHORT = 3000;
|
||||
|
||||
/**
|
||||
* Show the view or text notification for a long period of time. This time
|
||||
* could be user-definable.
|
||||
*
|
||||
* @see #setDuration
|
||||
*/
|
||||
public static final int LENGTH_LONG = 5000;
|
||||
|
||||
/**
|
||||
* <p>Show the view or text notification for an undefined amount of time
|
||||
* -Usually until an invocation of {@link #cancel()}, {@link #cancelAll(android.app.Activity)},
|
||||
* {@link #cancelAll()} or {@link android.app.Activity#onDestroy()}-,
|
||||
* stacking on top of any other {@link com.devspark.appmsg.AppMsg} with this duration.</p>
|
||||
*
|
||||
* <p><b>Note</b>: You are responsible
|
||||
* for calling {@link #cancel()} on such {@link com.devspark.appmsg.AppMsg}.</p>
|
||||
*
|
||||
* @see #setDuration
|
||||
*/
|
||||
public static final int LENGTH_STICKY = -1;
|
||||
|
||||
/**
|
||||
* Lowest priority, messages with this priority will be showed after all messages with priority
|
||||
* {@link #PRIORITY_HIGH} and {@link #PRIORITY_NORMAL} have been shown.
|
||||
*
|
||||
* @see #setPriority(int)
|
||||
*/
|
||||
public static final int PRIORITY_LOW = Integer.MIN_VALUE;
|
||||
/**
|
||||
* Normal priority, messages with this priority will be showed after all messages with priority
|
||||
* {@link #PRIORITY_HIGH} but before {@link #PRIORITY_LOW} have been shown.
|
||||
*
|
||||
* @see #setPriority(int)
|
||||
*/
|
||||
public static final int PRIORITY_NORMAL = 0;
|
||||
/**
|
||||
* Highest priority, messages with this priority will be showed before any other message.
|
||||
*
|
||||
* @see #setPriority(int)
|
||||
*/
|
||||
public static final int PRIORITY_HIGH = Integer.MAX_VALUE;
|
||||
|
||||
/**
|
||||
* Show the text notification for a long period of time with a negative style.
|
||||
*/
|
||||
public static final Style STYLE_ALERT = new Style(LENGTH_LONG, R.color.alert);
|
||||
|
||||
/**
|
||||
* Show the text notification for a short period of time with a positive style.
|
||||
*/
|
||||
public static final Style STYLE_CONFIRM = new Style(LENGTH_SHORT, R.color.confirm);
|
||||
|
||||
/**
|
||||
* Show the text notification for a short period of time with a neutral style.
|
||||
*/
|
||||
public static final Style STYLE_INFO = new Style(LENGTH_SHORT, R.color.info);
|
||||
|
||||
private final Activity mActivity;
|
||||
private int mDuration = LENGTH_SHORT;
|
||||
private View mView;
|
||||
private ViewGroup mParent;
|
||||
private LayoutParams mLayoutParams;
|
||||
private boolean mFloating;
|
||||
Animation mInAnimation, mOutAnimation;
|
||||
int mPriority = PRIORITY_NORMAL;
|
||||
|
||||
/**
|
||||
* Construct an empty AppMsg object. You must call {@link #setView} before
|
||||
* you can call {@link #show}.
|
||||
*
|
||||
* @param activity {@link android.app.Activity} to use.
|
||||
*/
|
||||
public AppMsg(Activity activity) {
|
||||
mActivity = activity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a {@link AppMsg} that just contains a text view.
|
||||
*
|
||||
* @param context The context to use. Usually your
|
||||
* {@link android.app.Activity} object.
|
||||
* @param text The text to show. Can be formatted text.
|
||||
* @param style The style with a background and a duration.
|
||||
*/
|
||||
public static AppMsg makeText(Activity context, CharSequence text, Style style) {
|
||||
return makeText(context, text, style, R.layout.app_msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* @author mengguoqiang 扩展支持设置字体大小
|
||||
* Make a {@link AppMsg} that just contains a text view.
|
||||
*
|
||||
* @param context The context to use. Usually your
|
||||
* {@link android.app.Activity} object.
|
||||
* @param text The text to show. Can be formatted text.
|
||||
* @param style The style with a background and a duration.
|
||||
*/
|
||||
public static AppMsg makeText(Activity context, CharSequence text, Style style, float textSize) {
|
||||
return makeText(context, text, style, R.layout.app_msg, textSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a {@link AppMsg} with a custom layout. The layout must have a {@link TextView} com id {@link android.R.id.message}
|
||||
*
|
||||
* @param context The context to use. Usually your
|
||||
* {@link android.app.Activity} object.
|
||||
* @param text The text to show. Can be formatted text.
|
||||
* @param style The style with a background and a duration.
|
||||
*/
|
||||
public static AppMsg makeText(Activity context, CharSequence text, Style style, int layoutId) {
|
||||
LayoutInflater inflate = (LayoutInflater)
|
||||
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
View v = inflate.inflate(layoutId, null);
|
||||
|
||||
return makeText(context, text, style, v, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @author mengguoqiang 扩展支持字体大小
|
||||
* Make a {@link AppMsg} with a custom layout. The layout must have a {@link TextView} com id {@link android.R.id.message}
|
||||
*
|
||||
* @param context The context to use. Usually your
|
||||
* {@link android.app.Activity} object.
|
||||
* @param text The text to show. Can be formatted text.
|
||||
* @param style The style with a background and a duration.
|
||||
*/
|
||||
public static AppMsg makeText(Activity context, CharSequence text, Style style, int layoutId, float textSize) {
|
||||
LayoutInflater inflate = (LayoutInflater)
|
||||
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
View v = inflate.inflate(layoutId, null);
|
||||
|
||||
return makeText(context, text, style, v, true, textSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a non-floating {@link AppMsg} with a custom view presented inside the layout.
|
||||
* It can be used to create non-floating notifications if floating is false.
|
||||
*
|
||||
* @param context The context to use. Usually your
|
||||
* {@link android.app.Activity} object.
|
||||
* @param customView
|
||||
* View to be used.
|
||||
* @param text The text to show. Can be formatted text.
|
||||
* @param style The style with a background and a duration.
|
||||
*/
|
||||
public static AppMsg makeText(Activity context, CharSequence text, Style style, View customView) {
|
||||
return makeText(context, text, style, customView, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a {@link AppMsg} with a custom view. It can be used to create non-floating notifications if floating is false.
|
||||
*
|
||||
* @param context The context to use. Usually your
|
||||
* {@link android.app.Activity} object.
|
||||
* @param view
|
||||
* View to be used.
|
||||
* @param text The text to show. Can be formatted text.
|
||||
* @param style The style with a background and a duration.
|
||||
* @param floating true if it'll float.
|
||||
*/
|
||||
private static AppMsg makeText(Activity context, CharSequence text, Style style, View view, boolean floating) {
|
||||
return makeText(context, text, style, view, floating, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @author mengguoqiang 扩展支持设置字体大小
|
||||
* Make a {@link AppMsg} with a custom view. It can be used to create non-floating notifications if floating is false.
|
||||
*
|
||||
* @param context The context to use. Usually your
|
||||
* {@link android.app.Activity} object.
|
||||
* @param view
|
||||
* View to be used.
|
||||
* @param text The text to show. Can be formatted text.
|
||||
* @param style The style with a background and a duration.
|
||||
* @param floating true if it'll float.
|
||||
*/
|
||||
private static AppMsg makeText(Activity context, CharSequence text, Style style, View view, boolean floating, float textSize) {
|
||||
AppMsg result = new AppMsg(context);
|
||||
|
||||
view.setBackgroundResource(style.background);
|
||||
|
||||
TextView tv = (TextView) view.findViewById(android.R.id.message);
|
||||
if(textSize > 0) tv.setTextSize(textSize);
|
||||
tv.setText(text);
|
||||
|
||||
result.mView = view;
|
||||
result.mDuration = style.duration;
|
||||
result.mFloating = floating;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a {@link AppMsg} with a custom view. It can be used to create non-floating notifications if floating is false.
|
||||
*
|
||||
* @param context The context to use. Usually your
|
||||
* {@link android.app.Activity} object.
|
||||
* @param resId The resource id of the string resource to use. Can be
|
||||
* formatted text.
|
||||
* @param style The style with a background and a duration.
|
||||
* @param floating true if it'll float.
|
||||
*/
|
||||
public static AppMsg makeText(Activity context, int resId, Style style, View customView, boolean floating) {
|
||||
return makeText(context, context.getResources().getText(resId), style, customView, floating);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a {@link AppMsg} that just contains a text view with the text from a
|
||||
* resource.
|
||||
*
|
||||
* @param context The context to use. Usually your
|
||||
* {@link android.app.Activity} object.
|
||||
* @param resId The resource id of the string resource to use. Can be
|
||||
* formatted text.
|
||||
* @param style The style with a background and a duration.
|
||||
* @throws Resources.NotFoundException if the resource can't be found.
|
||||
*/
|
||||
public static AppMsg makeText(Activity context, int resId, Style style)
|
||||
throws Resources.NotFoundException {
|
||||
return makeText(context, context.getResources().getText(resId), style);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a {@link AppMsg} with a custom layout using the text from a
|
||||
* resource. The layout must have a {@link TextView} com id {@link android.R.id.message}
|
||||
*
|
||||
* @param context The context to use. Usually your
|
||||
* {@link android.app.Activity} object.
|
||||
* @param resId The resource id of the string resource to use. Can be
|
||||
* formatted text.
|
||||
* @param style The style with a background and a duration.
|
||||
* @throws Resources.NotFoundException if the resource can't be found.
|
||||
*/
|
||||
public static AppMsg makeText(Activity context, int resId, Style style, int layoutId)
|
||||
throws Resources.NotFoundException {
|
||||
return makeText(context, context.getResources().getText(resId), style, layoutId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the view for the specified duration.
|
||||
*/
|
||||
public void show() {
|
||||
MsgManager manager = MsgManager.obtain(mActivity);
|
||||
manager.add(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if the {@link AppMsg} is being displayed, else <code>false</code>.
|
||||
*/
|
||||
public boolean isShowing() {
|
||||
if (mFloating) {
|
||||
return mView != null && mView.getParent() != null;
|
||||
} else {
|
||||
return mView.getVisibility() == View.VISIBLE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the view if it's showing, or don't show it if it isn't showing yet.
|
||||
* You do not normally have to call this. Normally view will disappear on its own
|
||||
* after the appropriate duration.
|
||||
*/
|
||||
public void cancel() {
|
||||
MsgManager.obtain(mActivity).clearMsg(this);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels all queued {@link AppMsg}s, in all Activities. If there is a {@link AppMsg}
|
||||
* displayed currently, it will be the last one displayed.
|
||||
*/
|
||||
public static void cancelAll() {
|
||||
MsgManager.clearAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels all queued {@link AppMsg}s, in given {@link android.app.Activity}.
|
||||
* If there is a {@link AppMsg} displayed currently, it will be the last one displayed.
|
||||
* @param activity
|
||||
*/
|
||||
public static void cancelAll(Activity activity) {
|
||||
MsgManager.release(activity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the activity.
|
||||
*/
|
||||
public Activity getActivity() {
|
||||
return mActivity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the view to show.
|
||||
*
|
||||
* @see #getView
|
||||
*/
|
||||
public void setView(View view) {
|
||||
mView = view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the view.
|
||||
*
|
||||
* @see #setView
|
||||
*/
|
||||
public View getView() {
|
||||
return mView;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set how long to show the view for.
|
||||
*
|
||||
* @see #LENGTH_SHORT
|
||||
* @see #LENGTH_LONG
|
||||
*/
|
||||
public void setDuration(int duration) {
|
||||
mDuration = duration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the duration.
|
||||
*
|
||||
* @see #setDuration
|
||||
*/
|
||||
public int getDuration() {
|
||||
return mDuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the text in a AppMsg that was previously created using one of the makeText() methods.
|
||||
*
|
||||
* @param resId The new text for the AppMsg.
|
||||
*/
|
||||
public void setText(int resId) {
|
||||
setText(mActivity.getText(resId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the text in a AppMsg that was previously created using one of the makeText() methods.
|
||||
*
|
||||
* @param s The new text for the AppMsg.
|
||||
*/
|
||||
public void setText(CharSequence s) {
|
||||
if (mView == null) {
|
||||
throw new RuntimeException("This AppMsg was not created with AppMsg.makeText()");
|
||||
}
|
||||
TextView tv = (TextView) mView.findViewById(android.R.id.message);
|
||||
if (tv == null) {
|
||||
throw new RuntimeException("This AppMsg was not created with AppMsg.makeText()");
|
||||
}
|
||||
tv.setText(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the crouton's layout parameters, constructing a default if necessary.
|
||||
*
|
||||
* @return the layout parameters
|
||||
*/
|
||||
public LayoutParams getLayoutParams() {
|
||||
if (mLayoutParams == null) {
|
||||
mLayoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
|
||||
}
|
||||
return mLayoutParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the layout parameters which will be used to display the crouton.
|
||||
*
|
||||
* @param layoutParams The layout parameters to use.
|
||||
* @return <code>this</code>, for chaining.
|
||||
*/
|
||||
public AppMsg setLayoutParams(LayoutParams layoutParams) {
|
||||
mLayoutParams = layoutParams;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and sets the layout parameters to have some gravity.
|
||||
*
|
||||
* @param gravity the gravity of the Crouton
|
||||
* @return <code>this</code>, for chaining.
|
||||
* @see android.view.Gravity
|
||||
*/
|
||||
public AppMsg setLayoutGravity(int gravity) {
|
||||
mLayoutParams = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, gravity);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the value of floating.
|
||||
*
|
||||
* @see #setFloating(boolean)
|
||||
*/
|
||||
public boolean isFloating() {
|
||||
return mFloating;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of floating.
|
||||
*
|
||||
* @param mFloating
|
||||
*/
|
||||
public void setFloating(boolean mFloating) {
|
||||
this.mFloating = mFloating;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Animations to be used when displaying/removing the Crouton.
|
||||
* @param inAnimation the Animation resource ID to be used when displaying.
|
||||
* @param outAnimation the Animation resource ID to be used when removing.
|
||||
*/
|
||||
public AppMsg setAnimation(int inAnimation, int outAnimation) {
|
||||
return setAnimation(AnimationUtils.loadAnimation(mActivity, inAnimation),
|
||||
AnimationUtils.loadAnimation(mActivity, outAnimation));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Animations to be used when displaying/removing the Crouton.
|
||||
* @param inAnimation the Animation to be used when displaying.
|
||||
* @param outAnimation the Animation to be used when removing.
|
||||
*/
|
||||
public AppMsg setAnimation(Animation inAnimation, Animation outAnimation) {
|
||||
mInAnimation = inAnimation;
|
||||
mOutAnimation = outAnimation;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
* Current priority
|
||||
*
|
||||
* @see #PRIORITY_HIGH
|
||||
* @see #PRIORITY_NORMAL
|
||||
* @see #PRIORITY_LOW
|
||||
*/
|
||||
public int getPriority() {
|
||||
return mPriority;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Set priority for this message</p>
|
||||
* <p><b>Note</b>: This only affects the order in which the messages get shown,
|
||||
* not the stacking order of the views.</p>
|
||||
*
|
||||
* <p>Example: In the queue there are 3 messages [A, B, C],
|
||||
* all of them with priority {@link #PRIORITY_NORMAL}, currently message A is being shown
|
||||
* so we add a new message D with priority {@link #PRIORITY_HIGH}, after A goes away, given that
|
||||
* D has a higher priority than B an the reset, D will be shown, then once that D is gone,
|
||||
* B will be shown, and then finally C.</p>
|
||||
*
|
||||
* @param priority
|
||||
* A value indicating priority, although you can use any integer value, usage of already
|
||||
* defined is highly encouraged.
|
||||
*
|
||||
* @see #PRIORITY_HIGH
|
||||
* @see #PRIORITY_NORMAL
|
||||
* @see #PRIORITY_LOW
|
||||
*/
|
||||
public void setPriority(int priority) {
|
||||
mPriority = priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
* Provided parent to add {@link #getView()} to using {@link #getLayoutParams()}.
|
||||
*/
|
||||
public ViewGroup getParent() {
|
||||
return mParent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a different parent than Activity decor view
|
||||
* @param parent
|
||||
* Provided parent to add {@link #getView()} to using {@link #getLayoutParams()}.
|
||||
*
|
||||
*/
|
||||
public void setParent(ViewGroup parent) {
|
||||
mParent = parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a different parent than Activity decor view
|
||||
*
|
||||
* @param parentId
|
||||
* Provided parent id to add {@link #getView()} to using {@link #getLayoutParams()}.
|
||||
*
|
||||
*/
|
||||
public void setParent(int parentId) {
|
||||
setParent((ViewGroup) mActivity.findViewById(parentId));
|
||||
}
|
||||
|
||||
/**
|
||||
* The style for a {@link AppMsg}.
|
||||
*
|
||||
* @author e.shishkin
|
||||
*/
|
||||
public static class Style {
|
||||
|
||||
private final int duration;
|
||||
private final int background;
|
||||
|
||||
/**
|
||||
* Construct an {@link AppMsg.Style} object.
|
||||
*
|
||||
* @param duration How long to display the message. Either
|
||||
* {@link #LENGTH_SHORT} or {@link #LENGTH_LONG}
|
||||
* @param resId resource for AppMsg background
|
||||
*/
|
||||
public Style(int duration, int resId) {
|
||||
this.duration = duration;
|
||||
this.background = resId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the duration in milliseconds.
|
||||
*/
|
||||
public int getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the resource id of background.
|
||||
*/
|
||||
public int getBackground() {
|
||||
return background;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof AppMsg.Style)) {
|
||||
return false;
|
||||
}
|
||||
Style style = (Style) o;
|
||||
return style.duration == duration
|
||||
&& style.background == background;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,340 @@
|
||||
/*
|
||||
* Copyright 2012 Evgeny Shishkin
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.devspark.appmsg;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.AnimationUtils;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.PriorityQueue;
|
||||
import java.util.Queue;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import static android.app.Application.ActivityLifecycleCallbacks;
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
import static android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH;
|
||||
import static com.devspark.appmsg.AppMsg.LENGTH_STICKY;
|
||||
|
||||
/**
|
||||
* @author Evgeny Shishkin
|
||||
*/
|
||||
class MsgManager extends Handler implements Comparator<AppMsg> {
|
||||
|
||||
private static final int MESSAGE_DISPLAY = 0xc2007;
|
||||
private static final int MESSAGE_ADD_VIEW = 0xc20074dd;
|
||||
private static final int MESSAGE_REMOVE = 0xc2007de1;
|
||||
|
||||
private static WeakHashMap<Activity, MsgManager> sManagers;
|
||||
private static ReleaseCallbacks sReleaseCallbacks;
|
||||
|
||||
private final Queue<AppMsg> msgQueue;
|
||||
private final Queue<AppMsg> stickyQueue;
|
||||
|
||||
private MsgManager() {
|
||||
msgQueue = new PriorityQueue<AppMsg>(1, this);
|
||||
stickyQueue = new LinkedList<AppMsg>();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A {@link MsgManager} instance to be used for given {@link android.app.Activity}.
|
||||
*/
|
||||
static synchronized MsgManager obtain(Activity activity) {
|
||||
if (sManagers == null) {
|
||||
sManagers = new WeakHashMap<Activity, MsgManager>(1);
|
||||
}
|
||||
MsgManager manager = sManagers.get(activity);
|
||||
if (manager == null) {
|
||||
manager = new MsgManager();
|
||||
ensureReleaseOnDestroy(activity);
|
||||
sManagers.put(activity, manager);
|
||||
}
|
||||
|
||||
return manager;
|
||||
}
|
||||
|
||||
static void ensureReleaseOnDestroy(Activity activity) {
|
||||
if (SDK_INT < ICE_CREAM_SANDWICH) {
|
||||
return;
|
||||
}
|
||||
if (sReleaseCallbacks == null) {
|
||||
sReleaseCallbacks = new ReleaseCallbacksIcs();
|
||||
}
|
||||
sReleaseCallbacks.register(activity.getApplication());
|
||||
}
|
||||
|
||||
|
||||
static synchronized void release(Activity activity) {
|
||||
if (sManagers != null) {
|
||||
final MsgManager manager = sManagers.remove(activity);
|
||||
if (manager != null) {
|
||||
manager.clearAllMsg();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static synchronized void clearAll() {
|
||||
if (sManagers != null) {
|
||||
final Iterator<MsgManager> iterator = sManagers.values().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
final MsgManager manager = iterator.next();
|
||||
if (manager != null) {
|
||||
manager.clearAllMsg();
|
||||
}
|
||||
iterator.remove();
|
||||
}
|
||||
sManagers.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a {@link AppMsg} to be displayed.
|
||||
*
|
||||
* @param appMsg
|
||||
*/
|
||||
void add(AppMsg appMsg) {
|
||||
msgQueue.add(appMsg);
|
||||
if (appMsg.mInAnimation == null) {
|
||||
appMsg.mInAnimation = AnimationUtils.loadAnimation(appMsg.getActivity(),
|
||||
android.R.anim.fade_in);
|
||||
}
|
||||
if (appMsg.mOutAnimation == null) {
|
||||
appMsg.mOutAnimation = AnimationUtils.loadAnimation(appMsg.getActivity(),
|
||||
android.R.anim.fade_out);
|
||||
}
|
||||
displayMsg();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all {@link AppMsg} from the queue.
|
||||
*/
|
||||
void clearMsg(AppMsg appMsg) {
|
||||
if(msgQueue.contains(appMsg) || stickyQueue.contains(appMsg)){
|
||||
// Avoid the message from being removed twice.
|
||||
removeMessages(MESSAGE_DISPLAY, appMsg);
|
||||
removeMessages(MESSAGE_ADD_VIEW, appMsg);
|
||||
removeMessages(MESSAGE_REMOVE, appMsg);
|
||||
msgQueue.remove(appMsg);
|
||||
stickyQueue.remove(appMsg);
|
||||
removeMsg(appMsg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all {@link AppMsg} from the queue.
|
||||
*/
|
||||
void clearAllMsg() {
|
||||
removeMessages(MESSAGE_DISPLAY);
|
||||
removeMessages(MESSAGE_ADD_VIEW);
|
||||
removeMessages(MESSAGE_REMOVE);
|
||||
clearShowing();
|
||||
msgQueue.clear();
|
||||
stickyQueue.clear();
|
||||
}
|
||||
|
||||
void clearShowing() {
|
||||
final Collection<AppMsg> showing = new HashSet<AppMsg>();
|
||||
obtainShowing(msgQueue, showing);
|
||||
obtainShowing(stickyQueue, showing);
|
||||
for (AppMsg msg : showing) {
|
||||
clearMsg(msg);
|
||||
}
|
||||
}
|
||||
|
||||
static void obtainShowing(Collection<AppMsg> from, Collection<AppMsg> appendTo) {
|
||||
for (AppMsg msg : from) {
|
||||
if (msg.isShowing()) {
|
||||
appendTo.add(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the next {@link AppMsg} within the queue.
|
||||
*/
|
||||
private void displayMsg() {
|
||||
if (msgQueue.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
// First peek whether the AppMsg is being displayed.
|
||||
final AppMsg appMsg = msgQueue.peek();
|
||||
final Message msg;
|
||||
if (!appMsg.isShowing()) {
|
||||
// Display the AppMsg
|
||||
msg = obtainMessage(MESSAGE_ADD_VIEW);
|
||||
msg.obj = appMsg;
|
||||
sendMessage(msg);
|
||||
} else if (appMsg.getDuration() != LENGTH_STICKY) {
|
||||
msg = obtainMessage(MESSAGE_DISPLAY);
|
||||
sendMessageDelayed(msg, appMsg.getDuration()
|
||||
+ appMsg.mInAnimation.getDuration() + appMsg.mOutAnimation.getDuration());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the {@link AppMsg}'s view after it's display duration.
|
||||
*
|
||||
* @param appMsg The {@link AppMsg} added to a {@link ViewGroup} and should be removed.s
|
||||
*/
|
||||
private void removeMsg(final AppMsg appMsg) {
|
||||
clearMsg(appMsg);
|
||||
final View view = appMsg.getView();
|
||||
ViewGroup parent = ((ViewGroup) view.getParent());
|
||||
if (parent != null) {
|
||||
appMsg.mOutAnimation.setAnimationListener(new OutAnimationListener(appMsg));
|
||||
view.clearAnimation();
|
||||
view.startAnimation(appMsg.mOutAnimation);
|
||||
}
|
||||
|
||||
Message msg = obtainMessage(MESSAGE_DISPLAY);
|
||||
sendMessage(msg);
|
||||
}
|
||||
|
||||
private void addMsgToView(AppMsg appMsg) {
|
||||
View view = appMsg.getView();
|
||||
if (view.getParent() == null) { // Not added yet
|
||||
final ViewGroup targetParent = appMsg.getParent();
|
||||
final ViewGroup.LayoutParams params = appMsg.getLayoutParams();
|
||||
if (targetParent != null) {
|
||||
targetParent.addView(view, params);
|
||||
} else {
|
||||
appMsg.getActivity().addContentView(view, params);
|
||||
}
|
||||
}
|
||||
view.clearAnimation();
|
||||
view.startAnimation(appMsg.mInAnimation);
|
||||
if (view.getVisibility() != View.VISIBLE) {
|
||||
view.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
final int duration = appMsg.getDuration();
|
||||
if (duration != LENGTH_STICKY) {
|
||||
final Message msg = obtainMessage(MESSAGE_REMOVE);
|
||||
msg.obj = appMsg;
|
||||
sendMessageDelayed(msg, duration);
|
||||
} else { // We are sticky, we don't get removed just yet
|
||||
stickyQueue.add(msgQueue.poll());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
final AppMsg appMsg;
|
||||
switch (msg.what) {
|
||||
case MESSAGE_DISPLAY:
|
||||
displayMsg();
|
||||
break;
|
||||
case MESSAGE_ADD_VIEW:
|
||||
appMsg = (AppMsg) msg.obj;
|
||||
addMsgToView(appMsg);
|
||||
break;
|
||||
case MESSAGE_REMOVE:
|
||||
appMsg = (AppMsg) msg.obj;
|
||||
removeMsg(appMsg);
|
||||
break;
|
||||
default:
|
||||
super.handleMessage(msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(AppMsg lhs, AppMsg rhs) {
|
||||
return inverseCompareInt(lhs.mPriority, rhs.mPriority);
|
||||
}
|
||||
|
||||
static int inverseCompareInt(int lhs, int rhs) {
|
||||
return lhs < rhs ? 1 : (lhs == rhs ? 0 : -1);
|
||||
}
|
||||
|
||||
private static class OutAnimationListener implements Animation.AnimationListener {
|
||||
|
||||
private final AppMsg appMsg;
|
||||
|
||||
private OutAnimationListener(AppMsg appMsg) {
|
||||
this.appMsg = appMsg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationStart(Animation animation) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animation animation) {
|
||||
final View view = appMsg.getView();
|
||||
if (appMsg.isFloating()) {
|
||||
final ViewGroup parent = ((ViewGroup) view.getParent());
|
||||
if (parent != null) {
|
||||
parent.post(new Runnable() { // One does not simply removeView
|
||||
@Override
|
||||
public void run() {
|
||||
parent.removeView(view);
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
view.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationRepeat(Animation animation) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
interface ReleaseCallbacks {
|
||||
void register(Application application);
|
||||
}
|
||||
|
||||
@TargetApi(ICE_CREAM_SANDWICH)
|
||||
static class ReleaseCallbacksIcs implements ActivityLifecycleCallbacks, ReleaseCallbacks {
|
||||
private WeakReference<Application> mLastApp;
|
||||
public void register(Application app) {
|
||||
if (mLastApp != null && mLastApp.get() == app) {
|
||||
return; // Already registered with this app
|
||||
} else {
|
||||
mLastApp = new WeakReference<Application>(app);
|
||||
}
|
||||
app.registerActivityLifecycleCallbacks(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityDestroyed(Activity activity) {
|
||||
release(activity);
|
||||
}
|
||||
@Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) {}
|
||||
@Override public void onActivityStarted(Activity activity) {}
|
||||
@Override public void onActivityResumed(Activity activity) {}
|
||||
@Override public void onActivityPaused(Activity activity) {}
|
||||
@Override public void onActivityStopped(Activity activity) {}
|
||||
@Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user