├── .gitignore
├── CHANGELOG.md
├── README-en.md
├── README.md
├── annotation
├── build.gradle
└── src
│ └── main
│ └── java
│ └── cn
│ └── bingoogolapple
│ └── badgeview
│ └── annotation
│ └── BGABadge.java
├── api
├── build.gradle
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── cn
│ │ └── bingoogolapple
│ │ └── badgeview
│ │ ├── BGABadgeViewHelper.java
│ │ ├── BGABadgeViewUtil.java
│ │ ├── BGABadgeable.java
│ │ ├── BGADragBadgeView.java
│ │ ├── BGADragDismissDelegate.java
│ │ └── BGAExplosionAnimator.java
│ └── res
│ └── values
│ └── attrs.xml
├── build.gradle
├── compiler
├── build.gradle
└── src
│ └── main
│ └── java
│ └── cn
│ └── bingoogolapple
│ └── badgeview
│ └── compiler
│ └── BGABadgeProcessor.java
├── demo
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── cn
│ │ └── bingoogolapple
│ │ └── badgeview
│ │ └── demo
│ │ ├── activity
│ │ └── MainActivity.java
│ │ ├── adapter
│ │ └── MessageAdapter.java
│ │ ├── model
│ │ └── MessageModel.java
│ │ └── util
│ │ ├── BGABadgeInit.java
│ │ └── ToastUtil.java
│ └── res
│ ├── color
│ └── selector_maintab.xml
│ ├── drawable
│ ├── layer_maintab_bg.xml
│ ├── selector_item.xml
│ ├── selector_tab_discover.xml
│ ├── selector_tab_home.xml
│ ├── selector_tab_me.xml
│ ├── selector_tab_message.xml
│ ├── selector_tab_plus.xml
│ ├── selector_tab_plusbg.xml
│ └── shape_toast.xml
│ ├── layout
│ ├── activity_main.xml
│ ├── item_message.xml
│ └── view_toast.xml
│ ├── mipmap-hdpi
│ ├── avatar_vip.png
│ ├── avator.png
│ ├── chat_white.png
│ ├── ic_launcher.png
│ ├── tab_discover_checked.png
│ ├── tab_discover_normal.png
│ ├── tab_home_checked.png
│ ├── tab_home_normal.png
│ ├── tab_me_checked.png
│ ├── tab_me_normal.png
│ ├── tab_message_checked.png
│ ├── tab_message_normal.png
│ ├── tab_plus_normal.png
│ └── tab_plus_pressed.png
│ ├── mipmap-mdpi
│ └── ic_launcher.png
│ ├── mipmap-xhdpi
│ ├── ic_launcher.png
│ └── toast.png
│ ├── mipmap-xxhdpi
│ └── ic_launcher.png
│ └── values
│ ├── colors.xml
│ ├── dimens.xml
│ ├── strings.xml
│ ├── styles.xml
│ └── styles_common.xml
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.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 | config.json
23 |
24 | # Proguard folder generated by Eclipse
25 | proguard/
26 |
27 | # Log Files
28 | *.log
29 |
30 | # Eclipse project files
31 | .classpath
32 | .project
33 | .settings/
34 |
35 | # Intellij project files
36 | *.iml
37 | *.ipr
38 | *.iws
39 | .idea/
40 |
41 | # Mac system files
42 | .DS_Store
43 |
44 | *.keystore
45 |
46 | repo/
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | Change Log
2 | ==========
3 |
4 | Version 1.1.9、1.2.0 *(2021-04-05)*
5 | ----------------------------
6 |
7 | - 从 JCenter 迁移到 JitPack
8 |
9 | Version 1.1.8 *(2018-04-09)*
10 | ----------------------------
11 |
12 | - fix #49
13 | - badge_dragable 变为 badge_draggable
14 | - BadgeViewHelper 的 setDragable 方法变为 setDraggable
15 |
16 | Version 1.1.7 *(2018-01-24)*
17 | ----------------------------
18 |
19 | - 优化 BGABadge 注解参数为 Class
20 | ```Java
21 | /**
22 | * 作者:王浩 邮件:bingoogolapple@gmail.com
23 | * 创建时间:2018/1/14
24 | * 描述:初始化 BGABadgeView-Android
25 | * 1.在项目任意一个类上面添加 BGABadge 注解
26 | * 2.需要哪些类具有徽章功能,就把那些类的 class 作为 BGABadge 注解的参数
27 | * 3.再 AS 中执行 Build => Rebuild Project
28 | * 4.经过前面三个步骤后就可以通过「cn.bingoogolapple.badgeview.BGABadge原始类名」来使用徽章控件了
29 | */
30 | @BGABadge({
31 | View.class, // 对应 cn.bingoogolapple.badgeview.BGABadgeView,不想用这个类的话就删了这一行
32 | ImageView.class, // 对应 cn.bingoogolapple.badgeview.BGABadgeImageView,不想用这个类的话就删了这一行
33 | TextView.class, // 对应 cn.bingoogolapple.badgeview.BGABadgeFloatingTextView,不想用这个类的话就删了这一行
34 | RadioButton.class, // 对应 cn.bingoogolapple.badgeview.BGABadgeRadioButton,不想用这个类的话就删了这一行
35 | LinearLayout.class, // 对应 cn.bingoogolapple.badgeview.BGABadgeLinearLayout,不想用这个类的话就删了这一行
36 | FrameLayout.class, // 对应 cn.bingoogolapple.badgeview.BGABadgeFrameLayout,不想用这个类的话就删了这一行
37 | RelativeLayout.class, // 对应 cn.bingoogolapple.badgeview.BGABadgeRelativeLayout,不想用这个类的话就删了这一行
38 | FloatingActionButton.class, // 对应 cn.bingoogolapple.badgeview.BGABadgeFloatingActionButton,不想用这个类的话就删了这一行
39 | })
40 | ```
41 |
42 | Version 1.1.6 *(2018-01-19)*
43 | ----------------------------
44 |
45 | - 优化 apt 生成的代码
46 |
47 | Version 1.1.5 *(2018-01-16)*
48 | ----------------------------
49 |
50 | - 移除 Library 中的 BGABadgeXxxxView,改为 annotationProcessor 的形式
51 |
52 | [  ](https://bintray.com/bingoogolapple/maven/bga-badgeview-api/_latestVersion) bga-badgeview-api 后面的「latestVersion」指的是左边这个 Download 徽章后面的「数字」,请自行替换。
53 |
54 | ```groovy
55 | dependencies {
56 | implementation 'cn.bingoogolapple:bga-badgeview-api:latestVersion'
57 | annotationProcessor "cn.bingoogolapple:bga-badgeview-compiler:latestVersion"
58 | }
59 | ```
60 |
61 | ```Java
62 | /**
63 | * 作者:王浩 邮件:bingoogolapple@gmail.com
64 | * 创建时间:2018/1/14
65 | * 描述:初始化 BGABadgeView-Android
66 | * 1.在项目任意一个类上面添加 BGABadge 注解
67 | * 2.需要哪些类具有徽章功能,就把那些类的全限定名作为 BGABadge 注解的参数
68 | * 3.再 AS 中执行 Build => Rebuild Project
69 | * 4.经过前面三个步骤后就可以通过「cn.bingoogolapple.badgeview.BGABadge原始类名」来使用徽章控件了
70 | */
71 | @BGABadge({
72 | "android.view.View", // 对应 cn.bingoogolapple.badgeview.BGABadgeView
73 | "android.widget.ImageView", // 对应 cn.bingoogolapple.badgeview.BGABadgeImageView
74 | "android.widget.TextView", // 对应 cn.bingoogolapple.badgeview.BGABadgeFloatingTextView
75 | "android.widget.RadioButton", // 对应 cn.bingoogolapple.badgeview.BGABadgeRadioButton
76 | "android.widget.LinearLayout", // 对应 cn.bingoogolapple.badgeview.BGABadgeLinearLayout
77 | "android.widget.FrameLayout", // 对应 cn.bingoogolapple.badgeview.BGABadgeFrameLayout
78 | "android.widget.RelativeLayout", // 对应 cn.bingoogolapple.badgeview.BGABadgeRelativeLayout
79 | "android.support.design.widget.FloatingActionButton", // 对应 cn.bingoogolapple.badgeview.BGABadgeFloatingActionButton
80 | })
81 | public class BGABadgeInit {
82 | }
83 | ```
84 |
85 | Version 1.1.4 *(2018-01-14)*
86 | ----------------------------
87 |
88 | - 修改拖拽效果 Window 类型 TYPE_APPLICATION_PANEL
89 |
90 | Version 1.1.3 *(2016-07-22)*
91 | ----------------------------
92 |
93 | - 取消对 nineoldandroids 的依赖,minSdkVersion 从 9 改到 14。如果你想兼容到 API 14 以下,请使用 v1.1.2
94 |
95 | Version 1.1.2 *(2016-06-03)*
96 | ----------------------------
97 |
98 | - 增加「badge_dragExtra」触发开始拖拽徽章事件的扩展触摸距离
99 |
100 | Version 1.1.1 *(2016-03-29)*
101 | ----------------------------
102 |
103 | - 增加徽章描边,badge_borderWidth 徽章描边宽度,badge_borderColor 徽章描边颜色
104 | - 修改 badge_is_resume_travel 为 badge_isResumeTravel 拖拽徽章超出轨迹范围后,再次放回到轨迹范围时,是否恢复轨迹
105 |
106 | Version 1.1.0 *(2016-03-21)*
107 | ----------------------------
108 |
109 | - fix #14
110 |
111 | Version 1.0.9 *(2016-03-14)*
112 | ----------------------------
113 |
114 | - 增加getBadgeViewHelper方法,通过Java代码方式配置自定义属性,以便后期支持React Native
115 |
116 | Version 1.0.8 *(2016-03-04)*
117 | ----------------------------
118 |
119 | - 解决某些手机获取不到状态栏导致绘制高度偏移问题 fix #5
120 | - 增加自定义属性badge_is_resume_travel: 拖拽徽章超出轨迹范围后,再次放回到轨迹范围时,是否恢复轨迹 fix #5
121 | - 取消在NavigationBar区域的拖拽
122 |
123 | Version 1.0.7 *(2016-03-03)*
124 | ----------------------------
125 |
126 | - 添加isShowBadge方法获取徽章的显示状态 fix #6
127 |
128 | Version 1.0.6 *(2015-12-06)*
129 | ----------------------------
130 |
131 | - 添加拖拽黏性效果
132 |
133 | Version 1.0.5 *(2015-12-05)*
134 | ----------------------------
135 |
136 | - 优化拖拽删除时的爆照效果
137 |
138 | Version 1.0.4 *(2015-12-05)*
139 | ----------------------------
140 |
141 | - 添加拖拽删除时的爆照效果
142 |
143 | Version 1.0.3 *(2015-12-04)*
144 | ----------------------------
145 |
146 | - 处理RadioButton不能监听点击事件
147 | - 移除BGABadgeCheckedTextView
148 | - 移除AppCompat里相关控件
149 | - 解决6.0系统拖拽拖拽徽章的权限问题
150 |
151 | Version 1.0.2 *(2015-7-16)*
152 | ----------------------------
153 |
154 | - 解决圆形徽章显示全问题
155 |
156 | Version 1.0.1 *(2015-7-12)*
157 | ----------------------------
158 |
159 | - 增加拖拽删除功能
160 | - 将showCriclePointBadge改为showCirclePointBadge
161 |
162 | Version 1.0.0 *(2015-7-7)*
163 | ----------------------------
164 |
165 | Initial release.
--------------------------------------------------------------------------------
/README-en.md:
--------------------------------------------------------------------------------
1 | :heartpulse:BGABadgeView-Android:heartpulse:
2 | ============
3 |
4 | [](http://android-arsenal.com/details/1/2106)
5 | [](https://www.apache.org/licenses/LICENSE-2.0)
6 | [](https://jitpack.io/#bingoogolapple/BGABadgeView-Android)
7 |
8 | ### [中文文档](https://github.com/bingoogolapple/BGABadgeView-Android/blob/master/README.md)
9 |
10 | ### [react-native-bga-badge-view](https://github.com/bingoogolapple/react-native-bga-badge-view)
11 |
12 | **The demo shows:**
13 | * The latest message number of weibo at the bottom tab
14 | * The VIP badge located in lower-right Corner of User’s Photo in the weibo user list
15 | * The new message in the weixin message page
16 | * The subscribe message in the weixin message page
17 | * User’s round corner photo made by RoundedBitmapDrawable from v4 package
18 | * Delete badge by drag and drop
19 |
20 | ### The realization of explosion effect refers to [ExplosionField](https://github.com/tyrantgit/ExplosionField) with the modify of only retaining one View,and only refresh the field around of badge
21 |
22 | ### Screenshots
23 | 
24 |
25 | ### Gradle Dependencies
26 |
27 | [](https://jitpack.io/#bingoogolapple/BGABadgeView-Android)
28 |
29 | ```groovy
30 | dependencies {
31 | implementation 'com.github.bingoogolapple.BGABadgeView-Android:api:latestVersion'
32 | annotationProcessor 'com.github.bingoogolapple.BGABadgeView-Android:compiler:latestVersion'
33 | }
34 | ```
35 |
36 | ### Initialize BGABadge
37 |
38 | Add BGABadge annotation to any class, such as newly created class BGABadgeInit
39 |
40 | ```Java
41 | @BGABadge({
42 | View.class, // ===> cn.bingoogolapple.badgeview.BGABadgeView,If you do not need, please delete this line
43 | ImageView.class, // ===> cn.bingoogolapple.badgeview.BGABadgeImageView,If you do not need, please delete this line
44 | TextView.class, // ===> cn.bingoogolapple.badgeview.BGABadgeFloatingTextView,If you do not need, please delete this line
45 | RadioButton.class, // ===> cn.bingoogolapple.badgeview.BGABadgeRadioButton,If you do not need, please delete this line
46 | LinearLayout.class, // ===> cn.bingoogolapple.badgeview.BGABadgeLinearLayout,If you do not need, please delete this line
47 | RelativeLayout.class, // ===> cn.bingoogolapple.badgeview.BGABadgeRelativeLayout,If you do not need, please delete this line
48 | FloatingActionButton.class, // ===> cn.bingoogolapple.badgeview.BGABadgeFloatingActionButton,If you do not need, please delete this line
49 | ...
50 | ...
51 | ...
52 | })
53 | public class BGABadgeInit {
54 | }
55 | ```
56 |
57 |
58 | ### Supported badge style for now
59 |
60 | Class name | usage scenario
61 | :----------- | :-----------
62 | BGABadgeRadioButton | Bottom navigation of weibo home page
63 | BGABadgeImageView | User’s photo of weibo user list
64 | BGABadgeTextView | You can alternatively use BGABadgeCheckedTextView
65 | BGABadgeLinearLayout | Message number in the right of item in the list
66 | BGABadgeRelativeLayout | Message number in the right of item in the list
67 | BGABadgeFrameLayout | Message number in the right of item in the list
68 |
69 | ### Interface/api explain
70 |
71 | ```java
72 | /**
73 | * show circle badge
74 | */
75 | void showCirclePointBadge();
76 |
77 | /**
78 | * show text badge
79 | *
80 | * @param badgeText
81 | */
82 | void showTextBadge(String badgeText);
83 |
84 | /**
85 | * hide badge
86 | */
87 | void hiddenBadge();
88 |
89 | /**
90 | * show image badge
91 | *
92 | * @param bitmap
93 | */
94 | void showDrawableBadge(Bitmap bitmap);
95 |
96 | /**
97 | * set the delegate to delete the badge by drag and drop
98 | *
99 | * @param delegate
100 | */
101 | void setDragDismissDelegage(BGADragDismissDelegate delegate);
102 |
103 | /**
104 | * Whether show the badge or not
105 | *
106 | * @return
107 | */
108 | boolean isShowBadge();
109 |
110 | /**
111 | * Can it be dragged
112 | *
113 | * @return
114 | */
115 | boolean isDraggable();
116 |
117 | /**
118 | * Whether being dragged
119 | *
120 | * @return
121 | */
122 | boolean isDragging();
123 | ```
124 |
125 | ### The customed attribution
126 |
127 | The customed attribution | Explain | Default value
128 | :----------- | :----------- | :-----------
129 | badge_bgColor | Badge background | Color.RED
130 | badge_textColor | Text color of badge | Color.WHITE
131 | badge_textSize | Text font size of badge | 10sp
132 | badge_verticalMargin | The distance in pixels from the top edge of badge’s background to the top edge of the host or from the bottom edge of badge’s bottom to the host’s bottom | 4dp
133 | badge_horizontalMargin | The distance in pixels from the edge of badge’s background to the left or right edge of the host | 4dp
134 | badge_padding | Badge’s padding | 4dp
135 | badge_gravity | Badge’s gravity, it’s layout direction | For BGABadgeImageView and BGABadgeRadioButton, upper right.For others, the default is the right side of the vertical center
136 | badge_draggable | The badge can be drag or not | false
137 | badge_isResumeTravel | When the badge is dragged out of path, if it can resume the path in case of put back | false
138 | badge_borderWidth | Border width of badge | 0dp
139 | badge_borderColor | Border color of badge | Color.WHITE
140 | badge_dragExtra | Extra distance of trigger drag event | 4dp
141 |
142 | ### About me
143 |
144 | | Personal homepage | email | QQ for the BGA funs |
145 | | ------------- | ------------ | ------------ |
146 | | bingoogolapple.cn | bingoogolapple@gmail.com |  |
147 |
148 | ## Donate
149 |
150 | It takes much time and energy to maintain and improve this project. It BGA helps you, you may want to buy me a coffee :).
151 |
152 |
153 |
154 |
155 |
156 | ## License
157 |
158 | Copyright 2015 bingoogolapple
159 |
160 | Licensed under the Apache License, Version 2.0 (the "License");
161 | you may not use this file except in compliance with the License.
162 | You may obtain a copy of the License at
163 |
164 | http://www.apache.org/licenses/LICENSE-2.0
165 |
166 | Unless required by applicable law or agreed to in writing, software
167 | distributed under the License is distributed on an "AS IS" BASIS,
168 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
169 | See the License for the specific language governing permissions and
170 | limitations under the License.
171 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | :heartpulse:BGABadgeView-Android:heartpulse:
2 | ============
3 |
4 | [](http://android-arsenal.com/details/1/2106)
5 | [](https://www.apache.org/licenses/LICENSE-2.0)
6 | [](https://jitpack.io/#bingoogolapple/BGABadgeView-Android)
7 |
8 | ### [English Document](https://github.com/bingoogolapple/BGABadgeView-Android/blob/master/README-en.md)
9 |
10 | ### [react-native-bga-badge-view](https://github.com/bingoogolapple/react-native-bga-badge-view)
11 |
12 | **demo中演示了:**
13 | * 微博底部tab显示最新微博条数
14 | * 微博列表用户头像显示显示右下角vip徽章
15 | * 微信消息界面用户新消息
16 | * 微信消息界面订阅号新消息
17 | * 使用v4包中的RoundedBitmapDrawable制作圆角头像
18 | * 拖拽删除徽章
19 |
20 | ### 爆炸效果参考的 [ExplosionField](https://github.com/tyrantgit/ExplosionField) 改成了只有一个View的情况,只刷新徽章附近的区域
21 |
22 | ### 效果图
23 | 
24 |
25 | ### [点击下载 Apk](http://fir.im/BGABadgeViewDemo) 或扫描下方二维码安装体验
26 | 
27 |
28 | ### 添加 Gradle 依赖
29 |
30 | * 把 `maven { url 'https://jitpack.io' }` 加入到 repositories 中
31 | * 添加如下依赖,末尾的「latestVersion」指的是徽章[](https://jitpack.io/#bingoogolapple/BGABadgeView-Android)里的版本名称,请自行替换。
32 |
33 | ```groovy
34 | dependencies {
35 | implementation 'com.github.bingoogolapple.BGABadgeView-Android:api:latestVersion'
36 | annotationProcessor 'com.github.bingoogolapple.BGABadgeView-Android:compiler:latestVersion'
37 | }
38 | ```
39 |
40 | ### 初始化徽章控件
41 |
42 | 1. 在项目任意一个类上面添加 BGABadge 注解,例如新建一个类 BGABadgeInit 专门用于初始化徽章控件
43 | 2. 需要哪些类具有徽章功能,就把那些类的 Class 作为 BGABadge 注解的参数「下面的代码块给出了例子,不需要的可以删掉对应的行」
44 | ```Java
45 | @BGABadge({
46 | View.class, // 对应 cn.bingoogolapple.badgeview.BGABadgeView,不想用这个类的话就删了这一行
47 | ImageView.class, // 对应 cn.bingoogolapple.badgeview.BGABadgeImageView,不想用这个类的话就删了这一行
48 | TextView.class, // 对应 cn.bingoogolapple.badgeview.BGABadgeFloatingTextView,不想用这个类的话就删了这一行
49 | RadioButton.class, // 对应 cn.bingoogolapple.badgeview.BGABadgeRadioButton,不想用这个类的话就删了这一行
50 | LinearLayout.class, // 对应 cn.bingoogolapple.badgeview.BGABadgeLinearLayout,不想用这个类的话就删了这一行
51 | FrameLayout.class, // 对应 cn.bingoogolapple.badgeview.BGABadgeFrameLayout,不想用这个类的话就删了这一行
52 | RelativeLayout.class, // 对应 cn.bingoogolapple.badgeview.BGABadgeRelativeLayout,不想用这个类的话就删了这一行
53 | FloatingActionButton.class, // 对应 cn.bingoogolapple.badgeview.BGABadgeFloatingActionButton,不想用这个类的话就删了这一行
54 | ...
55 | ...
56 | ...
57 | })
58 | public class BGABadgeInit {
59 | }
60 | ```
61 | 3. 再 AS 中执行 Build => Rebuild Project
62 | 4. 经过前面三个步骤后就可以通过「cn.bingoogolapple.badgeview.BGABadge原始类名」来使用徽章控件了
63 |
64 | ### 接口说明
65 |
66 | ```java
67 | /**
68 | * 显示圆点徽章
69 | */
70 | void showCirclePointBadge();
71 |
72 | /**
73 | * 显示文字徽章
74 | *
75 | * @param badgeText
76 | */
77 | void showTextBadge(String badgeText);
78 |
79 | /**
80 | * 隐藏徽章
81 | */
82 | void hiddenBadge();
83 |
84 | /**
85 | * 显示图像徽章
86 | *
87 | * @param bitmap
88 | */
89 | void showDrawableBadge(Bitmap bitmap);
90 |
91 | /**
92 | * 设置拖动删除徽章的代理
93 | *
94 | * @param delegate
95 | */
96 | void setDragDismissDelegage(BGADragDismissDelegate delegate);
97 |
98 | /**
99 | * 是否显示徽章
100 | *
101 | * @return
102 | */
103 | boolean isShowBadge();
104 |
105 | /**
106 | * 是否可拖动
107 | *
108 | * @return
109 | */
110 | boolean isDraggable();
111 |
112 | /**
113 | * 是否正在拖动
114 | *
115 | * @return
116 | */
117 | boolean isDragging();
118 | ```
119 |
120 | ### 自定义属性说明
121 |
122 | 属性名 | 说明 | 默认值
123 | :----------- | :----------- | :-----------
124 | badge_bgColor | 徽章背景色 | Color.RED
125 | badge_textColor | 徽章文本的颜色 | Color.WHITE
126 | badge_textSize | 徽章文本字体大小 | 10sp
127 | badge_verticalMargin | 徽章背景与宿主控件上下边缘间距离 | 4dp
128 | badge_horizontalMargin | 徽章背景与宿主控件左右边缘间距离 | 4dp
129 | badge_padding | 徽章文本边缘与徽章背景边缘间的距离 | 4dp
130 | badge_gravity | 徽章在宿主控件中的位置 | BGABadgeImageView和BGABadgeRadioButton是右上方,其他控件是右边垂直居中
131 | badge_draggable | 是否开启拖拽删除徽章 | false
132 | badge_isResumeTravel | 拖拽徽章超出轨迹范围后,再次放回到轨迹范围时,是否恢复轨迹 | false
133 | badge_borderWidth | 徽章描边宽度 | 0dp
134 | badge_borderColor | 徽章描边颜色 | Color.WHITE
135 | badge_dragExtra | 触发开始拖拽徽章事件的扩展触摸距离 | 4dp
136 |
137 | ## 作者联系方式
138 |
139 | | 个人主页 | 邮箱 |
140 | | ------------- | ------------ |
141 | | bingoogolapple.cn | bingoogolapple@gmail.com |
142 |
143 | | 个人微信号 | 微信群 | 公众号 |
144 | | ------------ | ------------ | ------------ |
145 | |
|
|
|
146 |
147 | | 个人 QQ 号 | QQ 群 |
148 | | ------------ | ------------ |
149 | |
|
|
150 |
151 | ## 打赏支持作者
152 |
153 | 如果您觉得 BGA 系列开源库或工具软件帮您节省了大量的开发时间,可以扫描下方的二维码打赏支持。您的支持将鼓励我继续创作,打赏后还可以加我微信免费开通一年 [上帝小助手浏览器扩展/插件开发平台](https://github.com/bingoogolapple/bga-god-assistant-config) 的会员服务
154 |
155 | | 微信 | QQ | 支付宝 |
156 | | ------------- | ------------- | ------------- |
157 | |
|
|
|
158 |
159 | ## 作者项目推荐
160 |
161 | * 欢迎您使用我开发的第一个独立开发软件产品 [上帝小助手浏览器扩展/插件开发平台](https://github.com/bingoogolapple/bga-god-assistant-config)
162 |
163 | ## License
164 |
165 | Copyright 2015 bingoogolapple
166 |
167 | Licensed under the Apache License, Version 2.0 (the "License");
168 | you may not use this file except in compliance with the License.
169 | You may obtain a copy of the License at
170 |
171 | http://www.apache.org/licenses/LICENSE-2.0
172 |
173 | Unless required by applicable law or agreed to in writing, software
174 | distributed under the License is distributed on an "AS IS" BASIS,
175 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
176 | See the License for the specific language governing permissions and
177 | limitations under the License.
178 |
--------------------------------------------------------------------------------
/annotation/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java-library'
2 | apply plugin: 'maven'
3 |
4 | sourceCompatibility = JavaVersion.VERSION_1_7
5 | targetCompatibility = JavaVersion.VERSION_1_7
6 |
7 | dependencies {
8 | compileOnly 'com.google.android:android:4.1.1.4'
9 | }
10 |
--------------------------------------------------------------------------------
/annotation/src/main/java/cn/bingoogolapple/badgeview/annotation/BGABadge.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2018 bingoogolapple
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package cn.bingoogolapple.badgeview.annotation;
18 |
19 | import android.view.View;
20 |
21 | import java.lang.annotation.ElementType;
22 | import java.lang.annotation.Retention;
23 | import java.lang.annotation.RetentionPolicy;
24 | import java.lang.annotation.Target;
25 |
26 | /**
27 | * 作者:王浩 邮件:bingoogolapple@gmail.com
28 | * 创建时间:2018/1/14
29 | * 描述:
30 | */
31 | @Retention(RetentionPolicy.CLASS)
32 | @Target(ElementType.TYPE)
33 | public @interface BGABadge {
34 | Class extends View>[] value() default {};
35 | }
36 |
--------------------------------------------------------------------------------
/api/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'com.github.dcendents.android-maven'
3 |
4 | android {
5 | compileSdkVersion ANDROID_BUILD_SDK_VERSION as int
6 |
7 | defaultConfig {
8 | minSdkVersion ANDROID_BUILD_MIN_SDK_VERSION as int
9 | targetSdkVersion ANDROID_BUILD_TARGET_SDK_VERSION as int
10 | }
11 |
12 | android {
13 | lintOptions {
14 | abortOnError false
15 | }
16 | }
17 | }
18 |
19 | dependencies {
20 | compileOnly 'com.android.support:appcompat-v7:27.0.2'
21 | api project(':annotation')
22 | }
23 |
--------------------------------------------------------------------------------
/api/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/api/src/main/java/cn/bingoogolapple/badgeview/BGABadgeViewHelper.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2015 bingoogolapple
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package cn.bingoogolapple.badgeview;
18 |
19 | import android.content.Context;
20 | import android.content.res.TypedArray;
21 | import android.graphics.Bitmap;
22 | import android.graphics.Canvas;
23 | import android.graphics.Color;
24 | import android.graphics.Paint;
25 | import android.graphics.Rect;
26 | import android.graphics.RectF;
27 | import android.text.TextUtils;
28 | import android.util.AttributeSet;
29 | import android.view.MotionEvent;
30 | import android.view.View;
31 |
32 | /**
33 | * 作者:王浩 邮件:bingoogolapple@gmail.com
34 | * 创建时间:15/7/6 下午10:13
35 | * 描述:
36 | */
37 | public class BGABadgeViewHelper {
38 | private Bitmap mBitmap;
39 | private BGABadgeable mBadgeable;
40 | private Paint mBadgePaint;
41 | /**
42 | * 徽章背景色
43 | */
44 | private int mBadgeBgColor;
45 | /**
46 | * 徽章文本的颜色
47 | */
48 | private int mBadgeTextColor;
49 | /**
50 | * 徽章文本字体大小
51 | */
52 | private int mBadgeTextSize;
53 | /**
54 | * 徽章背景与宿主控件上下边缘间距离
55 | */
56 | private int mBadgeVerticalMargin;
57 | /**
58 | * 徽章背景与宿主控件左右边缘间距离
59 | */
60 | private int mBadgeHorizontalMargin;
61 | /***
62 | * 徽章文本边缘与徽章背景边缘间的距离
63 | */
64 | private int mBadgePadding;
65 | /**
66 | * 徽章文本
67 | */
68 | private String mBadgeText;
69 | /**
70 | * 徽章文本所占区域大小
71 | */
72 | private Rect mBadgeNumberRect;
73 | /**
74 | * 是否显示Badge
75 | */
76 | private boolean mIsShowBadge;
77 | /**
78 | * 徽章在宿主控件中的位置
79 | */
80 | private BadgeGravity mBadgeGravity;
81 | /**
82 | * 整个徽章所占区域
83 | */
84 | private RectF mBadgeRectF;
85 | /**
86 | * 是否可拖动
87 | */
88 | private boolean mDraggable;
89 | /**
90 | * 拖拽徽章超出轨迹范围后,再次放回到轨迹范围时,是否恢复轨迹
91 | */
92 | private boolean mIsResumeTravel;
93 | /***
94 | * 徽章描边宽度
95 | */
96 | private int mBadgeBorderWidth;
97 | /***
98 | * 徽章描边颜色
99 | */
100 | private int mBadgeBorderColor;
101 | /**
102 | * 触发开始拖拽徽章事件的扩展触摸距离
103 | */
104 | private int mDragExtra;
105 | /**
106 | * 整个徽章加上其触发开始拖拽区域所占区域
107 | */
108 | private RectF mBadgeDragExtraRectF;
109 | /**
110 | * 拖动时的徽章控件
111 | */
112 | private BGADragBadgeView mDropBadgeView;
113 | /**
114 | * 是否正在拖动
115 | */
116 | private boolean mIsDragging;
117 | /**
118 | * 拖动大于BGABadgeViewHelper.mMoveHiddenThreshold后抬起手指徽章消失的代理
119 | */
120 | private BGADragDismissDelegate mDelegate;
121 | private boolean mIsShowDrawable = false;
122 |
123 | public BGABadgeViewHelper(BGABadgeable badgeable, Context context, AttributeSet attrs, BadgeGravity defaultBadgeGravity) {
124 | mBadgeable = badgeable;
125 | initDefaultAttrs(context, defaultBadgeGravity);
126 | initCustomAttrs(context, attrs);
127 | afterInitDefaultAndCustomAttrs();
128 | mDropBadgeView = new BGADragBadgeView(context, this);
129 | }
130 |
131 | private void initDefaultAttrs(Context context, BadgeGravity defaultBadgeGravity) {
132 | mBadgeNumberRect = new Rect();
133 | mBadgeRectF = new RectF();
134 | mBadgeBgColor = Color.RED;
135 | mBadgeTextColor = Color.WHITE;
136 | mBadgeTextSize = BGABadgeViewUtil.sp2px(context, 10);
137 |
138 | mBadgePaint = new Paint();
139 | mBadgePaint.setAntiAlias(true);
140 | mBadgePaint.setStyle(Paint.Style.FILL);
141 | // 设置mBadgeText居中,保证mBadgeText长度为1时,文本也能居中
142 | mBadgePaint.setTextAlign(Paint.Align.CENTER);
143 |
144 | mBadgePadding = BGABadgeViewUtil.dp2px(context, 4);
145 | mBadgeVerticalMargin = BGABadgeViewUtil.dp2px(context, 4);
146 | mBadgeHorizontalMargin = BGABadgeViewUtil.dp2px(context, 4);
147 |
148 | mBadgeGravity = defaultBadgeGravity;
149 | mIsShowBadge = false;
150 |
151 | mBadgeText = null;
152 |
153 | mBitmap = null;
154 |
155 | mIsDragging = false;
156 |
157 | mDraggable = false;
158 |
159 | mBadgeBorderColor = Color.WHITE;
160 |
161 | mDragExtra = BGABadgeViewUtil.dp2px(context, 4);
162 | mBadgeDragExtraRectF = new RectF();
163 | }
164 |
165 | private void initCustomAttrs(Context context, AttributeSet attrs) {
166 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.BGABadgeView);
167 | final int N = typedArray.getIndexCount();
168 | for (int i = 0; i < N; i++) {
169 | initCustomAttr(typedArray.getIndex(i), typedArray);
170 | }
171 | typedArray.recycle();
172 | }
173 |
174 | private void initCustomAttr(int attr, TypedArray typedArray) {
175 | if (attr == R.styleable.BGABadgeView_badge_bgColor) {
176 | mBadgeBgColor = typedArray.getColor(attr, mBadgeBgColor);
177 | } else if (attr == R.styleable.BGABadgeView_badge_textColor) {
178 | mBadgeTextColor = typedArray.getColor(attr, mBadgeTextColor);
179 | } else if (attr == R.styleable.BGABadgeView_badge_textSize) {
180 | mBadgeTextSize = typedArray.getDimensionPixelSize(attr, mBadgeTextSize);
181 | } else if (attr == R.styleable.BGABadgeView_badge_verticalMargin) {
182 | mBadgeVerticalMargin = typedArray.getDimensionPixelSize(attr, mBadgeVerticalMargin);
183 | } else if (attr == R.styleable.BGABadgeView_badge_horizontalMargin) {
184 | mBadgeHorizontalMargin = typedArray.getDimensionPixelSize(attr, mBadgeHorizontalMargin);
185 | } else if (attr == R.styleable.BGABadgeView_badge_padding) {
186 | mBadgePadding = typedArray.getDimensionPixelSize(attr, mBadgePadding);
187 | } else if (attr == R.styleable.BGABadgeView_badge_gravity) {
188 | int ordinal = typedArray.getInt(attr, mBadgeGravity.ordinal());
189 | mBadgeGravity = BadgeGravity.values()[ordinal];
190 | } else if (attr == R.styleable.BGABadgeView_badge_draggable) {
191 | mDraggable = typedArray.getBoolean(attr, mDraggable);
192 | } else if (attr == R.styleable.BGABadgeView_badge_isResumeTravel) {
193 | mIsResumeTravel = typedArray.getBoolean(attr, mIsResumeTravel);
194 | } else if (attr == R.styleable.BGABadgeView_badge_borderWidth) {
195 | mBadgeBorderWidth = typedArray.getDimensionPixelSize(attr, mBadgeBorderWidth);
196 | } else if (attr == R.styleable.BGABadgeView_badge_borderColor) {
197 | mBadgeBorderColor = typedArray.getColor(attr, mBadgeBorderColor);
198 | } else if (attr == R.styleable.BGABadgeView_badge_dragExtra) {
199 | mDragExtra = typedArray.getDimensionPixelSize(attr, mDragExtra);
200 | }
201 | }
202 |
203 | private void afterInitDefaultAndCustomAttrs() {
204 | mBadgePaint.setTextSize(mBadgeTextSize);
205 | }
206 |
207 | public void setBadgeBgColorInt(int badgeBgColor) {
208 | mBadgeBgColor = badgeBgColor;
209 | mBadgeable.postInvalidate();
210 | }
211 |
212 | public void setBadgeTextColorInt(int badgeTextColor) {
213 | mBadgeTextColor = badgeTextColor;
214 | mBadgeable.postInvalidate();
215 | }
216 |
217 | public void setBadgeTextSizeSp(int badgetextSize) {
218 | if (badgetextSize >= 0) {
219 | mBadgeTextSize = BGABadgeViewUtil.sp2px(mBadgeable.getContext(), badgetextSize);
220 | mBadgePaint.setTextSize(mBadgeTextSize);
221 | mBadgeable.postInvalidate();
222 | }
223 | }
224 |
225 | public void setBadgeVerticalMarginDp(int badgeVerticalMargin) {
226 | if (badgeVerticalMargin >= 0) {
227 | mBadgeVerticalMargin = BGABadgeViewUtil.dp2px(mBadgeable.getContext(), badgeVerticalMargin);
228 | mBadgeable.postInvalidate();
229 | }
230 | }
231 |
232 | public void setBadgeHorizontalMarginDp(int badgeHorizontalMargin) {
233 | if (badgeHorizontalMargin >= 0) {
234 | mBadgeHorizontalMargin = BGABadgeViewUtil.dp2px(mBadgeable.getContext(), badgeHorizontalMargin);
235 | mBadgeable.postInvalidate();
236 | }
237 | }
238 |
239 | public void setBadgePaddingDp(int badgePadding) {
240 | if (badgePadding >= 0) {
241 | mBadgePadding = BGABadgeViewUtil.dp2px(mBadgeable.getContext(), badgePadding);
242 | mBadgeable.postInvalidate();
243 | }
244 | }
245 |
246 | public void setBadgeGravity(BadgeGravity badgeGravity) {
247 | if (badgeGravity != null) {
248 | mBadgeGravity = badgeGravity;
249 | mBadgeable.postInvalidate();
250 | }
251 | }
252 |
253 | public void setDraggable(boolean draggable) {
254 | mDraggable = draggable;
255 | mBadgeable.postInvalidate();
256 | }
257 |
258 | public void setIsResumeTravel(boolean isResumeTravel) {
259 | mIsResumeTravel = isResumeTravel;
260 | mBadgeable.postInvalidate();
261 | }
262 |
263 | public void setBadgeBorderWidthDp(int badgeBorderWidthDp) {
264 | if (badgeBorderWidthDp >= 0) {
265 | mBadgeBorderWidth = BGABadgeViewUtil.dp2px(mBadgeable.getContext(), badgeBorderWidthDp);
266 | mBadgeable.postInvalidate();
267 | }
268 | }
269 |
270 | public void setBadgeBorderColorInt(int badgeBorderColor) {
271 | mBadgeBorderColor = badgeBorderColor;
272 | mBadgeable.postInvalidate();
273 | }
274 |
275 | public boolean onTouchEvent(MotionEvent event) {
276 | switch (event.getAction()) {
277 | case MotionEvent.ACTION_DOWN:
278 | mBadgeDragExtraRectF.left = mBadgeRectF.left - mDragExtra;
279 | mBadgeDragExtraRectF.top = mBadgeRectF.top - mDragExtra;
280 | mBadgeDragExtraRectF.right = mBadgeRectF.right + mDragExtra;
281 | mBadgeDragExtraRectF.bottom = mBadgeRectF.bottom + mDragExtra;
282 |
283 | if ((mBadgeBorderWidth == 0 || mIsShowDrawable) && mDraggable && mIsShowBadge && mBadgeDragExtraRectF.contains(event.getX(), event.getY())) {
284 | mIsDragging = true;
285 | mBadgeable.getParent().requestDisallowInterceptTouchEvent(true);
286 |
287 | Rect badgeableRect = new Rect();
288 | mBadgeable.getGlobalVisibleRect(badgeableRect);
289 | mDropBadgeView.setStickCenter(badgeableRect.left + mBadgeRectF.left + mBadgeRectF.width() / 2, badgeableRect.top + mBadgeRectF.top + mBadgeRectF.height() / 2);
290 |
291 | mDropBadgeView.onTouchEvent(event);
292 | mBadgeable.postInvalidate();
293 | return true;
294 | }
295 | break;
296 | case MotionEvent.ACTION_MOVE:
297 | if (mIsDragging) {
298 | mDropBadgeView.onTouchEvent(event);
299 | return true;
300 | }
301 | break;
302 | case MotionEvent.ACTION_UP:
303 | case MotionEvent.ACTION_CANCEL:
304 | if (mIsDragging) {
305 | mDropBadgeView.onTouchEvent(event);
306 | mIsDragging = false;
307 | return true;
308 | }
309 | break;
310 | default:
311 | break;
312 | }
313 | return mBadgeable.callSuperOnTouchEvent(event);
314 | }
315 |
316 | public void endDragWithDismiss() {
317 | hiddenBadge();
318 | if (mDelegate != null) {
319 | mDelegate.onDismiss(mBadgeable);
320 | }
321 | }
322 |
323 | public void endDragWithoutDismiss() {
324 | mBadgeable.postInvalidate();
325 | }
326 |
327 | public void drawBadge(Canvas canvas) {
328 | if (mIsShowBadge && !mIsDragging) {
329 | if (mIsShowDrawable) {
330 | drawDrawableBadge(canvas);
331 | } else {
332 | drawTextBadge(canvas);
333 | }
334 | }
335 | }
336 |
337 | /**
338 | * 绘制图像徽章
339 | *
340 | * @param canvas
341 | */
342 | private void drawDrawableBadge(Canvas canvas) {
343 | mBadgeRectF.left = mBadgeable.getWidth() - mBadgeHorizontalMargin - mBitmap.getWidth();
344 | mBadgeRectF.top = mBadgeVerticalMargin;
345 | switch (mBadgeGravity) {
346 | case RightTop:
347 | mBadgeRectF.top = mBadgeVerticalMargin;
348 | break;
349 | case RightCenter:
350 | mBadgeRectF.top = (mBadgeable.getHeight() - mBitmap.getHeight()) / 2;
351 | break;
352 | case RightBottom:
353 | mBadgeRectF.top = mBadgeable.getHeight() - mBitmap.getHeight() - mBadgeVerticalMargin;
354 | break;
355 | default:
356 | break;
357 | }
358 | canvas.drawBitmap(mBitmap, mBadgeRectF.left, mBadgeRectF.top, mBadgePaint);
359 | mBadgeRectF.right = mBadgeRectF.left + mBitmap.getWidth();
360 | mBadgeRectF.bottom = mBadgeRectF.top + mBitmap.getHeight();
361 | }
362 |
363 | /**
364 | * 绘制文字徽章
365 | *
366 | * @param canvas
367 | */
368 | private void drawTextBadge(Canvas canvas) {
369 | String badgeText = "";
370 | if (!TextUtils.isEmpty(mBadgeText)) {
371 | badgeText = mBadgeText;
372 | }
373 | // 获取文本宽所占宽高
374 | mBadgePaint.getTextBounds(badgeText, 0, badgeText.length(), mBadgeNumberRect);
375 | // 计算徽章背景的宽高
376 | int badgeHeight = mBadgeNumberRect.height() + mBadgePadding * 2;
377 | int badgeWidth;
378 | // 当mBadgeText的长度为1或0时,计算出来的高度会比宽度大,此时设置宽度等于高度
379 | if (badgeText.length() == 1 || badgeText.length() == 0) {
380 | badgeWidth = badgeHeight;
381 | } else {
382 | badgeWidth = mBadgeNumberRect.width() + mBadgePadding * 2;
383 | }
384 |
385 | // 计算徽章背景上下的值
386 | mBadgeRectF.top = mBadgeVerticalMargin;
387 | mBadgeRectF.bottom = mBadgeable.getHeight() - mBadgeVerticalMargin;
388 | switch (mBadgeGravity) {
389 | case RightTop:
390 | mBadgeRectF.bottom = mBadgeRectF.top + badgeHeight;
391 | break;
392 | case RightCenter:
393 | mBadgeRectF.top = (mBadgeable.getHeight() - badgeHeight) / 2;
394 | mBadgeRectF.bottom = mBadgeRectF.top + badgeHeight;
395 | break;
396 | case RightBottom:
397 | mBadgeRectF.top = mBadgeRectF.bottom - badgeHeight;
398 | break;
399 | default:
400 | break;
401 | }
402 |
403 | // 计算徽章背景左右的值
404 | mBadgeRectF.right = mBadgeable.getWidth() - mBadgeHorizontalMargin;
405 | mBadgeRectF.left = mBadgeRectF.right - badgeWidth;
406 |
407 | if (mBadgeBorderWidth > 0) {
408 | // 设置徽章边框景色
409 | mBadgePaint.setColor(mBadgeBorderColor);
410 | // 绘制徽章边框背景
411 | canvas.drawRoundRect(mBadgeRectF, badgeHeight / 2, badgeHeight / 2, mBadgePaint);
412 |
413 | // 设置徽章背景色
414 | mBadgePaint.setColor(mBadgeBgColor);
415 | // 绘制徽章背景
416 | canvas.drawRoundRect(new RectF(mBadgeRectF.left + mBadgeBorderWidth, mBadgeRectF.top + mBadgeBorderWidth, mBadgeRectF.right - mBadgeBorderWidth, mBadgeRectF.bottom - mBadgeBorderWidth), (badgeHeight - 2 * mBadgeBorderWidth) / 2, (badgeHeight - 2 * mBadgeBorderWidth) / 2, mBadgePaint);
417 | } else {
418 | // 设置徽章背景色
419 | mBadgePaint.setColor(mBadgeBgColor);
420 | // 绘制徽章背景
421 | canvas.drawRoundRect(mBadgeRectF, badgeHeight / 2, badgeHeight / 2, mBadgePaint);
422 | }
423 |
424 |
425 | if (!TextUtils.isEmpty(mBadgeText)) {
426 | // 设置徽章文本颜色
427 | mBadgePaint.setColor(mBadgeTextColor);
428 | // initDefaultAttrs方法中设置了mBadgeText居中,此处的x为徽章背景的中心点y
429 | float x = mBadgeRectF.left + badgeWidth / 2;
430 | // 注意:绘制文本时的y是指文本底部,而不是文本的中间
431 | float y = mBadgeRectF.bottom - mBadgePadding;
432 | // 绘制徽章文本
433 | canvas.drawText(badgeText, x, y, mBadgePaint);
434 | }
435 | }
436 |
437 | public void showCirclePointBadge() {
438 | showTextBadge(null);
439 | }
440 |
441 | public void showTextBadge(String badgeText) {
442 | mIsShowDrawable = false;
443 | mBadgeText = badgeText;
444 | mIsShowBadge = true;
445 | mBadgeable.postInvalidate();
446 | }
447 |
448 | public void hiddenBadge() {
449 | mIsShowBadge = false;
450 | mBadgeable.postInvalidate();
451 | }
452 |
453 | public boolean isShowBadge() {
454 | return mIsShowBadge;
455 | }
456 |
457 | public void showDrawable(Bitmap bitmap) {
458 | mBitmap = bitmap;
459 | mIsShowDrawable = true;
460 | mIsShowBadge = true;
461 | mBadgeable.postInvalidate();
462 | }
463 |
464 | public boolean isShowDrawable() {
465 | return mIsShowDrawable;
466 | }
467 |
468 | public RectF getBadgeRectF() {
469 | return mBadgeRectF;
470 | }
471 |
472 | public int getBadgePadding() {
473 | return mBadgePadding;
474 | }
475 |
476 | public String getBadgeText() {
477 | return mBadgeText;
478 | }
479 |
480 | public int getBadgeBgColor() {
481 | return mBadgeBgColor;
482 | }
483 |
484 | public int getBadgeTextColor() {
485 | return mBadgeTextColor;
486 | }
487 |
488 | public int getBadgeTextSize() {
489 | return mBadgeTextSize;
490 | }
491 |
492 | public Bitmap getBitmap() {
493 | return mBitmap;
494 | }
495 |
496 | public void setDragDismissDelegate(BGADragDismissDelegate delegate) {
497 | mDelegate = delegate;
498 | }
499 |
500 | public View getRootView() {
501 | return mBadgeable.getRootView();
502 | }
503 |
504 | public boolean isResumeTravel() {
505 | return mIsResumeTravel;
506 | }
507 |
508 | public boolean isDragging() {
509 | return mIsDragging;
510 | }
511 |
512 | public boolean isDraggable() {
513 | return mDraggable;
514 | }
515 |
516 | public enum BadgeGravity {
517 | RightTop,
518 | RightCenter,
519 | RightBottom
520 | }
521 | }
--------------------------------------------------------------------------------
/api/src/main/java/cn/bingoogolapple/badgeview/BGABadgeViewUtil.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2015 bingoogolapple
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package cn.bingoogolapple.badgeview;
18 |
19 | import android.content.Context;
20 | import android.graphics.Bitmap;
21 | import android.graphics.PointF;
22 | import android.graphics.Rect;
23 | import android.util.TypedValue;
24 |
25 | /**
26 | * 作者:王浩 邮件:bingoogolapple@gmail.com
27 | * 创建时间:15/12/5 上午12:27
28 | * 描述:
29 | */
30 | public class BGABadgeViewUtil {
31 |
32 | private BGABadgeViewUtil() {
33 | }
34 |
35 | public static int dp2px(Context context, float dpValue) {
36 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpValue, context.getResources().getDisplayMetrics());
37 | }
38 |
39 | public static int sp2px(Context context, float spValue) {
40 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spValue, context.getResources().getDisplayMetrics());
41 | }
42 |
43 | public static Bitmap createBitmapSafely(BGADragBadgeView dragBadgeView, Rect rect, int retryCount) {
44 | try {
45 | dragBadgeView.setDrawingCacheEnabled(true);
46 | // 只裁剪徽章区域,不然会很卡
47 | return Bitmap.createBitmap(dragBadgeView.getDrawingCache(), rect.left < 0 ? 0 : rect.left, rect.top < 0 ? 0 : rect.top, rect.width(), rect.height());
48 | } catch (OutOfMemoryError e) {
49 | if (retryCount > 0) {
50 | System.gc();
51 | return createBitmapSafely(dragBadgeView, rect, retryCount - 1);
52 | }
53 | return null;
54 | }
55 | }
56 |
57 | public static float getDistanceBetween2Points(PointF p0, PointF p1) {
58 | float distance = (float) Math.sqrt(Math.pow(p0.y - p1.y, 2) + Math.pow(p0.x - p1.x, 2));
59 | return distance;
60 | }
61 |
62 | public static PointF getMiddlePoint(PointF p1, PointF p2) {
63 | return new PointF((p1.x + p2.x) / 2.0f, (p1.y + p2.y) / 2.0f);
64 | }
65 |
66 | public static PointF getPointByPercent(PointF p1, PointF p2, float percent) {
67 | return new PointF(evaluate(percent, p1.x, p2.x), evaluate(percent, p1.y, p2.y));
68 | }
69 |
70 | // 从FloatEvaluator中拷贝过来,这样就不用每次都new FloatEvaluator了
71 | public static Float evaluate(float fraction, Number startValue, Number endValue) {
72 | float startFloat = startValue.floatValue();
73 | return startFloat + fraction * (endValue.floatValue() - startFloat);
74 | }
75 |
76 | public static PointF[] getIntersectionPoints(PointF pMiddle, float radius, Double lineK) {
77 | PointF[] points = new PointF[2];
78 |
79 | float radian, xOffset = 0, yOffset = 0;
80 | if (lineK != null) {
81 | radian = (float) Math.atan(lineK);
82 | xOffset = (float) (Math.sin(radian) * radius);
83 | yOffset = (float) (Math.cos(radian) * radius);
84 | } else {
85 | xOffset = radius;
86 | yOffset = 0;
87 | }
88 | points[0] = new PointF(pMiddle.x + xOffset, pMiddle.y - yOffset);
89 | points[1] = new PointF(pMiddle.x - xOffset, pMiddle.y + yOffset);
90 |
91 | return points;
92 | }
93 | }
--------------------------------------------------------------------------------
/api/src/main/java/cn/bingoogolapple/badgeview/BGABadgeable.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2015 bingoogolapple
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package cn.bingoogolapple.badgeview;
18 |
19 | import android.content.Context;
20 | import android.graphics.Bitmap;
21 | import android.graphics.Rect;
22 | import android.view.MotionEvent;
23 | import android.view.View;
24 | import android.view.ViewParent;
25 |
26 | /**
27 | * 作者:王浩 邮件:bingoogolapple@gmail.com
28 | * 创建时间:15/7/6 下午10:42
29 | * 描述:
30 | */
31 | public interface BGABadgeable {
32 | /**
33 | * 显示圆点徽章
34 | */
35 | void showCirclePointBadge();
36 |
37 | /**
38 | * 显示文字徽章
39 | *
40 | * @param badgeText
41 | */
42 | void showTextBadge(String badgeText);
43 |
44 | /**
45 | * 隐藏徽章
46 | */
47 | void hiddenBadge();
48 |
49 | /**
50 | * 显示图像徽章
51 | *
52 | * @param bitmap
53 | */
54 | void showDrawableBadge(Bitmap bitmap);
55 |
56 | /**
57 | * 调用父类的onTouchEvent方法
58 | *
59 | * @param event
60 | * @return
61 | */
62 | boolean callSuperOnTouchEvent(MotionEvent event);
63 |
64 | /**
65 | * 拖动大于BGABadgeViewHelper.mMoveHiddenThreshold后抬起手指徽章消失的代理
66 | *
67 | * @param delegate
68 | */
69 | void setDragDismissDelegate(BGADragDismissDelegate delegate);
70 |
71 | /**
72 | * 是否显示徽章
73 | *
74 | * @return
75 | */
76 | boolean isShowBadge();
77 |
78 | /**
79 | * 是否可拖动
80 | *
81 | * @return
82 | */
83 | boolean isDraggable();
84 |
85 | /**
86 | * 是否正在拖动
87 | *
88 | * @return
89 | */
90 | boolean isDragging();
91 |
92 | BGABadgeViewHelper getBadgeViewHelper();
93 |
94 | int getWidth();
95 |
96 | int getHeight();
97 |
98 | void postInvalidate();
99 |
100 | ViewParent getParent();
101 |
102 | int getId();
103 |
104 | boolean getGlobalVisibleRect(Rect r);
105 |
106 | Context getContext();
107 |
108 | View getRootView();
109 | }
--------------------------------------------------------------------------------
/api/src/main/java/cn/bingoogolapple/badgeview/BGADragBadgeView.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2015 bingoogolapple
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package cn.bingoogolapple.badgeview;
18 |
19 | import android.animation.Animator;
20 | import android.animation.AnimatorListenerAdapter;
21 | import android.animation.ValueAnimator;
22 | import android.content.Context;
23 | import android.graphics.Bitmap;
24 | import android.graphics.Canvas;
25 | import android.graphics.Color;
26 | import android.graphics.Paint;
27 | import android.graphics.Path;
28 | import android.graphics.PixelFormat;
29 | import android.graphics.PointF;
30 | import android.graphics.Rect;
31 | import android.graphics.RectF;
32 | import android.view.Gravity;
33 | import android.view.MotionEvent;
34 | import android.view.View;
35 | import android.view.WindowManager;
36 | import android.view.animation.OvershootInterpolator;
37 |
38 | import java.lang.ref.WeakReference;
39 |
40 |
41 | /**
42 | * 作者:王浩 邮件:bingoogolapple@gmail.com
43 | * 创建时间:15/7/12 下午3:23
44 | * 描述:
45 | */
46 | class BGADragBadgeView extends View {
47 | private static final String TAG = BGADragBadgeView.class.getSimpleName();
48 | private BGABadgeViewHelper mBadgeViewHelper;
49 | private Paint mBadgePaint;
50 | private WindowManager mWindowManager;
51 | private WindowManager.LayoutParams mLayoutParams;
52 | private int mStartX;
53 | private int mStartY;
54 | private BGAExplosionAnimator mExplosionAnimator;
55 | private SetExplosionAnimatorNullTask mSetExplosionAnimatorNullTask;
56 |
57 | /**
58 | * 针圆切线的切点
59 | */
60 | private PointF[] mStickPoints = new PointF[]{
61 | new PointF(0, 0),
62 | new PointF(0, 0)
63 | };
64 | /**
65 | * 拖拽圆切线的切点
66 | */
67 | private PointF[] mDragPoints = new PointF[]{
68 | new PointF(0, 0),
69 | new PointF(0, 0)
70 | };
71 | /**
72 | * 控制点
73 | */
74 | private PointF mControlPoint = new PointF(0, 0);
75 | /**
76 | * 拖拽圆中心点
77 | */
78 | private PointF mDragCenter = new PointF(0, 0);
79 | /**
80 | * 拖拽圆半径
81 | */
82 | private float mDragRadius;
83 |
84 | /**
85 | * 针圆中心点
86 | */
87 | private PointF mStickCenter;
88 | /**
89 | * 针圆半径
90 | */
91 | private float mStickRadius;
92 | /**
93 | * 拖拽圆最大半径
94 | */
95 | private int mMaxDragRadius;
96 | /**
97 | * 拖拽圆半径和针圆半径的差值
98 | */
99 | private int mDragStickRadiusDifference;
100 | /**
101 | * 拖动mDismissThreshold距离后抬起手指徽章消失
102 | */
103 | private int mDismissThreshold;
104 |
105 | private boolean mDismissAble;
106 | private boolean mIsDragDisappear;
107 |
108 | public BGADragBadgeView(Context context, BGABadgeViewHelper badgeViewHelper) {
109 | super(context);
110 | mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
111 | mBadgeViewHelper = badgeViewHelper;
112 | initBadgePaint();
113 | initLayoutParams();
114 | initStick();
115 |
116 | mSetExplosionAnimatorNullTask = new SetExplosionAnimatorNullTask(this);
117 | }
118 |
119 | private void initBadgePaint() {
120 | mBadgePaint = new Paint();
121 | mBadgePaint.setAntiAlias(true);
122 | mBadgePaint.setStyle(Paint.Style.FILL);
123 | // 设置mBadgeText居中,保证mBadgeText长度为1时,文本也能居中
124 | mBadgePaint.setTextAlign(Paint.Align.CENTER);
125 | mBadgePaint.setTextSize(mBadgeViewHelper.getBadgeTextSize());
126 | }
127 |
128 | private void initLayoutParams() {
129 | mLayoutParams = new WindowManager.LayoutParams();
130 | mLayoutParams.gravity = Gravity.LEFT + Gravity.TOP;
131 | mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
132 | mLayoutParams.format = PixelFormat.TRANSLUCENT;
133 | mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
134 | mLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
135 | mLayoutParams.height = WindowManager.LayoutParams.MATCH_PARENT;
136 | }
137 |
138 | private void initStick() {
139 | mMaxDragRadius = BGABadgeViewUtil.dp2px(getContext(), 10);
140 | mDragStickRadiusDifference = BGABadgeViewUtil.dp2px(getContext(), 1);
141 | }
142 |
143 | @Override
144 | protected void onDraw(Canvas canvas) {
145 | try {
146 | if (mExplosionAnimator == null) {
147 | if (mBadgeViewHelper.isShowDrawable()) {
148 | if (mBadgeViewHelper.getBadgeBgColor() == Color.RED) {
149 | mBadgePaint.setColor(mBadgeViewHelper.getBitmap().getPixel(mBadgeViewHelper.getBitmap().getWidth() / 2,
150 | mBadgeViewHelper.getBitmap().getHeight() / 2));
151 | } else {
152 | mBadgePaint.setColor(mBadgeViewHelper.getBadgeBgColor());
153 | }
154 | drawStick(canvas);
155 | drawDrawableBadge(canvas);
156 | } else {
157 | mBadgePaint.setColor(mBadgeViewHelper.getBadgeBgColor());
158 | drawStick(canvas);
159 | drawTextBadge(canvas);
160 | }
161 | } else {
162 | mExplosionAnimator.draw(canvas);
163 | }
164 | } catch (Exception e) {
165 | // 确保自己能被移除
166 | removeSelfWithException();
167 | }
168 | }
169 |
170 | private void drawDrawableBadge(Canvas canvas) {
171 | canvas.drawBitmap(mBadgeViewHelper.getBitmap(), mStartX, mStartY, mBadgePaint);
172 | }
173 |
174 | private void drawTextBadge(Canvas canvas) {
175 | // 设置徽章背景色
176 | mBadgePaint.setColor(mBadgeViewHelper.getBadgeBgColor());
177 | // 绘制徽章背景
178 | canvas.drawRoundRect(
179 | new RectF(mStartX, mStartY, mStartX + mBadgeViewHelper.getBadgeRectF().width(), mStartY + mBadgeViewHelper.getBadgeRectF().height()),
180 | mBadgeViewHelper.getBadgeRectF().height() / 2, mBadgeViewHelper.getBadgeRectF().height() / 2, mBadgePaint);
181 |
182 | // 设置徽章文本颜色
183 | mBadgePaint.setColor(mBadgeViewHelper.getBadgeTextColor());
184 | float x = mStartX + mBadgeViewHelper.getBadgeRectF().width() / 2;
185 | // 注意:绘制文本时的y是指文本底部,而不是文本的中间
186 | float y = mStartY + mBadgeViewHelper.getBadgeRectF().height() - mBadgeViewHelper.getBadgePadding();
187 | // 绘制徽章文本
188 | String badgeText = mBadgeViewHelper.getBadgeText() == null ? "" : mBadgeViewHelper.getBadgeText();
189 | canvas.drawText(badgeText, x, y, mBadgePaint);
190 | }
191 |
192 | private void drawStick(Canvas canvas) {
193 | float currentStickRadius = getCurrentStickRadius();
194 |
195 | // 2. 获取直线与圆的交点
196 | float yOffset = mStickCenter.y - mDragCenter.y;
197 | float xOffset = mStickCenter.x - mDragCenter.x;
198 | Double lineK = null;
199 | if (xOffset != 0) {
200 | lineK = (double) (yOffset / xOffset);
201 | }
202 | // 通过几何图形工具获取交点坐标
203 | mDragPoints = BGABadgeViewUtil.getIntersectionPoints(mDragCenter, mDragRadius, lineK);
204 | mStickPoints = BGABadgeViewUtil.getIntersectionPoints(mStickCenter, currentStickRadius, lineK);
205 |
206 | // 3. 获取控制点坐标
207 | mControlPoint = BGABadgeViewUtil.getMiddlePoint(mDragCenter, mStickCenter);
208 |
209 | if (!mIsDragDisappear) {
210 | if (!mDismissAble) {
211 |
212 | // 3. 画连接部分
213 | Path path = new Path();
214 | // 跳到点1
215 | path.moveTo(mStickPoints[0].x, mStickPoints[0].y);
216 | // 画曲线1 -> 2
217 | path.quadTo(mControlPoint.x, mControlPoint.y, mDragPoints[0].x, mDragPoints[0].y);
218 | // 画直线2 -> 3
219 | path.lineTo(mDragPoints[1].x, mDragPoints[1].y);
220 | // 画曲线3 -> 4
221 | path.quadTo(mControlPoint.x, mControlPoint.y, mStickPoints[1].x, mStickPoints[1].y);
222 | path.close();
223 | canvas.drawPath(path, mBadgePaint);
224 |
225 | // 2. 画固定圆
226 | canvas.drawCircle(mStickCenter.x, mStickCenter.y, currentStickRadius, mBadgePaint);
227 | }
228 |
229 | // 1. 画拖拽圆
230 | canvas.drawCircle(mDragCenter.x, mDragCenter.y, mDragRadius, mBadgePaint);
231 | }
232 | }
233 |
234 | /**
235 | * 获取针圆实时半径
236 | */
237 | private float getCurrentStickRadius() {
238 | /**
239 | * distance 0 -> mDismissThreshold
240 | * percent 0.0f -> 1.0f
241 | * currentStickRadius mStickRadius * 100% -> mStickRadius * 20%
242 | */
243 | float distance = BGABadgeViewUtil.getDistanceBetween2Points(mDragCenter, mStickCenter);
244 | distance = Math.min(distance, mDismissThreshold);
245 | float percent = distance / mDismissThreshold;
246 | return BGABadgeViewUtil.evaluate(percent, mStickRadius, mStickRadius * 0.2f);
247 | }
248 |
249 | public void setStickCenter(float x, float y) {
250 | mStickCenter = new PointF(x, y);
251 | }
252 |
253 | @Override
254 | public boolean onTouchEvent(MotionEvent event) {
255 | try {
256 | switch (event.getAction()) {
257 | case MotionEvent.ACTION_DOWN:
258 | handleActionDown(event);
259 | break;
260 | case MotionEvent.ACTION_MOVE:
261 | handleActionMove(event);
262 | break;
263 | case MotionEvent.ACTION_UP:
264 | case MotionEvent.ACTION_CANCEL:
265 | handleActionUp(event);
266 | break;
267 | }
268 | } catch (Exception e) {
269 | // 确保自己能被移除
270 | removeSelfWithException();
271 | }
272 | return true;
273 | }
274 |
275 | private void handleActionDown(MotionEvent event) {
276 | if (mExplosionAnimator == null && getParent() == null) {
277 | mDragRadius = Math.min(mBadgeViewHelper.getBadgeRectF().width() / 2, mMaxDragRadius);
278 | mStickRadius = mDragRadius - mDragStickRadiusDifference;
279 | mDismissThreshold = (int) (mStickRadius * 10);
280 |
281 | mDismissAble = false;
282 | mIsDragDisappear = false;
283 |
284 | mWindowManager.addView(this, mLayoutParams);
285 |
286 | updateDragPosition(event.getRawX(), event.getRawY());
287 | }
288 | }
289 |
290 | private void handleActionMove(MotionEvent event) {
291 | if (mExplosionAnimator == null && getParent() != null) {
292 | updateDragPosition(event.getRawX(), event.getRawY());
293 |
294 | // 处理断开事件
295 | if (BGABadgeViewUtil.getDistanceBetween2Points(mDragCenter, mStickCenter) > mDismissThreshold) {
296 | mDismissAble = true;
297 | postInvalidate();
298 | } else if (mBadgeViewHelper.isResumeTravel()) {
299 | mDismissAble = false;
300 | postInvalidate();
301 | }
302 | }
303 | }
304 |
305 | private void handleActionUp(MotionEvent event) {
306 | handleActionMove(event);
307 |
308 | if (mDismissAble) {
309 | // 拖拽点超出过范围
310 | if (BGABadgeViewUtil.getDistanceBetween2Points(mDragCenter, mStickCenter) > mDismissThreshold) {
311 | // 现在也超出范围,消失
312 | try {
313 | mIsDragDisappear = true;
314 | startDismissAnim(getNewStartX(event.getRawX()), getNewStartY(event.getRawY()));
315 | } catch (Exception e) {
316 | removeSelf();
317 | mBadgeViewHelper.endDragWithDismiss();
318 | }
319 | } else {
320 | // 现在没有超出范围,放回去
321 | removeSelf();
322 | mBadgeViewHelper.endDragWithoutDismiss();
323 | }
324 | } else {
325 | // 拖拽点没超出过范围,弹回去
326 | try {
327 | startSpringAnim();
328 | } catch (Exception e) {
329 | removeSelf();
330 | mBadgeViewHelper.endDragWithoutDismiss();
331 | }
332 | }
333 | }
334 |
335 | private void startSpringAnim() {
336 | final PointF startReleaseDragCenter = new PointF(mDragCenter.x, mDragCenter.y);
337 | ValueAnimator springAnim = ValueAnimator.ofFloat(1.0f);
338 | springAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
339 |
340 | @Override
341 | public void onAnimationUpdate(ValueAnimator mAnim) {
342 | // 0.0 -> 1.0f
343 | float percent = mAnim.getAnimatedFraction();
344 | PointF p = BGABadgeViewUtil.getPointByPercent(startReleaseDragCenter, mStickCenter, percent);
345 | updateDragPosition(p.x, p.y);
346 | }
347 | });
348 | springAnim.addListener(new AnimatorListenerAdapter() {
349 | @Override
350 | public void onAnimationEnd(Animator animation) {
351 | removeSelf();
352 | mBadgeViewHelper.endDragWithoutDismiss();
353 | }
354 |
355 | @Override
356 | public void onAnimationCancel(Animator animation) {
357 | removeSelf();
358 | mBadgeViewHelper.endDragWithoutDismiss();
359 | }
360 | });
361 |
362 | springAnim.setInterpolator(new OvershootInterpolator(4));
363 | springAnim.setRepeatCount(1);
364 | springAnim.setRepeatMode(ValueAnimator.INFINITE);
365 | springAnim.setDuration(BGAExplosionAnimator.ANIM_DURATION / 2);
366 | springAnim.start();
367 | }
368 |
369 | private void startDismissAnim(int newX, int newY) {
370 | int badgeWidth = (int) mBadgeViewHelper.getBadgeRectF().width();
371 | int badgeHeight = (int) mBadgeViewHelper.getBadgeRectF().height();
372 | Rect rect = new Rect(newX - badgeWidth / 2, newY - badgeHeight / 2, newX + badgeWidth / 2, newY + badgeHeight / 2);
373 |
374 | Bitmap badgeBitmap = BGABadgeViewUtil.createBitmapSafely(this, rect, 1);
375 | if (badgeBitmap == null) {
376 | removeSelf();
377 | mBadgeViewHelper.endDragWithDismiss();
378 | return;
379 | }
380 |
381 | if (mExplosionAnimator != null) {
382 | removeSelf();
383 | mBadgeViewHelper.endDragWithDismiss();
384 | return;
385 | }
386 |
387 | mExplosionAnimator = new BGAExplosionAnimator(this, rect, badgeBitmap);
388 | mExplosionAnimator.addListener(new AnimatorListenerAdapter() {
389 | @Override
390 | public void onAnimationEnd(Animator animation) {
391 | removeSelf();
392 | mBadgeViewHelper.endDragWithDismiss();
393 | }
394 |
395 | @Override
396 | public void onAnimationCancel(Animator animation) {
397 | removeSelf();
398 | mBadgeViewHelper.endDragWithDismiss();
399 | }
400 | });
401 | mExplosionAnimator.start();
402 | }
403 |
404 | private void removeSelf() {
405 | if (getParent() != null) {
406 | mWindowManager.removeView(this);
407 | }
408 | mDismissAble = false;
409 | mIsDragDisappear = false;
410 |
411 | // 处理有时候爆炸效果结束后出现一瞬间的拖拽效果
412 | postDelayed(mSetExplosionAnimatorNullTask, 60);
413 | }
414 |
415 | /**
416 | * 修改拖拽位置
417 | */
418 | private void updateDragPosition(float rawX, float rawY) {
419 | mStartX = getNewStartX(rawX);
420 | mStartY = getNewStartY(rawY);
421 |
422 | mDragCenter.set(rawX, rawY);
423 | postInvalidate();
424 | }
425 |
426 | private int getNewStartX(float rawX) {
427 | int badgeWidth = (int) mBadgeViewHelper.getBadgeRectF().width();
428 | int newX = (int) rawX - badgeWidth / 2;
429 | if (newX < 0) {
430 | newX = 0;
431 | }
432 | if (newX > mWindowManager.getDefaultDisplay().getWidth() - badgeWidth) {
433 | newX = mWindowManager.getDefaultDisplay().getWidth() - badgeWidth;
434 | }
435 | return newX;
436 | }
437 |
438 | private int getNewStartY(float rawY) {
439 | int badgeHeight = (int) mBadgeViewHelper.getBadgeRectF().height();
440 | int maxNewY = getHeight() - badgeHeight;
441 | int newStartY = (int) rawY - badgeHeight / 2;
442 | return Math.min(Math.max(0, newStartY), maxNewY);
443 | }
444 |
445 | private void removeSelfWithException() {
446 | removeSelf();
447 | if (BGABadgeViewUtil.getDistanceBetween2Points(mDragCenter, mStickCenter) > mDismissThreshold) {
448 | mBadgeViewHelper.endDragWithDismiss();
449 | } else {
450 | mBadgeViewHelper.endDragWithoutDismiss();
451 | }
452 | }
453 |
454 | private static class SetExplosionAnimatorNullTask implements Runnable {
455 | private final WeakReference mDragBadgeView;
456 |
457 | public SetExplosionAnimatorNullTask(BGADragBadgeView dragBadgeView) {
458 | mDragBadgeView = new WeakReference<>(dragBadgeView);
459 | }
460 |
461 | @Override
462 | public void run() {
463 | BGADragBadgeView dragBadgeView = mDragBadgeView.get();
464 | if (dragBadgeView != null) {
465 | dragBadgeView.mExplosionAnimator = null;
466 | }
467 | }
468 | }
469 | }
--------------------------------------------------------------------------------
/api/src/main/java/cn/bingoogolapple/badgeview/BGADragDismissDelegate.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2015 bingoogolapple
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package cn.bingoogolapple.badgeview;
18 |
19 | /**
20 | * 作者:王浩 邮件:bingoogolapple@gmail.com
21 | * 创建时间:15/7/12 下午6:33
22 | * 描述:拖动大于BGABadgeViewHelper.mMoveHiddenThreshold后抬起手指徽章消失的代理
23 | */
24 | public interface BGADragDismissDelegate {
25 |
26 | /**
27 | * 拖动大于BGABadgeViewHelper.mMoveHiddenThreshold后抬起手指徽章消失的回调方法
28 | *
29 | * @param badgeable
30 | */
31 | void onDismiss(BGABadgeable badgeable);
32 | }
--------------------------------------------------------------------------------
/api/src/main/java/cn/bingoogolapple/badgeview/BGAExplosionAnimator.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2015 bingoogolapple
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package cn.bingoogolapple.badgeview;
18 |
19 | import android.animation.ValueAnimator;
20 | import android.graphics.Bitmap;
21 | import android.graphics.Canvas;
22 | import android.graphics.Color;
23 | import android.graphics.Paint;
24 | import android.graphics.Rect;
25 | import android.view.animation.AccelerateInterpolator;
26 | import android.view.animation.Interpolator;
27 |
28 | import java.util.Random;
29 |
30 | /**
31 | * 作者:王浩 邮件:bingoogolapple@gmail.com
32 | * 创建时间:15/12/5 上午12:21
33 | * 描述:参考https://github.com/tyrantgit/ExplosionField改成了只有一个View的情况,只刷新徽章附近的区域
34 | */
35 | public class BGAExplosionAnimator extends ValueAnimator {
36 | public static final int ANIM_DURATION = 300;
37 | private static final Interpolator DEFAULT_INTERPOLATOR = new AccelerateInterpolator(0.6f);
38 | private static final float END_VALUE = 1.4f;
39 | private static final int REFRESH_RATIO = 3;
40 | private static float X;
41 | private static float Y;
42 | private static float V;
43 | private static float W;
44 |
45 | private Particle[] mParticles;
46 | private Paint mPaint;
47 | private BGADragBadgeView mDragBadgeView;
48 | private Rect mRect;
49 | private Rect mInvalidateRect;
50 |
51 | public BGAExplosionAnimator(BGADragBadgeView dragBadgeView, Rect rect, Bitmap bitmap) {
52 | setFloatValues(0.0f, END_VALUE);
53 | setDuration(ANIM_DURATION);
54 | setInterpolator(DEFAULT_INTERPOLATOR);
55 |
56 | X = BGABadgeViewUtil.dp2px(dragBadgeView.getContext(), 5);
57 | Y = BGABadgeViewUtil.dp2px(dragBadgeView.getContext(), 20);
58 | V = BGABadgeViewUtil.dp2px(dragBadgeView.getContext(), 2);
59 | W = BGABadgeViewUtil.dp2px(dragBadgeView.getContext(), 1);
60 |
61 | mPaint = new Paint();
62 | mDragBadgeView = dragBadgeView;
63 | mRect = rect;
64 | mInvalidateRect = new Rect(mRect.left - mRect.width() * REFRESH_RATIO, mRect.top - mRect.height() * REFRESH_RATIO, mRect.right + mRect.width() * REFRESH_RATIO, mRect.bottom + mRect.height() * REFRESH_RATIO);
65 |
66 | int partLen = 15;
67 | mParticles = new Particle[partLen * partLen];
68 | Random random = new Random(System.currentTimeMillis());
69 | int w = bitmap.getWidth() / (partLen + 2);
70 | int h = bitmap.getHeight() / (partLen + 2);
71 | for (int i = 0; i < partLen; i++) {
72 | for (int j = 0; j < partLen; j++) {
73 | mParticles[(i * partLen) + j] = generateParticle(bitmap.getPixel((j + 1) * w, (i + 1) * h), random);
74 | }
75 | }
76 | }
77 |
78 | private Particle generateParticle(int color, Random random) {
79 | Particle particle = new Particle();
80 | particle.color = color;
81 | particle.radius = V;
82 | if (random.nextFloat() < 0.2f) {
83 | particle.baseRadius = V + ((X - V) * random.nextFloat());
84 | } else {
85 | particle.baseRadius = W + ((V - W) * random.nextFloat());
86 | }
87 | float nextFloat = random.nextFloat();
88 | particle.top = mRect.height() * ((0.18f * random.nextFloat()) + 0.2f);
89 | particle.top = nextFloat < 0.2f ? particle.top : particle.top + ((particle.top * 0.2f) * random.nextFloat());
90 | particle.bottom = (mRect.height() * (random.nextFloat() - 0.5f)) * 1.8f;
91 | float f = nextFloat < 0.2f ? particle.bottom : nextFloat < 0.8f ? particle.bottom * 0.6f : particle.bottom * 0.3f;
92 | particle.bottom = f;
93 | particle.mag = 4.0f * particle.top / particle.bottom;
94 | particle.neg = (-particle.mag) / particle.bottom;
95 | f = mRect.centerX() + (Y * (random.nextFloat() - 0.5f));
96 | particle.baseCx = f + mRect.width() / 2;
97 | particle.cx = particle.baseCx;
98 | f = mRect.centerY() + (Y * (random.nextFloat() - 0.5f));
99 | particle.baseCy = f;
100 | particle.cy = f;
101 | particle.life = END_VALUE / 10 * random.nextFloat();
102 | particle.overflow = 0.4f * random.nextFloat();
103 | particle.alpha = 1f;
104 | return particle;
105 | }
106 |
107 | public void draw(Canvas canvas) {
108 | if (!isStarted()) {
109 | return;
110 | }
111 | for (Particle particle : mParticles) {
112 | particle.advance((float) getAnimatedValue());
113 | if (particle.alpha > 0f) {
114 | mPaint.setColor(particle.color);
115 | mPaint.setAlpha((int) (Color.alpha(particle.color) * particle.alpha));
116 | canvas.drawCircle(particle.cx, particle.cy, particle.radius, mPaint);
117 | }
118 | }
119 | postInvalidate();
120 | }
121 |
122 | @Override
123 | public void start() {
124 | super.start();
125 | postInvalidate();
126 | }
127 |
128 | /**
129 | * 只刷新徽章附近的区域
130 | */
131 | private void postInvalidate() {
132 | mDragBadgeView.postInvalidate(mInvalidateRect.left, mInvalidateRect.top, mInvalidateRect.right, mInvalidateRect.bottom);
133 | }
134 |
135 | private class Particle {
136 | float alpha;
137 | int color;
138 | float cx;
139 | float cy;
140 | float radius;
141 | float baseCx;
142 | float baseCy;
143 | float baseRadius;
144 | float top;
145 | float bottom;
146 | float mag;
147 | float neg;
148 | float life;
149 | float overflow;
150 |
151 | public void advance(float factor) {
152 | float f = 0f;
153 | float normalization = factor / END_VALUE;
154 | if (normalization < life || normalization > 1f - overflow) {
155 | alpha = 0f;
156 | return;
157 | }
158 | normalization = (normalization - life) / (1f - life - overflow);
159 | float f2 = normalization * END_VALUE;
160 | if (normalization >= 0.7f) {
161 | f = (normalization - 0.7f) / 0.3f;
162 | }
163 | alpha = 1f - f;
164 | f = bottom * f2;
165 | cx = baseCx + f;
166 | cy = (float) (baseCy - this.neg * Math.pow(f, 2.0)) - f * mag;
167 | radius = V + (baseRadius - V) * f2;
168 | }
169 | }
170 | }
--------------------------------------------------------------------------------
/api/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | google()
7 | }
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:3.1.2'
10 | classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
11 | }
12 | }
13 |
14 | allprojects {
15 | repositories {
16 | maven { url 'https://jitpack.io' }
17 | jcenter()
18 | google()
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/compiler/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java-library'
2 | apply plugin: 'maven'
3 |
4 | dependencies {
5 | implementation project(':annotation')
6 |
7 | compileOnly 'com.google.auto.service:auto-service:1.0-rc4'
8 | implementation 'com.google.auto:auto-common:0.10'
9 | implementation 'com.squareup:javapoet:1.9.0'
10 | }
11 |
12 | sourceCompatibility = JavaVersion.VERSION_1_7
13 | targetCompatibility = JavaVersion.VERSION_1_7
14 |
--------------------------------------------------------------------------------
/compiler/src/main/java/cn/bingoogolapple/badgeview/compiler/BGABadgeProcessor.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2018 bingoogolapple
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package cn.bingoogolapple.badgeview.compiler;
18 |
19 | import com.google.auto.service.AutoService;
20 | import com.squareup.javapoet.ClassName;
21 | import com.squareup.javapoet.JavaFile;
22 | import com.squareup.javapoet.MethodSpec;
23 | import com.squareup.javapoet.TypeName;
24 | import com.squareup.javapoet.TypeSpec;
25 |
26 | import java.io.IOException;
27 | import java.util.HashSet;
28 | import java.util.LinkedHashSet;
29 | import java.util.List;
30 | import java.util.Set;
31 |
32 | import javax.annotation.processing.AbstractProcessor;
33 | import javax.annotation.processing.Filer;
34 | import javax.annotation.processing.Messager;
35 | import javax.annotation.processing.ProcessingEnvironment;
36 | import javax.annotation.processing.Processor;
37 | import javax.annotation.processing.RoundEnvironment;
38 | import javax.lang.model.SourceVersion;
39 | import javax.lang.model.element.Element;
40 | import javax.lang.model.element.ElementKind;
41 | import javax.lang.model.element.Modifier;
42 | import javax.lang.model.element.TypeElement;
43 | import javax.lang.model.type.DeclaredType;
44 | import javax.lang.model.type.MirroredTypesException;
45 | import javax.lang.model.type.TypeMirror;
46 | import javax.lang.model.util.Elements;
47 | import javax.tools.Diagnostic;
48 |
49 | import cn.bingoogolapple.badgeview.annotation.BGABadge;
50 |
51 | /**
52 | * 作者:王浩 邮件:bingoogolapple@gmail.com
53 | * 创建时间:2018/1/14
54 | * 描述:
55 | */
56 | @SuppressWarnings("unused")
57 | @AutoService(Processor.class)
58 | public class BGABadgeProcessor extends AbstractProcessor {
59 | private static final String CLASS_JAVA_DOC = "Generated by BGABadgeView-Android. Do not edit it!\n";
60 | private static final String PACKAGE_NAME = "cn.bingoogolapple.badgeview";
61 | private static final String CLASS_PREFIX = "BGABadge";
62 | private Filer mFileUtils;
63 | private Elements mElementUtils;
64 | private Messager mMessager;
65 |
66 | @Override
67 | public synchronized void init(ProcessingEnvironment processingEnvironment) {
68 | super.init(processingEnvironment);
69 | mFileUtils = processingEnv.getFiler();
70 | mElementUtils = processingEnv.getElementUtils();
71 | mMessager = processingEnv.getMessager();
72 | }
73 |
74 | @Override
75 | public SourceVersion getSupportedSourceVersion() {
76 | return SourceVersion.latestSupported();
77 | }
78 |
79 | /**
80 | * 告知 Processor 哪些注解需要处理
81 | *
82 | * @return 返回一个 Set 集合,集合内容为自定义注解的包名+类名
83 | */
84 | @Override
85 | public Set getSupportedAnnotationTypes() {
86 | final Set annotationTypes = new LinkedHashSet<>();
87 | annotationTypes.add(BGABadge.class.getCanonicalName());
88 | return annotationTypes;
89 | }
90 |
91 | /**
92 | * 所有的注解处理都是从这个方法开始的,当 APT 找到所有需要处理的注解后,会回调这个方法。当没有属于该 Processor 处理的注解被使用时,不会回调该方法
93 | *
94 | * @param set 所有的由该 Processor 处理,并待处理的 Annotations「属于该 Processor 处理的注解,但并未被使用,不存在与这个集合里」
95 | * @param roundEnvironment 表示当前或是之前的运行环境,可以通过该对象查找到注解
96 | * @return 表示这组 Annotation 是否被这个 Processor 消费,如果消费「返回 true」后续子的 Processor 不会再对这组 Annotation 进行处理
97 | */
98 | @Override
99 | public boolean process(Set extends TypeElement> set, RoundEnvironment roundEnvironment) {
100 | Set extends Element> elements = roundEnvironment.getElementsAnnotatedWith(BGABadge.class);
101 | if (elements == null || elements.isEmpty()) {
102 | return true;
103 | }
104 | mMessager.printMessage(Diagnostic.Kind.NOTE,
105 | "====================================== BGABadgeProcessor process START ======================================");
106 | Set viewClassSet = new HashSet<>();
107 | parseParams(elements, viewClassSet);
108 | try {
109 | generate(viewClassSet);
110 | } catch (IllegalAccessException e) {
111 | e.printStackTrace();
112 | } catch (IOException e) {
113 | mMessager.printMessage(Diagnostic.Kind.ERROR, "Exception occurred when generating class file.");
114 | e.printStackTrace();
115 | }
116 | mMessager.printMessage(Diagnostic.Kind.NOTE,
117 | "====================================== BGABadgeProcessor process END ======================================");
118 | return true;
119 | }
120 |
121 | private void parseParams(Set extends Element> elements, Set viewClassSet) {
122 | for (Element element : elements) {
123 | checkAnnotationValid(element, BGABadge.class);
124 | TypeElement classElement = (TypeElement) element;
125 | // 获取该注解的值
126 | BGABadge badgeAnnotation = classElement.getAnnotation(BGABadge.class);
127 | try {
128 | badgeAnnotation.value();
129 | } catch (MirroredTypesException e) {
130 | List extends TypeMirror> typeMirrors = e.getTypeMirrors();
131 | for (TypeMirror typeMirror : typeMirrors) {
132 | DeclaredType classTypeMirror = (DeclaredType) typeMirror;
133 | TypeElement classTypeElement = (TypeElement) classTypeMirror.asElement();
134 | String qualifiedName = classTypeElement.getQualifiedName().toString();
135 |
136 | viewClassSet.add(qualifiedName);
137 | }
138 | }
139 | }
140 | }
141 |
142 | private void generate(Set viewClassSet) throws IllegalAccessException, IOException {
143 | mMessager.printMessage(Diagnostic.Kind.NOTE, "生成 " + viewClassSet.size() + " 个");
144 | for (String clazz : viewClassSet) {
145 | int lastDotIndex = clazz.lastIndexOf(".");
146 | String superPackageName = clazz.substring(0, lastDotIndex);
147 | String superClassName = clazz.substring(lastDotIndex + 1);
148 | String className = CLASS_PREFIX + superClassName;
149 |
150 | mMessager.printMessage(Diagnostic.Kind.NOTE, clazz + " ====> " + className);
151 |
152 | TypeSpec.Builder typeBuilder = TypeSpec.classBuilder(className)
153 | .addJavadoc(CLASS_JAVA_DOC)
154 | .addModifiers(Modifier.PUBLIC)
155 | .superclass(ClassName.get(superPackageName, superClassName))
156 | .addSuperinterface(ClassName.get(PACKAGE_NAME, "BGABadgeable"))
157 | .addField(ClassName.get(PACKAGE_NAME, "BGABadgeViewHelper"), "mBadgeViewHelper", Modifier.PRIVATE);
158 |
159 | generateMethod(typeBuilder, clazz);
160 |
161 | JavaFile javaFile = JavaFile.builder(PACKAGE_NAME, typeBuilder.build()).build();
162 | javaFile.writeTo(mFileUtils);
163 | }
164 | }
165 |
166 | private void generateMethod(TypeSpec.Builder typeBuilder, String clazz) {
167 | constructor(typeBuilder, clazz);
168 | onTouchEvent(typeBuilder);
169 | callSuperOnTouchEvent(typeBuilder);
170 | if (isAssignable(clazz, "android.view.ViewGroup")) {
171 | dispatchDraw(typeBuilder);
172 | } else {
173 | onDraw(typeBuilder);
174 | }
175 | showCirclePointBadge(typeBuilder);
176 | showTextBadge(typeBuilder);
177 | hiddenBadge(typeBuilder);
178 | showDrawableBadge(typeBuilder);
179 | setDragDismissDelegate(typeBuilder);
180 | isShowBadge(typeBuilder);
181 | isDraggable(typeBuilder);
182 | isDragging(typeBuilder);
183 | getBadgeViewHelper(typeBuilder);
184 | }
185 |
186 | private void constructor(TypeSpec.Builder typeBuilder, String clazz) {
187 | TypeName contextType = ClassName.get("android.content", "Context");
188 | TypeName attributeSetType = ClassName.get("android.util", "AttributeSet");
189 | MethodSpec constructorOne = MethodSpec.constructorBuilder()
190 | .addModifiers(Modifier.PUBLIC)
191 | .addParameter(contextType, "context")
192 | .addStatement("this(context, null)")
193 | .build();
194 | MethodSpec constructorTwo = MethodSpec.constructorBuilder()
195 | .addModifiers(Modifier.PUBLIC)
196 | .addParameter(contextType, "context")
197 | .addParameter(attributeSetType, "attrs")
198 | .addStatement("this(context, attrs, 0)")
199 | .build();
200 | MethodSpec.Builder constructorThreeBuilder = MethodSpec.constructorBuilder()
201 | .addModifiers(Modifier.PUBLIC)
202 | .addParameter(contextType, "context")
203 | .addParameter(attributeSetType, "attrs")
204 | .addParameter(int.class, "defStyleAttr")
205 | .addStatement("super(context, attrs, defStyleAttr)");
206 | if (isAssignable(clazz, "android.widget.ImageView") || isAssignable(clazz, "android.widget.RadioButton")) {
207 | constructorThreeBuilder.addStatement("mBadgeViewHelper = new BGABadgeViewHelper(this, context, attrs, BGABadgeViewHelper.BadgeGravity.RightTop)");
208 | } else {
209 | constructorThreeBuilder.addStatement(
210 | "mBadgeViewHelper = new BGABadgeViewHelper(this, context, attrs, BGABadgeViewHelper.BadgeGravity.RightCenter)");
211 | }
212 |
213 | typeBuilder.addMethod(constructorOne)
214 | .addMethod(constructorTwo)
215 | .addMethod(constructorThreeBuilder.build());
216 | }
217 |
218 | private void onTouchEvent(TypeSpec.Builder typeBuilder) {
219 | MethodSpec methodSpec = MethodSpec.methodBuilder("onTouchEvent")
220 | .addAnnotation(Override.class)
221 | .addModifiers(Modifier.PUBLIC)
222 | .addParameter(ClassName.get("android.view", "MotionEvent"), "event")
223 | .addStatement("return mBadgeViewHelper.onTouchEvent(event)")
224 | .returns(boolean.class)
225 | .build();
226 | typeBuilder.addMethod(methodSpec);
227 | }
228 |
229 | private void callSuperOnTouchEvent(TypeSpec.Builder typeBuilder) {
230 | MethodSpec methodSpec = MethodSpec.methodBuilder("callSuperOnTouchEvent")
231 | .addAnnotation(Override.class)
232 | .addModifiers(Modifier.PUBLIC)
233 | .addParameter(ClassName.get("android.view", "MotionEvent"), "event")
234 | .addStatement("return super.onTouchEvent(event)")
235 | .returns(boolean.class)
236 | .build();
237 | typeBuilder.addMethod(methodSpec);
238 | }
239 |
240 | private void onDraw(TypeSpec.Builder typeBuilder) {
241 | MethodSpec methodSpec = MethodSpec.methodBuilder("onDraw")
242 | .addAnnotation(Override.class)
243 | .addModifiers(Modifier.PUBLIC)
244 | .addParameter(ClassName.get("android.graphics", "Canvas"), "canvas")
245 | .addStatement("super.onDraw(canvas)")
246 | .addStatement("mBadgeViewHelper.drawBadge(canvas)")
247 | .build();
248 | typeBuilder.addMethod(methodSpec);
249 | }
250 |
251 | private void dispatchDraw(TypeSpec.Builder typeBuilder) {
252 | MethodSpec methodSpec = MethodSpec.methodBuilder("dispatchDraw")
253 | .addAnnotation(Override.class)
254 | .addModifiers(Modifier.PUBLIC)
255 | .addParameter(ClassName.get("android.graphics", "Canvas"), "canvas")
256 | .addStatement("super.dispatchDraw(canvas)")
257 | .addStatement("mBadgeViewHelper.drawBadge(canvas)")
258 | .build();
259 | typeBuilder.addMethod(methodSpec);
260 | }
261 |
262 | private void showCirclePointBadge(TypeSpec.Builder typeBuilder) {
263 | MethodSpec methodSpec = MethodSpec.methodBuilder("showCirclePointBadge")
264 | .addAnnotation(Override.class)
265 | .addModifiers(Modifier.PUBLIC)
266 | .addStatement("mBadgeViewHelper.showCirclePointBadge()")
267 | .build();
268 | typeBuilder.addMethod(methodSpec);
269 | }
270 |
271 | private void showTextBadge(TypeSpec.Builder typeBuilder) {
272 | MethodSpec methodSpec = MethodSpec.methodBuilder("showTextBadge")
273 | .addAnnotation(Override.class)
274 | .addModifiers(Modifier.PUBLIC)
275 | .addParameter(String.class, "badgeText")
276 | .addStatement("mBadgeViewHelper.showTextBadge(badgeText)")
277 | .build();
278 | typeBuilder.addMethod(methodSpec);
279 | }
280 |
281 | private void hiddenBadge(TypeSpec.Builder typeBuilder) {
282 | MethodSpec methodSpec = MethodSpec.methodBuilder("hiddenBadge")
283 | .addAnnotation(Override.class)
284 | .addModifiers(Modifier.PUBLIC)
285 | .addStatement("mBadgeViewHelper.hiddenBadge()")
286 | .build();
287 | typeBuilder.addMethod(methodSpec);
288 | }
289 |
290 | private void showDrawableBadge(TypeSpec.Builder typeBuilder) {
291 | MethodSpec methodSpec = MethodSpec.methodBuilder("showDrawableBadge")
292 | .addAnnotation(Override.class)
293 | .addModifiers(Modifier.PUBLIC)
294 | .addParameter(ClassName.get("android.graphics", "Bitmap"), "bitmap")
295 | .addStatement("mBadgeViewHelper.showDrawable(bitmap)")
296 | .build();
297 | typeBuilder.addMethod(methodSpec);
298 | }
299 |
300 | private void setDragDismissDelegate(TypeSpec.Builder typeBuilder) {
301 | MethodSpec methodSpec = MethodSpec.methodBuilder("setDragDismissDelegate")
302 | .addAnnotation(Override.class)
303 | .addModifiers(Modifier.PUBLIC)
304 | .addParameter(ClassName.get(PACKAGE_NAME, "BGADragDismissDelegate"), "delegate")
305 | .addStatement("mBadgeViewHelper.setDragDismissDelegate(delegate)")
306 | .build();
307 | typeBuilder.addMethod(methodSpec);
308 | }
309 |
310 | private void isShowBadge(TypeSpec.Builder typeBuilder) {
311 | MethodSpec methodSpec = MethodSpec.methodBuilder("isShowBadge")
312 | .addAnnotation(Override.class)
313 | .addModifiers(Modifier.PUBLIC)
314 | .addStatement("return mBadgeViewHelper.isShowBadge()")
315 | .returns(boolean.class)
316 | .build();
317 | typeBuilder.addMethod(methodSpec);
318 | }
319 |
320 | private void isDraggable(TypeSpec.Builder typeBuilder) {
321 | MethodSpec methodSpec = MethodSpec.methodBuilder("isDraggable")
322 | .addAnnotation(Override.class)
323 | .addModifiers(Modifier.PUBLIC)
324 | .addStatement("return mBadgeViewHelper.isDraggable()")
325 | .returns(boolean.class)
326 | .build();
327 | typeBuilder.addMethod(methodSpec);
328 | }
329 |
330 | private void isDragging(TypeSpec.Builder typeBuilder) {
331 | MethodSpec methodSpec = MethodSpec.methodBuilder("isDragging")
332 | .addAnnotation(Override.class)
333 | .addModifiers(Modifier.PUBLIC)
334 | .addStatement("return mBadgeViewHelper.isDragging()")
335 | .returns(boolean.class)
336 | .build();
337 | typeBuilder.addMethod(methodSpec);
338 | }
339 |
340 | private void getBadgeViewHelper(TypeSpec.Builder typeBuilder) {
341 | MethodSpec methodSpec = MethodSpec.methodBuilder("getBadgeViewHelper")
342 | .addAnnotation(Override.class)
343 | .addModifiers(Modifier.PUBLIC)
344 | .addStatement("return mBadgeViewHelper")
345 | .returns(ClassName.get(PACKAGE_NAME, "BGABadgeViewHelper"))
346 | .build();
347 | typeBuilder.addMethod(methodSpec);
348 | }
349 |
350 | private boolean checkAnnotationValid(Element annotatedElement, Class clazz) {
351 | if (annotatedElement.getKind() != ElementKind.CLASS) {
352 | error(annotatedElement, "%s must be declared on class.", clazz.getSimpleName());
353 | return false;
354 | }
355 |
356 | if (annotatedElement.getModifiers().contains(Modifier.PRIVATE)) {
357 | error(annotatedElement, "%s must can not be private.", ((TypeElement) annotatedElement).getQualifiedName());
358 | return false;
359 | }
360 | return true;
361 | }
362 |
363 | private void error(Element element, String message, Object... args) {
364 | if (args.length > 0) {
365 | message = String.format(message, args);
366 | }
367 | mMessager.printMessage(Diagnostic.Kind.ERROR, message, element);
368 | }
369 |
370 | private boolean isAssignable(String childClazz, String superClazz) {
371 | return processingEnv.getTypeUtils().isAssignable(
372 | processingEnv.getElementUtils().getTypeElement(childClazz).asType(),
373 | processingEnv.getElementUtils().getTypeElement(superClazz).asType());
374 |
375 | }
376 | }
377 |
--------------------------------------------------------------------------------
/demo/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion ANDROID_BUILD_SDK_VERSION as int
5 |
6 | defaultConfig {
7 | minSdkVersion ANDROID_BUILD_MIN_SDK_VERSION as int
8 | targetSdkVersion ANDROID_BUILD_TARGET_SDK_VERSION as int
9 | versionCode VERSION_CODE as int
10 | versionName VERSION_NAME
11 | }
12 |
13 | buildTypes {
14 | release {
15 | minifyEnabled true
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | }
20 |
21 | dependencies {
22 |
23 | implementation project(':api')
24 | annotationProcessor project(':compiler')
25 |
26 | // -------------------- 以下一个库是必须依赖的 ----------------------------
27 | // implementation 'com.github.bingoogolapple.BGABadgeView-Android:api:1.2.0'
28 | // annotationProcessor "com.github.bingoogolapple.BGABadgeView-Android:compiler:1.2.0"
29 | // -------------------- 以上一个库是必须依赖的 ----------------------------
30 |
31 | // 以下几个库是演示案例所使用到的
32 | implementation 'com.android.support:design:27.0.2'
33 | implementation 'com.android.support:recyclerview-v7:27.0.2'
34 | implementation 'cn.bingoogolapple:bga-baseadapter:1.2.9'
35 | }
--------------------------------------------------------------------------------
/demo/proguard-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bingoogolapple/BGABadgeView-Android/d69ee719c0c418c35e7936b5e6621c0193198748/demo/proguard-rules.pro
--------------------------------------------------------------------------------
/demo/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
12 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/demo/src/main/java/cn/bingoogolapple/badgeview/demo/activity/MainActivity.java:
--------------------------------------------------------------------------------
1 | package cn.bingoogolapple.badgeview.demo.activity;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.BitmapFactory;
5 | import android.graphics.Color;
6 | import android.os.Bundle;
7 | import android.os.Handler;
8 | import android.support.v4.graphics.drawable.RoundedBitmapDrawable;
9 | import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory;
10 | import android.support.v7.app.AppCompatActivity;
11 | import android.support.v7.widget.LinearLayoutManager;
12 | import android.support.v7.widget.RecyclerView;
13 | import android.view.View;
14 | import android.view.ViewGroup;
15 | import android.widget.RadioGroup;
16 |
17 | import cn.bingoogolapple.badgeview.BGABadgeFloatingActionButton;
18 | import cn.bingoogolapple.badgeview.BGABadgeFrameLayout;
19 | import cn.bingoogolapple.badgeview.BGABadgeImageView;
20 | import cn.bingoogolapple.badgeview.BGABadgeLinearLayout;
21 | import cn.bingoogolapple.badgeview.BGABadgeRadioButton;
22 | import cn.bingoogolapple.badgeview.BGABadgeRelativeLayout;
23 | import cn.bingoogolapple.badgeview.BGABadgeTextView;
24 | import cn.bingoogolapple.badgeview.BGABadgeView;
25 | import cn.bingoogolapple.badgeview.BGABadgeable;
26 | import cn.bingoogolapple.badgeview.BGADragDismissDelegate;
27 | import cn.bingoogolapple.badgeview.demo.R;
28 | import cn.bingoogolapple.badgeview.demo.adapter.MessageAdapter;
29 | import cn.bingoogolapple.badgeview.demo.model.MessageModel;
30 | import cn.bingoogolapple.badgeview.demo.util.ToastUtil;
31 | import cn.bingoogolapple.baseadapter.BGAOnRVItemClickListener;
32 |
33 | public class MainActivity extends AppCompatActivity {
34 | private BGABadgeView mTestBv;
35 |
36 | private BGABadgeTextView mTestBtv;
37 |
38 | private BGABadgeImageView mNormalBiv;
39 | private BGABadgeImageView mRoundedBiv;
40 | private BGABadgeImageView mCircleBiv;
41 |
42 | private BGABadgeLinearLayout mTestBll;
43 | private BGABadgeRelativeLayout mTestBrl;
44 | private BGABadgeFrameLayout mTestBfl;
45 |
46 | private RecyclerView mRecyclerView;
47 | private MessageAdapter mMessageAdapter;
48 |
49 |
50 | private RadioGroup mTabRg;
51 | private BGABadgeRadioButton mHomeBrb;
52 | private BGABadgeRadioButton mMessageBrb;
53 | private BGABadgeRadioButton mDiscoverBrb;
54 | private BGABadgeRadioButton mMeBrb;
55 |
56 | private BGABadgeFloatingActionButton mChatBfab;
57 |
58 | @Override
59 | protected void onCreate(Bundle savedInstanceState) {
60 | super.onCreate(savedInstanceState);
61 | setContentView(R.layout.activity_main);
62 | ToastUtil.init(this);
63 |
64 | initView();
65 | testBadgeView();
66 | testRadioButton();
67 | testRecyclerView();
68 | }
69 |
70 | private void initView() {
71 | mTestBv = findViewById(R.id.bv_main_test);
72 |
73 | mTestBtv = findViewById(R.id.btv_main_test);
74 |
75 | mNormalBiv = findViewById(R.id.biv_main_normal);
76 | mRoundedBiv = findViewById(R.id.biv_main_rounded);
77 | mCircleBiv = findViewById(R.id.biv_main_circle);
78 |
79 | mTestBll = findViewById(R.id.bll_main_test);
80 | mTestBrl = findViewById(R.id.brl_main_test);
81 | mTestBfl = findViewById(R.id.bfl_main_test);
82 |
83 | mRecyclerView = findViewById(R.id.recyclerview);
84 |
85 | mTabRg = findViewById(R.id.rg_main_tab);
86 | mHomeBrb = findViewById(R.id.brb_main_home);
87 | mMessageBrb = findViewById(R.id.brb_main_message);
88 | mDiscoverBrb = findViewById(R.id.brb_main_discover);
89 | mMeBrb = findViewById(R.id.brb_main_me);
90 |
91 | mChatBfab = findViewById(R.id.bfab_main_chat);
92 | }
93 |
94 | private void testBadgeView() {
95 | mTestBv.showTextBadge("9");
96 | mTestBv.getBadgeViewHelper().setBadgeTextSizeSp(15);
97 | mTestBv.getBadgeViewHelper().setBadgePaddingDp(8);
98 | mTestBv.getBadgeViewHelper().setBadgeTextColorInt(Color.parseColor("#FF0000"));
99 | mTestBv.getBadgeViewHelper().setBadgeBgColorInt(Color.parseColor("#00FF00"));
100 | mTestBv.getBadgeViewHelper().setDraggable(true);
101 | mTestBv.getBadgeViewHelper().setBadgePaddingDp(7);
102 | mTestBv.getBadgeViewHelper().setBadgeBorderWidthDp(2);
103 | mTestBv.getBadgeViewHelper().setBadgeBorderColorInt(Color.parseColor("#0000FF"));
104 |
105 | mTestBtv.showCirclePointBadge();
106 |
107 | mNormalBiv.showCirclePointBadge();
108 |
109 | Bitmap avatarBadgeBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.avatar_vip);
110 |
111 | RoundedBitmapDrawable roundedDrawable = RoundedBitmapDrawableFactory.create(getResources(),
112 | BitmapFactory.decodeResource(getResources(), R.mipmap.avator));
113 | roundedDrawable.getPaint().setAntiAlias(true);
114 | roundedDrawable.setCornerRadius(30);
115 | mRoundedBiv.setImageDrawable(roundedDrawable);
116 | mRoundedBiv.showDrawableBadge(avatarBadgeBitmap);
117 |
118 | Bitmap avatarBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.avator);
119 | RoundedBitmapDrawable circleDrawable = RoundedBitmapDrawableFactory.create(getResources(), avatarBitmap);
120 | circleDrawable.getPaint().setAntiAlias(true);
121 | circleDrawable.setCornerRadius(Math.max(avatarBitmap.getWidth(), avatarBitmap.getHeight()) / 2.0f);
122 | mCircleBiv.setImageDrawable(circleDrawable);
123 | mCircleBiv.showDrawableBadge(avatarBadgeBitmap);
124 |
125 | mTestBll.showDrawableBadge(avatarBadgeBitmap);
126 | mTestBrl.showTextBadge("LoveAndroid");
127 | mTestBfl.showTextBadge("8");
128 |
129 | mChatBfab.showTextBadge("8");
130 | mChatBfab.setDragDismissDelegate(new BGADragDismissDelegate() {
131 | @Override
132 | public void onDismiss(BGABadgeable badgeable) {
133 | ToastUtil.show("清空聊天消息");
134 | }
135 | });
136 |
137 | new Handler().postDelayed(new Runnable() {
138 | @Override
139 | public void run() {
140 | mRoundedBiv.hiddenBadge();
141 | }
142 | }, 3000);
143 |
144 | new Handler().postDelayed(new Runnable() {
145 | @Override
146 | public void run() {
147 | mRoundedBiv.showCirclePointBadge();
148 | }
149 | }, 6000);
150 |
151 | new Handler().postDelayed(new Runnable() {
152 | @Override
153 | public void run() {
154 | mRoundedBiv.showDrawableBadge(BitmapFactory.decodeResource(getResources(), R.mipmap.avatar_vip));
155 | }
156 | }, 9000);
157 | }
158 |
159 | private void testRadioButton() {
160 | mHomeBrb.showTextBadge("10");
161 | mMessageBrb.showTextBadge("1");
162 | mDiscoverBrb.showTextBadge("...");
163 | mMeBrb.showDrawableBadge(BitmapFactory.decodeResource(getResources(), R.mipmap.avatar_vip));
164 | new Handler().postDelayed(new Runnable() {
165 | @Override
166 | public void run() {
167 | mHomeBrb.showTextBadge("1");
168 | }
169 | }, 5000);
170 |
171 | mHomeBrb.setDragDismissDelegate(new BGADragDismissDelegate() {
172 | @Override
173 | public void onDismiss(BGABadgeable badgeable) {
174 | ToastUtil.show("消息单选按钮徽章拖动消失");
175 | }
176 | });
177 |
178 | mTabRg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
179 | @Override
180 | public void onCheckedChanged(RadioGroup group, int checkedId) {
181 | switch (checkedId) {
182 | case R.id.brb_main_home:
183 | ToastUtil.show("首页");
184 | break;
185 | case R.id.brb_main_message:
186 | ToastUtil.show("消息");
187 | break;
188 | case R.id.brb_main_discover:
189 | ToastUtil.show("发现");
190 | break;
191 | case R.id.brb_main_me:
192 | ToastUtil.show("我");
193 | break;
194 | }
195 | }
196 | });
197 | }
198 |
199 | private void testRecyclerView() {
200 | mRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
201 | mMessageAdapter = new MessageAdapter(mRecyclerView);
202 | mMessageAdapter.setOnRVItemClickListener(new BGAOnRVItemClickListener() {
203 | @Override
204 | public void onRVItemClick(ViewGroup viewGroup, View view, int position) {
205 | ToastUtil.show("点击了条目 " + mMessageAdapter.getItem(position).title);
206 | }
207 | });
208 | mRecyclerView.setAdapter(mMessageAdapter);
209 | mMessageAdapter.setData(MessageModel.getTestData());
210 | }
211 | }
--------------------------------------------------------------------------------
/demo/src/main/java/cn/bingoogolapple/badgeview/demo/adapter/MessageAdapter.java:
--------------------------------------------------------------------------------
1 | package cn.bingoogolapple.badgeview.demo.adapter;
2 |
3 | import android.support.v7.widget.RecyclerView;
4 |
5 | import cn.bingoogolapple.baseadapter.BGARecyclerViewAdapter;
6 | import cn.bingoogolapple.baseadapter.BGAViewHolderHelper;
7 | import cn.bingoogolapple.badgeview.BGABadgeLinearLayout;
8 | import cn.bingoogolapple.badgeview.BGABadgeable;
9 | import cn.bingoogolapple.badgeview.BGADragDismissDelegate;
10 | import cn.bingoogolapple.badgeview.demo.R;
11 | import cn.bingoogolapple.badgeview.demo.model.MessageModel;
12 | import cn.bingoogolapple.badgeview.demo.util.ToastUtil;
13 |
14 | /**
15 | * 作者:王浩 邮件:bingoogolapple@gmail.com
16 | * 创建时间:15/7/12 上午11:39
17 | * 描述:
18 | */
19 | public class MessageAdapter extends BGARecyclerViewAdapter {
20 | public MessageAdapter(RecyclerView recyclerView) {
21 | super(recyclerView, R.layout.item_message);
22 | }
23 |
24 | @Override
25 | protected void fillData(BGAViewHolderHelper holderHelper, final int position, final MessageModel message) {
26 | holderHelper.setText(R.id.tv_item_message_title, message.title);
27 | holderHelper.setText(R.id.tv_item_message_detail, message.detail);
28 |
29 | BGABadgeLinearLayout rootView = (BGABadgeLinearLayout) holderHelper.getConvertView();
30 | if (message.newMsgCount > 0) {
31 | rootView.showTextBadge("" + message.newMsgCount);
32 | rootView.setDragDismissDelegate(new BGADragDismissDelegate() {
33 | @Override
34 | public void onDismiss(BGABadgeable badgeable) {
35 | message.newMsgCount = 0;
36 | ToastUtil.show(message.title + "的徽章消失");
37 | }
38 | });
39 | } else {
40 | rootView.hiddenBadge();
41 | }
42 | }
43 | }
--------------------------------------------------------------------------------
/demo/src/main/java/cn/bingoogolapple/badgeview/demo/model/MessageModel.java:
--------------------------------------------------------------------------------
1 | package cn.bingoogolapple.badgeview.demo.model;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 | import java.util.Random;
6 |
7 | /**
8 | * 作者:王浩 邮件:bingoogolapple@gmail.com
9 | * 创建时间:15/7/12 上午11:33
10 | * 描述:
11 | */
12 | public class MessageModel {
13 | public String title;
14 | public String detail;
15 | public int newMsgCount;
16 |
17 | public MessageModel(String title, String detail, int newMsgCount) {
18 | this.title = title;
19 | this.detail = detail;
20 | this.newMsgCount = newMsgCount;
21 | }
22 |
23 | public static List getTestData() {
24 | List messages = new ArrayList<>();
25 | Random random = new Random();
26 | for (int i = 0; i < 30; i++) {
27 | messages.add(new MessageModel("title" + i, "detail" + i, random.nextInt(150)));
28 | }
29 | return messages;
30 | }
31 |
32 | }
--------------------------------------------------------------------------------
/demo/src/main/java/cn/bingoogolapple/badgeview/demo/util/BGABadgeInit.java:
--------------------------------------------------------------------------------
1 | package cn.bingoogolapple.badgeview.demo.util;
2 |
3 | import android.support.design.widget.FloatingActionButton;
4 | import android.view.View;
5 | import android.widget.FrameLayout;
6 | import android.widget.ImageView;
7 | import android.widget.LinearLayout;
8 | import android.widget.RadioButton;
9 | import android.widget.RelativeLayout;
10 | import android.widget.TextView;
11 |
12 | import cn.bingoogolapple.badgeview.annotation.BGABadge;
13 |
14 | /**
15 | * 作者:王浩 邮件:bingoogolapple@gmail.com
16 | * 创建时间:2018/1/14
17 | * 描述:初始化 BGABadgeView-Android
18 | * 1.在项目任意一个类上面添加 BGABadge 注解
19 | * 2.需要哪些类具有徽章功能,就把那些类的 class 作为 BGABadge 注解的参数
20 | * 3.再 AS 中执行 Build => Rebuild Project
21 | * 4.经过前面三个步骤后就可以通过「cn.bingoogolapple.badgeview.BGABadge原始类名」来使用徽章控件了
22 | */
23 | @BGABadge({
24 | View.class, // 对应 cn.bingoogolapple.badgeview.BGABadgeView,不想用这个类的话就删了这一行
25 | ImageView.class, // 对应 cn.bingoogolapple.badgeview.BGABadgeImageView,不想用这个类的话就删了这一行
26 | TextView.class, // 对应 cn.bingoogolapple.badgeview.BGABadgeFloatingTextView,不想用这个类的话就删了这一行
27 | RadioButton.class, // 对应 cn.bingoogolapple.badgeview.BGABadgeRadioButton,不想用这个类的话就删了这一行
28 | LinearLayout.class, // 对应 cn.bingoogolapple.badgeview.BGABadgeLinearLayout,不想用这个类的话就删了这一行
29 | FrameLayout.class, // 对应 cn.bingoogolapple.badgeview.BGABadgeFrameLayout,不想用这个类的话就删了这一行
30 | RelativeLayout.class, // 对应 cn.bingoogolapple.badgeview.BGABadgeRelativeLayout,不想用这个类的话就删了这一行
31 | FloatingActionButton.class, // 对应 cn.bingoogolapple.badgeview.BGABadgeFloatingActionButton,不想用这个类的话就删了这一行
32 | })
33 | public class BGABadgeInit {
34 | }
35 |
--------------------------------------------------------------------------------
/demo/src/main/java/cn/bingoogolapple/badgeview/demo/util/ToastUtil.java:
--------------------------------------------------------------------------------
1 | package cn.bingoogolapple.badgeview.demo.util;
2 |
3 | import android.content.Context;
4 | import android.view.Gravity;
5 | import android.view.LayoutInflater;
6 | import android.widget.TextView;
7 | import android.widget.Toast;
8 |
9 | import cn.bingoogolapple.badgeview.BGABadgeViewUtil;
10 | import cn.bingoogolapple.badgeview.demo.R;
11 |
12 | /**
13 | * 作者:王浩 邮件:bingoogolapple@gmail.com
14 | * 创建时间:15/12/5 上午11:50
15 | * 描述:
16 | */
17 | public class ToastUtil {
18 | private static Toast sToast;
19 | private static TextView sMsgTv;
20 |
21 | private ToastUtil() {
22 | }
23 |
24 | public static void init(Context context) {
25 | sToast = new Toast(context.getApplicationContext());
26 | sToast.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, BGABadgeViewUtil.dp2px(context, 70));
27 | sMsgTv = (TextView) LayoutInflater.from(context).inflate(R.layout.view_toast, null);
28 | sToast.setView(sMsgTv);
29 | sToast.setDuration(Toast.LENGTH_SHORT);
30 | }
31 |
32 | public static void show(CharSequence text) {
33 | sMsgTv.setText(text);
34 | sToast.show();
35 | }
36 | }
--------------------------------------------------------------------------------
/demo/src/main/res/color/selector_maintab.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/demo/src/main/res/drawable/layer_maintab_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 |
7 |
8 | -
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/demo/src/main/res/drawable/selector_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/demo/src/main/res/drawable/selector_tab_discover.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/demo/src/main/res/drawable/selector_tab_home.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/demo/src/main/res/drawable/selector_tab_me.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/demo/src/main/res/drawable/selector_tab_message.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/demo/src/main/res/drawable/selector_tab_plus.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/demo/src/main/res/drawable/selector_tab_plusbg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
-
6 |
7 |
8 |
9 |
10 | -
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | -
19 |
20 |
-
21 |
22 |
23 |
24 |
25 | -
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/demo/src/main/res/drawable/shape_toast.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
12 |
13 |
20 |
21 |
22 |
31 |
32 |
38 |
39 |
44 |
45 |
55 |
56 |
64 |
65 |
68 |
69 |
70 |
71 |
77 |
78 |
81 |
82 |
86 |
87 |
88 |
89 |
96 |
97 |
100 |
101 |
105 |
106 |
107 |
108 |
113 |
114 |
115 |
120 |
121 |
130 |
131 |
140 |
141 |
146 |
147 |
157 |
158 |
166 |
167 |
168 |
169 |
183 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/item_message.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
18 |
19 |
26 |
27 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/view_toast.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-hdpi/avatar_vip.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bingoogolapple/BGABadgeView-Android/d69ee719c0c418c35e7936b5e6621c0193198748/demo/src/main/res/mipmap-hdpi/avatar_vip.png
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-hdpi/avator.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bingoogolapple/BGABadgeView-Android/d69ee719c0c418c35e7936b5e6621c0193198748/demo/src/main/res/mipmap-hdpi/avator.png
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-hdpi/chat_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bingoogolapple/BGABadgeView-Android/d69ee719c0c418c35e7936b5e6621c0193198748/demo/src/main/res/mipmap-hdpi/chat_white.png
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bingoogolapple/BGABadgeView-Android/d69ee719c0c418c35e7936b5e6621c0193198748/demo/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-hdpi/tab_discover_checked.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bingoogolapple/BGABadgeView-Android/d69ee719c0c418c35e7936b5e6621c0193198748/demo/src/main/res/mipmap-hdpi/tab_discover_checked.png
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-hdpi/tab_discover_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bingoogolapple/BGABadgeView-Android/d69ee719c0c418c35e7936b5e6621c0193198748/demo/src/main/res/mipmap-hdpi/tab_discover_normal.png
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-hdpi/tab_home_checked.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bingoogolapple/BGABadgeView-Android/d69ee719c0c418c35e7936b5e6621c0193198748/demo/src/main/res/mipmap-hdpi/tab_home_checked.png
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-hdpi/tab_home_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bingoogolapple/BGABadgeView-Android/d69ee719c0c418c35e7936b5e6621c0193198748/demo/src/main/res/mipmap-hdpi/tab_home_normal.png
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-hdpi/tab_me_checked.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bingoogolapple/BGABadgeView-Android/d69ee719c0c418c35e7936b5e6621c0193198748/demo/src/main/res/mipmap-hdpi/tab_me_checked.png
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-hdpi/tab_me_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bingoogolapple/BGABadgeView-Android/d69ee719c0c418c35e7936b5e6621c0193198748/demo/src/main/res/mipmap-hdpi/tab_me_normal.png
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-hdpi/tab_message_checked.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bingoogolapple/BGABadgeView-Android/d69ee719c0c418c35e7936b5e6621c0193198748/demo/src/main/res/mipmap-hdpi/tab_message_checked.png
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-hdpi/tab_message_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bingoogolapple/BGABadgeView-Android/d69ee719c0c418c35e7936b5e6621c0193198748/demo/src/main/res/mipmap-hdpi/tab_message_normal.png
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-hdpi/tab_plus_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bingoogolapple/BGABadgeView-Android/d69ee719c0c418c35e7936b5e6621c0193198748/demo/src/main/res/mipmap-hdpi/tab_plus_normal.png
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-hdpi/tab_plus_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bingoogolapple/BGABadgeView-Android/d69ee719c0c418c35e7936b5e6621c0193198748/demo/src/main/res/mipmap-hdpi/tab_plus_pressed.png
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bingoogolapple/BGABadgeView-Android/d69ee719c0c418c35e7936b5e6621c0193198748/demo/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bingoogolapple/BGABadgeView-Android/d69ee719c0c418c35e7936b5e6621c0193198748/demo/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-xhdpi/toast.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bingoogolapple/BGABadgeView-Android/d69ee719c0c418c35e7936b5e6621c0193198748/demo/src/main/res/mipmap-xhdpi/toast.png
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bingoogolapple/BGABadgeView-Android/d69ee719c0c418c35e7936b5e6621c0193198748/demo/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #f57257
4 | #f46444
5 | #f46444
6 |
7 | #cccc
8 |
--------------------------------------------------------------------------------
/demo/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/demo/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | BGABadgeViewDemo
3 |
--------------------------------------------------------------------------------
/demo/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
13 |
14 |
22 |
23 |
--------------------------------------------------------------------------------
/demo/src/main/res/values/styles_common.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
13 |
14 |
18 |
19 |
23 |
24 |
29 |
30 |
35 |
36 |
41 |
42 |
47 |
48 |
51 |
52 |
55 |
56 |
59 |
60 |
63 |
64 |
67 |
68 |
71 |
72 |
75 |
76 |
79 |
80 |
83 |
84 |
87 |
88 |
91 |
92 |
95 |
96 |
99 |
100 |
103 |
104 |
107 |
108 |
111 |
112 |
116 |
117 |
121 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | PUBLISH_AAR_GITHUB_REPOSITORIES_NAME=BGABadgeView-Android
2 |
3 | ANDROID_BUILD_MIN_SDK_VERSION=14
4 | ANDROID_BUILD_TARGET_SDK_VERSION=27
5 | ANDROID_BUILD_SDK_VERSION=27
6 |
7 | VERSION_NAME=1.1.9
8 | VERSION_CODE=119
9 |
10 | #org.gradle.jvmargs=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005
11 | #org.gradle.parallel=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bingoogolapple/BGABadgeView-Android/d69ee719c0c418c35e7936b5e6621c0193198748/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Oct 07 10:51:24 CST 2016
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.10-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':annotation', ':api', ':compiler', ':demo'
--------------------------------------------------------------------------------