├── demo
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── mipmap-hdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── values
│ │ │ │ ├── strings.xml
│ │ │ │ ├── colors.xml
│ │ │ │ ├── dimens.xml
│ │ │ │ └── styles.xml
│ │ │ ├── drawable
│ │ │ │ └── circle.xml
│ │ │ ├── values-w820dp
│ │ │ │ └── dimens.xml
│ │ │ └── layout
│ │ │ │ ├── activity_main.xml
│ │ │ │ ├── activity_watcher_demo.xml
│ │ │ │ └── fragment_blank.xml
│ │ ├── java
│ │ │ └── dog
│ │ │ │ └── abcd
│ │ │ │ └── demo
│ │ │ │ ├── MyApplication.java
│ │ │ │ ├── MainActivity.java
│ │ │ │ ├── DemoCircleLayout.java
│ │ │ │ ├── WatcherDemoActivity.java
│ │ │ │ └── BlankFragment.java
│ │ └── AndroidManifest.xml
│ └── androidTest
│ │ └── java
│ │ └── dog
│ │ └── abcd
│ │ └── demo
│ │ └── ExampleInstrumentedTest.java
├── proguard-rules.pro
└── build.gradle
├── settings.gradle
├── lib
├── src
│ └── main
│ │ ├── java
│ │ └── dog
│ │ │ └── abcd
│ │ │ └── lib
│ │ │ ├── alert
│ │ │ ├── package-info.java
│ │ │ ├── AstiAlertCircle.java
│ │ │ ├── AstiAlertManager.java
│ │ │ ├── AstiAlertBase.java
│ │ │ ├── AstiAlert.java
│ │ │ └── AstiAlertDialog.java
│ │ │ ├── network
│ │ │ ├── package-info.java
│ │ │ ├── AntiNetworkException.java
│ │ │ ├── listener
│ │ │ │ ├── AntiNetworkStringListener.java
│ │ │ │ ├── AntiNetworkBitmapListener.java
│ │ │ │ ├── AntiNetworkJsonListener.java
│ │ │ │ └── AntiNetworkJsonArrayListener.java
│ │ │ ├── AntiNetworkListener.java
│ │ │ ├── AntiResponseRequest.java
│ │ │ ├── AntiNetworkConvert.java
│ │ │ ├── AntiNetworkStack.java
│ │ │ ├── AntiNetwork.java
│ │ │ └── AntiNetworkManager.java
│ │ │ ├── utils
│ │ │ ├── package-info.java
│ │ │ ├── AntiSystemUtils.java
│ │ │ ├── AntiLog.java
│ │ │ ├── AntiToast.java
│ │ │ ├── AntiLocationConvertUtils.java
│ │ │ ├── AntiDataSave.java
│ │ │ ├── AntiDataUtils.java
│ │ │ ├── AntiImageUtils.java
│ │ │ ├── AntiImageLoader.java
│ │ │ ├── AntiDateUtils.java
│ │ │ ├── AntiScreenUtils.java
│ │ │ └── AntiViewUtils.java
│ │ │ ├── views
│ │ │ ├── package-info.java
│ │ │ ├── AstiClearEditText.java
│ │ │ ├── AstiCircleImageView.java
│ │ │ ├── AstiFlowLayout.java
│ │ │ └── AstiBannerPager.java
│ │ │ ├── watcher
│ │ │ ├── package-info.java
│ │ │ ├── AntiChangedListener.java
│ │ │ ├── AntiMessenger.java
│ │ │ └── AntiWatcher.java
│ │ │ └── permission
│ │ │ ├── package-info.java
│ │ │ ├── AntiPermissionListener.java
│ │ │ ├── AntiPermission.java
│ │ │ └── AntiPermissionUtil.java
│ │ ├── res
│ │ ├── drawable-xxhdpi
│ │ │ └── text_clean.png
│ │ ├── values
│ │ │ ├── dimens.xml
│ │ │ ├── strings.xml
│ │ │ └── color.xml
│ │ ├── drawable
│ │ │ ├── bg_btn_white.xml
│ │ │ ├── bg_btn_app_radius.xml
│ │ │ ├── bg_btn_radius_bottom.xml
│ │ │ ├── bg_circle_banner.xml
│ │ │ ├── bg_btn_radius_left_bottom.xml
│ │ │ ├── bg_btn_radius_right_bottom.xml
│ │ │ ├── bg_dialog.xml
│ │ │ ├── btn_app_radius.xml
│ │ │ ├── btn_app_radius_pressed.xml
│ │ │ ├── bg_circle_banner_on.xml
│ │ │ ├── btn_radius_right_bottom.xml
│ │ │ ├── btn_radius_left_bottom.xml
│ │ │ ├── btn_radius_bottom.xml
│ │ │ ├── btn_radius_right_bottom_pressed.xml
│ │ │ ├── btn_radius_left_bottom_pressed.xml
│ │ │ └── btn_radius_bottom_pressed.xml
│ │ └── layout
│ │ │ ├── layout_dialog_circle.xml
│ │ │ ├── layout_alert_dialog.xml
│ │ │ └── layout_alert.xml
│ │ └── AndroidManifest.xml
├── build.gradle
└── build
│ └── outputs
│ └── logs
│ └── manifest-merger-debug-report.txt
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── local.properties
├── AntiLib.iml
├── gradlew.bat
├── gradlew
└── README.md
/demo/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':lib', ':demo'
2 |
--------------------------------------------------------------------------------
/lib/src/main/java/dog/abcd/lib/alert/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 常用弹窗包
3 | */
4 | package dog.abcd.lib.alert;
--------------------------------------------------------------------------------
/lib/src/main/java/dog/abcd/lib/network/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 网络请求
3 | */
4 | package dog.abcd.lib.network;
--------------------------------------------------------------------------------
/lib/src/main/java/dog/abcd/lib/utils/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 常用的工具包
3 | */
4 | package dog.abcd.lib.utils;
--------------------------------------------------------------------------------
/lib/src/main/java/dog/abcd/lib/views/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 自定义控件包
3 | */
4 | package dog.abcd.lib.views;
--------------------------------------------------------------------------------
/lib/src/main/java/dog/abcd/lib/watcher/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 数据同步监听
3 | */
4 | package dog.abcd.lib.watcher;
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michaellee123/AntiLib/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/lib/src/main/java/dog/abcd/lib/permission/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * 运行时权限请求工具
3 | */
4 | package dog.abcd.lib.permission;
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michaellee123/AntiLib/HEAD/demo/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michaellee123/AntiLib/HEAD/demo/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michaellee123/AntiLib/HEAD/demo/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michaellee123/AntiLib/HEAD/demo/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michaellee123/AntiLib/HEAD/demo/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/lib/src/main/res/drawable-xxhdpi/text_clean.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michaellee123/AntiLib/HEAD/lib/src/main/res/drawable-xxhdpi/text_clean.png
--------------------------------------------------------------------------------
/lib/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | *
6 | * @author Michael Lee
7 | * create at 2017/2/23 下午 13:04
8 | */
9 | public interface AntiPermissionListener {
10 | void onPermissionRequestFinish(String[] success, String[] failed, String[] refuse);
11 | }
12 |
--------------------------------------------------------------------------------
/lib/src/main/res/drawable/bg_btn_radius_bottom.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 | * 需要检查数据改变的类实现该接口以及方法
9 | *
10 | * @author Michael Lee
11 | * create at 2016-4-15 上午9:27:45
12 | */
13 | public interface AntiChangedListener {
14 | void onWatcherChanged(String changedKey);
15 | }
16 |
--------------------------------------------------------------------------------
/lib/src/main/res/drawable/bg_circle_banner.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 | * Description
11 | *
12 | * @author Michael Lee
13 | * create at 2017/2/24 下午 14:42
14 | */
15 | public class MyApplication extends Application {
16 | @Override
17 | public void onCreate() {
18 | super.onCreate();
19 | //初始化网络请求
20 | AntiNetworkManager.init(this, 0, null, null);
21 | //初始化图片加载
22 | AntiImageLoader.init(this);
23 | // AntiImageLoader.init(this,加载中的图片,加载图片为空时的图片,加载失败的图片);
24 | // AntiImageLoader.init(this,自定义图片加载配置);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/lib/src/main/java/dog/abcd/lib/network/AntiNetworkException.java:
--------------------------------------------------------------------------------
1 | package dog.abcd.lib.network;
2 |
3 | /**
4 | * 网络错误
5 | * 包括http错误与错误信息
6 | *
7 | * @author Michael Lee
8 | * create at 2017/2/20 下午 14:33
9 | */
10 | public class AntiNetworkException extends Exception {
11 |
12 | public AntiNetworkException(int code, String message) {
13 | this.code = code;
14 | this.message = message;
15 | }
16 |
17 | private int code;
18 |
19 | private String message;
20 |
21 | @Override
22 | public String getMessage() {
23 | return message;
24 | }
25 |
26 | public void setMessage(String message) {
27 | this.message = message;
28 | }
29 |
30 | public int getCode() {
31 | return code;
32 | }
33 |
34 | public void setCode(int code) {
35 | this.code = code;
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/demo/src/androidTest/java/dog/abcd/demo/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package dog.abcd.demo;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumentation test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("dog.abcd.demo", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/lib/src/main/java/dog/abcd/lib/network/listener/AntiNetworkStringListener.java:
--------------------------------------------------------------------------------
1 | package dog.abcd.lib.network.listener;
2 |
3 | import com.android.volley.NetworkResponse;
4 |
5 | import dog.abcd.lib.network.AntiNetwork;
6 | import dog.abcd.lib.network.AntiNetworkConvert;
7 | import dog.abcd.lib.network.AntiNetworkListener;
8 |
9 | /**
10 | * 网络请求处理回调(结果为String)
11 | * 从AntiNetworkListener重写
12 | * @see AntiNetworkListener
13 | *
14 | * @author Michael Lee
15 | * create at 2017/6/5 下午 15:55
16 | */
17 | public abstract class AntiNetworkStringListener implements AntiNetworkListener {
18 | @Override
19 | public final void success(AntiNetwork network, NetworkResponse result) {
20 | success( network, AntiNetworkConvert.convertResponseToString( result ) );
21 | }
22 |
23 | protected abstract void success(AntiNetwork network, String result);
24 | }
25 |
--------------------------------------------------------------------------------
/AntiLib.iml:
--------------------------------------------------------------------------------
1 |
2 |
13 | * 从AntiNetworkListener重写
14 | * @see AntiNetworkListener
15 | *
16 | * @author Michael Lee
17 | * create at 2017/6/5 下午 16:02
18 | */
19 | public abstract class AntiNetworkBitmapListener implements AntiNetworkListener {
20 |
21 | @Override
22 | public final void success(AntiNetwork network, NetworkResponse result) {
23 | success( network, AntiNetworkConvert.convertResponseToBitmap( result ) );
24 | }
25 |
26 | protected abstract void success(AntiNetwork network, Bitmap result);
27 | }
28 |
--------------------------------------------------------------------------------
/lib/src/main/java/dog/abcd/lib/network/listener/AntiNetworkJsonListener.java:
--------------------------------------------------------------------------------
1 | package dog.abcd.lib.network.listener;
2 |
3 | import com.android.volley.NetworkResponse;
4 |
5 | import org.json.JSONObject;
6 |
7 | import dog.abcd.lib.network.AntiNetwork;
8 | import dog.abcd.lib.network.AntiNetworkConvert;
9 | import dog.abcd.lib.network.AntiNetworkListener;
10 |
11 | /**
12 | * 网络请求处理回调(结果为JSON [org.json.JSONObject])
13 | * 从AntiNetworkListener重写
14 | * @see AntiNetworkListener
15 | *
16 | * @author Michael Lee
17 | * create at 2017/6/5 下午 16:00
18 | */
19 | public abstract class AntiNetworkJsonListener implements AntiNetworkListener {
20 |
21 | @Override
22 | public final void success(AntiNetwork network, NetworkResponse result) {
23 | success( network, AntiNetworkConvert.convertResponseToJson( result ) );
24 | }
25 |
26 | protected abstract void success(AntiNetwork network, JSONObject result);
27 | }
28 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/activity_watcher_demo.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 | * 从AntiNetworkListener重写
14 | * @see AntiNetworkListener
15 | *
16 | * @author Michael Lee
17 | * create at 2017/6/5 下午 16:02
18 | */
19 | public abstract class AntiNetworkJsonArrayListener implements AntiNetworkListener {
20 |
21 | @Override
22 | public final void success(AntiNetwork network, NetworkResponse result) {
23 | success( network, AntiNetworkConvert.convertResponseToJsonArray( result ) );
24 | }
25 |
26 | protected abstract void success(AntiNetwork network, JSONArray result);
27 | }
28 |
--------------------------------------------------------------------------------
/demo/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
14 | * 直接实现本接口可以获取到最原始的网络请求数据回调,再通过AntiNetworkConvert类进行转换,或者自行转换,现有四个不同类型的二次封装抽象
15 | *
16 | * 如果在当做AntiNetworkManager里面的默认监听时方法中返回了true,则不会再调用之后的方法
17 | *
18 | * @author Michael Lee
164 | * 将这个bitmap放在canvas上面承载,并在其上面画一个椭圆(其实也是一个圆,因为width=height)来固定显示区域
165 | *
166 | * @param width
167 | * @param height
168 | * @return
169 | */
170 | public Bitmap createOvalBitmap(final int width, final int height) {
171 | Bitmap.Config localConfig = Bitmap.Config.ARGB_8888;
172 | Bitmap localBitmap = Bitmap.createBitmap(width, height, localConfig);
173 | Canvas localCanvas = new Canvas(localBitmap);
174 | Paint localPaint = new Paint();
175 | final int padding = mBorderWidth > 2 ? mBorderWidth - 2 : 0;
176 | /**
177 | * 设置椭圆的大小(因为椭圆的最外边会和border的最外边重合的,如果图片最外边的颜色很深,有看出有棱边的效果,所以为了让体验更加好,
178 | * 让其缩进padding px)
179 | */
180 | RectF localRectF = new RectF(padding, padding, width - padding, height
181 | - padding);
182 | localCanvas.drawOval(localRectF, localPaint);
183 | return localBitmap;
184 | }
185 | }
186 |
--------------------------------------------------------------------------------
/lib/src/main/java/dog/abcd/lib/permission/AntiPermissionUtil.java:
--------------------------------------------------------------------------------
1 | package dog.abcd.lib.permission;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.content.pm.PackageManager;
6 | import android.net.Uri;
7 | import android.os.Build;
8 | import android.support.v4.app.ActivityCompat;
9 | import android.support.v4.content.ContextCompat;
10 |
11 | import java.util.HashMap;
12 | import java.util.Map;
13 |
14 | import dog.abcd.lib.utils.AntiLog;
15 |
16 | /**
17 | * 运行时权限请求工具
19 | * create at 2017/2/20 下午 14:31
20 | * @see dog.abcd.lib.network.AntiNetworkConvert
21 | * @see AntiNetworkBitmapListener
22 | * @see AntiNetworkJsonArrayListener
23 | * @see AntiNetworkJsonListener
24 | * @see AntiNetworkStringListener
25 | */
26 | public interface AntiNetworkListener {
27 |
28 | void success(AntiNetwork network, NetworkResponse result);
29 |
30 | void error(AntiNetwork network, AntiNetworkException error);
31 | }
32 |
--------------------------------------------------------------------------------
/lib/src/main/java/dog/abcd/lib/utils/AntiSystemUtils.java:
--------------------------------------------------------------------------------
1 | package dog.abcd.lib.utils;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.net.Uri;
6 |
7 | /**
8 | *
9 | * 系统帮助类
10 | * 一些常用的系统方法调用
11 | *
12 | * @author Michael Lee
13 | * create at 2016-1-28 上午10:56:01
14 | *
15 | */
16 | public class AntiSystemUtils {
17 |
18 | private AntiSystemUtils(){
19 |
20 | }
21 |
22 | /**
23 | * 调用系统下载
24 | *
25 | * @param url
26 | * @param context
27 | */
28 | public static void download(String url, Context context) {
29 | try {
30 | Intent i = new Intent(Intent.ACTION_VIEW);
31 | i.setData(Uri.parse(url));
32 | context.startActivity(i);
33 | } catch (Exception e) {
34 | }
35 | }
36 |
37 | /**
38 | * 跳转系统拨打电话界面
39 | *
40 | * @param context
41 | * @param number
42 | */
43 | public static void callPhone(Context context, String number) {
44 | try {
45 | Uri uri = Uri.parse("tel:" + number);
46 | Intent it = new Intent(Intent.ACTION_DIAL, uri);
47 | context.startActivity(it);
48 | } catch (Exception e) {
49 | }
50 | }
51 |
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/lib/src/main/java/dog/abcd/lib/network/AntiResponseRequest.java:
--------------------------------------------------------------------------------
1 | package dog.abcd.lib.network;
2 |
3 | import com.android.volley.NetworkResponse;
4 | import com.android.volley.Request;
5 | import com.android.volley.Response;
6 | import com.android.volley.toolbox.HttpHeaderParser;
7 |
8 | /**
9 | * 通用网络请求
10 | * 返回的值需要调用AntiNetworkConvert进行转换
11 | *
12 | * @author Michael Lee
13 | * create at 2017/2/21 下午 12:57
14 | */
15 | public class AntiResponseRequest extends Request
8 | * 封装了Log类的操作,方法调用与Log类一致,只是加入idDebug状态,
9 | * 在发布App的时候在Application中设置为false则不会打印日志出来了
10 | *
11 | * @author Michael Lee
12 | * create at 2016-1-28 下午1:45:53
13 | */
14 | public class AntiLog {
15 | // 是否为调试状态
16 | private static boolean isDebug = true;
17 |
18 | /**
19 | * 是否打印,默认开启
20 | *
21 | * @param isDebug
22 | */
23 | public static void setDebug(boolean isDebug) {
24 | AntiLog.isDebug = isDebug;
25 | }
26 |
27 | public static void e(String tag, String msg) {
28 | if (isDebug) {
29 | Log.e(tag, msg);
30 | }
31 | }
32 |
33 | public static void i(String tag, String msg) {
34 | if (isDebug) {
35 | Log.i(tag, msg);
36 | }
37 | }
38 |
39 | public static void d(String tag, String msg) {
40 | if (isDebug) {
41 | Log.d(tag, msg);
42 | }
43 | }
44 |
45 | public static void w(String tag, String msg) {
46 | if (isDebug) {
47 | Log.w(tag, msg);
48 | }
49 | }
50 |
51 | public static void v(String tag, String msg) {
52 | if (isDebug) {
53 | Log.v(tag, msg);
54 | }
55 | }
56 |
57 | public static void wtf(String tag, String msg) {
58 | if (isDebug) {
59 | Log.wtf(tag, msg);
60 | }
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/lib/src/main/res/layout/layout_dialog_circle.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 | * 避免了多次调用后一直显示Toast的问题
9 | *
10 | * @author Michael Lee
11 | * create at 2016-1-28 下午1:51:56
12 | */
13 | public class AntiToast {
14 |
15 | private AntiToast() {
16 |
17 | }
18 |
19 | private static Toast toast;
20 |
21 | /**
22 | * 显示Toast
23 | *
24 | * @param context 上下文
25 | * @param message 显示文字
26 | */
27 | public static Toast show(Context context, CharSequence message) {
28 | if (null == toast) {
29 | toast = Toast.makeText(context, message, Toast.LENGTH_SHORT);
30 | } else {
31 | toast.setText(message);
32 | }
33 | toast.show();
34 | return toast;
35 | }
36 |
37 | /**
38 | * 显示Toast
39 | *
40 | * @param context 上下文
41 | * @param message 显示文字
42 | * @param showTime 显示停留的时间
43 | */
44 | public static Toast show(Context context, CharSequence message, int showTime) {
45 | if (null == toast) {
46 | toast = Toast.makeText(context, message, showTime);
47 | } else {
48 | toast.setText(message);
49 | }
50 | toast.show();
51 | return toast;
52 | }
53 |
54 | /**
55 | * 隐藏Toast
56 | */
57 | public static void hidden() {
58 | if (null != toast) {
59 | toast.cancel();
60 | toast = null;
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/lib/src/main/java/dog/abcd/lib/utils/AntiLocationConvertUtils.java:
--------------------------------------------------------------------------------
1 | package dog.abcd.lib.utils;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | /**
7 | * 坐标类型转换
8 | * GCJ02和BD09的互相转换
9 | *
10 | * @author Michael Lee
11 | * create at 2016-1-28 上午11:30:33
12 | */
13 | public class AntiLocationConvertUtils {
14 |
15 | private AntiLocationConvertUtils() {
16 |
17 | }
18 |
19 | private static double x_pi = 3.14159265358979324 * 3000.0 / 180.0;
20 | private static Map
12 | * 圆条加载提示框
13 | * -更新弹出框线程不同步造成的显示问题
14 | *
15 | * @author Michael Lee
16 | * create at 2016年1月28日 上午11:18:18
17 | */
18 | public class AstiAlertCircle extends AstiAlertBase {
19 |
20 | View alertView;
21 |
22 | private boolean cancelable;
23 |
24 | private TextView tvMessage;
25 |
26 | public TextView getTvMessage() {
27 | return tvMessage;
28 | }
29 |
30 | /**
31 | * @param context
32 | * @param message 提示信息
33 | * @param cancelable 是否能够取消(默认为能够取消)
34 | * @return
35 | */
36 | public static AstiAlertCircle create(Context context, String TAG, String message, boolean cancelable) {
37 | return new AstiAlertCircle(context, TAG, message, cancelable);
38 | }
39 |
40 | public static AstiAlertCircle create(Context context, String TAG, String message) {
41 | return new AstiAlertCircle(context, TAG, message, true);
42 | }
43 |
44 | private AstiAlertCircle(Context context, String TAG, String message, boolean cancelable) {
45 | super(context, TAG);
46 | alertView = initView(message);
47 | this.cancelable = cancelable;
48 | }
49 |
50 | protected View initView(String message) {
51 | View view = LayoutInflater.from(getContext()).inflate(R.layout.layout_dialog_circle, null);
52 | tvMessage = (TextView) view.findViewById(R.id.dialog_message);
53 | tvMessage.setText(message);
54 | return view;
55 | }
56 |
57 | @Override
58 | protected View createView() {
59 | return alertView;
60 | }
61 |
62 | @Override
63 | protected boolean cancelable() {
64 | return cancelable;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/lib/src/main/java/dog/abcd/lib/permission/AntiPermission.java:
--------------------------------------------------------------------------------
1 | package dog.abcd.lib.permission;
2 |
3 | import android.app.Activity;
4 |
5 | import java.util.ArrayList;
6 | import java.util.List;
7 |
8 | /**
9 | * 运行时权限请求
10 | *
11 | * @author Michael Lee
12 | * create at 2017/2/23 下午 13:04
13 | */
14 | class AntiPermission {
15 | private List
11 | * 保存、传递数据
12 | *
13 | * @author Michael Lee
14 | * create at 2016-4-15 上午9:27:32
15 | */
16 | class AntiMessenger {
17 | private Map
16 | * Description
17 | *
18 | * @author Michael Lee
19 | * create at 2017/3/1 下午 16:41
20 | */
21 | public class DemoCircleLayout extends RelativeLayout {
22 | public DemoCircleLayout(Context context) {
23 | super(context);
24 | }
25 |
26 | public DemoCircleLayout(Context context, AttributeSet attrs) {
27 | super(context, attrs);
28 | }
29 |
30 | public DemoCircleLayout(Context context, AttributeSet attrs, int defStyleAttr) {
31 | super(context, attrs, defStyleAttr);
32 | }
33 |
34 | @Override
35 | protected void onDraw(Canvas canvas) {
36 | super.onDraw(canvas);
37 | Bitmap circleBitmap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight() / 4, Bitmap.Config.ARGB_8888);
38 | Canvas circleCanvas = new Canvas();
39 | circleCanvas.setBitmap(circleBitmap);
40 | Paint paint = new Paint();
41 | paint.setColor(Color.WHITE);
42 | circleCanvas.drawCircle(getMeasuredWidth() / 2, getMeasuredHeight() / 2, getMeasuredWidth() / 2, paint);
43 | circleCanvas.save();
44 | circleCanvas.restore();
45 | canvas.drawBitmap(circleBitmap, 0, 0, null);
46 | canvas.drawCircle(getMeasuredWidth() / 7 * 2, getMeasuredHeight() / 5 * 2, getMeasuredWidth() / 15, paint);
47 | canvas.drawCircle(getMeasuredWidth() / 7 * 5, getMeasuredHeight() / 5 * 2, getMeasuredWidth() / 15, paint);
48 | canvas.drawRect(getMeasuredWidth() / 8 * 3, getMeasuredHeight() / 4 * 3, getMeasuredWidth() / 8 * 5, getMeasuredHeight() / 4 * 3 + 5, paint);
49 | canvas.save();
50 | canvas.restore();
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/demo/src/main/java/dog/abcd/demo/WatcherDemoActivity.java:
--------------------------------------------------------------------------------
1 | package dog.abcd.demo;
2 |
3 | import android.os.Bundle;
4 | import android.support.v7.app.AppCompatActivity;
5 | import android.view.View;
6 | import android.widget.Button;
7 |
8 | import dog.abcd.lib.utils.AntiToast;
9 | import dog.abcd.lib.watcher.AntiWatcher;
10 |
11 | /**
12 | * 向上个页面发送通知
13 | */
14 | public class WatcherDemoActivity extends AppCompatActivity {
15 |
16 | String[] images = new String[]{
17 | "https://a-ssl.duitang.com/uploads/item/201608/02/20160802212747_Lx5Yd.thumb.700_0.jpeg",
18 | "http://imgsrc.baidu.com/forum/w%3D580/sign=d8630275fefaaf5184e381b7bc5594ed/d7dd9c4bd11373f0947ac5cca70f4bfbfaed04bd.jpg",
19 | "http://imgsrc.baidu.com/forum/w%3D580/sign=b6966cbdb78f8c54e3d3c5270a282dee/756eb3025aafa40f523c648ea864034f79f0190c.jpg",
20 | "http://imgsrc.baidu.com/forum/w%3D580/sign=982a18c2ce11728b302d8c2af8fdc3b3/0ce533087bf40ad12bf350b0542c11dfa8eccee8.jpg",
21 | "http://imgsrc.baidu.com/forum/w%3D580/sign=3adac14461d0f703e6b295d438fb5148/e343d61190ef76c617266c789e16fdfaae51670f.jpg",
22 | "http://imgsrc.baidu.com/forum/w%3D580/sign=82ee7b9ad42a60595210e1121835342d/869428d8bc3eb135e01b20e8a51ea8d3fc1f4427.jpg",
23 | "http://imgsrc.baidu.com/forum/w%3D580/sign=cbb6e457940a304e5222a0f2e1c9a7c3/8d4a821c8701a18bb17f821c9d2f07082938fe6f.jpg",
24 | "http://imgsrc.baidu.com/forum/w%3D580/sign=0e56606c48fbfbeddc59367748f1f78e/df67e62a6059252d80d3ec57379b033b5ab5b93f.jpg"
25 | };
26 |
27 | static int i = 0;
28 |
29 | Button button;
30 |
31 | @Override
32 | protected void onCreate(Bundle savedInstanceState) {
33 | super.onCreate(savedInstanceState);
34 | setContentView(R.layout.activity_watcher_demo);
35 | button = findViewById(R.id.change);
36 | i++;
37 | button.setOnClickListener(new View.OnClickListener() {
38 | @Override
39 | public void onClick(View v) {
40 | AntiWatcher.putString("image", images[i % (images.length - 1)]);
41 | AntiToast.show(WatcherDemoActivity.this, "返回上个页面查看结果");
42 | }
43 | });
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/lib/src/main/java/dog/abcd/lib/utils/AntiDataSave.java:
--------------------------------------------------------------------------------
1 | package dog.abcd.lib.utils;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.content.SharedPreferences;
6 | import android.content.SharedPreferences.Editor;
7 |
8 | /**
9 | * 数据缓存类
10 | * 封装SharedPreferences的简单操作
11 | *
12 | * @author Michael Lee
13 | * create at 2016-1-28 上午11:02:16
14 | */
15 | public class AntiDataSave {
16 | private Context context;
17 |
18 | private SharedPreferences sp;
19 |
20 | public AntiDataSave(Context context) {
21 | this.context = context;
22 | }
23 |
24 | /**
25 | * 获取SharedPreferences对象
26 | *
27 | * @param file
28 | * 文件名
29 | * @return SharedPreferences
30 | */
31 | public SharedPreferences getSharedPreferences(String file) {
32 | sp = context.getSharedPreferences(file, Activity.MODE_PRIVATE);
33 | return sp;
34 | }
35 |
36 | /**
37 | * 存储数据
38 | *
39 | * @param file
40 | * 文件名
41 | * @param key
42 | * 键
43 | * @param value
44 | * 值
45 | */
46 | public void save(String file, String key, String value) {
47 | try{
48 | sp = context.getSharedPreferences(file, Activity.MODE_PRIVATE);
49 | Editor editor = sp.edit();
50 | editor.putString(key, value);
51 | editor.commit();
52 | }catch(Exception e){
53 |
54 | }
55 | }
56 |
57 | /**
58 | * 读取数据
59 | *
60 | * @param file
61 | * 文件名
62 | * @param key
63 | * 键
64 | * @param defaultValue
65 | * 默认值
66 | * @return 字符串
67 | */
68 | public String read(String file, String key, String defaultValue) {
69 | try{
70 | sp = context.getSharedPreferences(file, Activity.MODE_PRIVATE);
71 | return sp.getString(key, defaultValue);
72 | }catch(Exception exception){
73 | return null;
74 | }
75 | }
76 |
77 | /**
78 | * 清除缓存
79 | *
80 | * @param file
81 | * 文件名
82 | * @return 操作结果(always be true)
83 | */
84 | public boolean clearData(String file) {
85 | try{
86 | sp = context.getSharedPreferences(file, Activity.MODE_PRIVATE);
87 | Editor editor = sp.edit();
88 | editor.clear();
89 | editor.commit();
90 | return true;
91 | }catch(Exception e){
92 | return false;
93 | }
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/fragment_blank.xml:
--------------------------------------------------------------------------------
1 |
8 | * 对所有弹窗进行管理
9 | *
10 | * @author Michael Lee
11 | * create at 2017/1/17 下午 16:35
12 | */
13 | public class AstiAlertManager {
14 |
15 | Map
17 | * 由返回的Response的data传进来转换成需要的类型
18 | *
19 | * @author Michael Lee
20 | * create at 2017/2/21 下午 15:04
21 | */
22 | public class AntiNetworkConvert {
23 | protected static final String PROTOCOL_CHARSET = "utf-8";
24 |
25 | public static String convertResponseToString(NetworkResponse response) {
26 | String parsed;
27 | try {
28 | parsed = new String( response.data, HttpHeaderParser.parseCharset( response.headers, PROTOCOL_CHARSET ) );
29 | } catch (UnsupportedEncodingException e) {
30 | parsed = new String( response.data );
31 | }
32 | return parsed;
33 | }
34 |
35 |
36 | public static JSONObject convertResponseToJson(NetworkResponse response) {
37 | try {
38 | String jsonString = new String( response.data,
39 | HttpHeaderParser.parseCharset( response.headers, PROTOCOL_CHARSET ) );
40 | return new JSONObject( jsonString );
41 | } catch (UnsupportedEncodingException e) {
42 | return null;
43 | } catch (JSONException je) {
44 | return null;
45 | }
46 | }
47 |
48 | public static JSONArray convertResponseToJsonArray(NetworkResponse response) {
49 | try {
50 | String jsonString = new String( response.data,
51 | HttpHeaderParser.parseCharset( response.headers, PROTOCOL_CHARSET ) );
52 | return new JSONArray( jsonString );
53 | } catch (UnsupportedEncodingException e) {
54 | return null;
55 | } catch (JSONException je) {
56 | return null;
57 | }
58 | }
59 |
60 | public static Bitmap convertResponseToBitmap(NetworkResponse response) {
61 | byte[] data = response.data;
62 | BitmapFactory.Options decodeOptions = new BitmapFactory.Options();
63 | // If we have to resize this image, first get the natural bounds.
64 | decodeOptions.inJustDecodeBounds = true;
65 | BitmapFactory.decodeByteArray( data, 0, data.length, decodeOptions );
66 | // Decode to the nearest power of two scaling factor.
67 | decodeOptions.inJustDecodeBounds = false;
68 | // decodeOptions.inPreferQualityOverSpeed = PREFER_QUALITY_OVER_SPEED;
69 | return BitmapFactory.decodeByteArray( data, 0, data.length, decodeOptions );
70 | }
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/lib/src/main/res/layout/layout_alert_dialog.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 | * 继承后实现createView方法再调用show方法即可
14 | *
15 | * @author Michael Lee
16 | * create at 2017/1/17 下午 16:38
17 | */
18 | public abstract class AstiAlertBase {
19 |
20 | private Context context;
21 | private String TAG;
22 | private AlertDialog dlg;
23 | private Window window;
24 |
25 | public AstiAlertBase(Context context, String TAG) {
26 | if (TAG == null || context == null) {
27 | throw new IllegalArgumentException("arguments that named TAG or context can not be null!");
28 | }
29 | this.TAG = TAG;
30 | this.context = context;
31 | }
32 |
33 | protected abstract View createView();
34 |
35 | protected abstract boolean cancelable();
36 |
37 | public void show() {
38 | dismiss();
39 | try {
40 | dlg = new AlertDialog.Builder(context).create();
41 | dlg.show();
42 | window = dlg.getWindow();
43 | dlg.setCancelable(cancelable());
44 | window.setContentView(createView());
45 | window.setBackgroundDrawableResource(R.color.alpha);
46 | AstiAlertManager.getInstance().add(this);
47 | } catch (Exception e) {
48 | e.printStackTrace();
49 | }
50 | }
51 |
52 | /**
53 | * 取消显示
54 | */
55 | public void dismiss() {
56 | try {
57 | dlg.dismiss();
58 | } catch (Exception e) {
59 |
60 | }
61 | }
62 |
63 | /**
64 | * 取消显示
65 | */
66 | public void cancel() {
67 | try {
68 | dlg.cancel();
69 | } catch (Exception e) {
70 |
71 | }
72 | }
73 |
74 | public String getTAG() {
75 | return TAG;
76 | }
77 |
78 | public Context getContext() {
79 | return context;
80 | }
81 |
82 | /**
83 | * 获取窗口
84 | *
85 | * @return
86 | */
87 | public Window getWindow() {
88 | return window;
89 | }
90 |
91 | /**
92 | * @return 获取弹出窗口
93 | */
94 | public AlertDialog getDialog() {
95 | return dlg;
96 | }
97 |
98 | /**
99 | * 设置取消的回调
100 | *
101 | * @param onCancelListener
102 | */
103 | public void setOnCancelListener(DialogInterface.OnCancelListener onCancelListener) {
104 | dlg.setOnCancelListener(onCancelListener);
105 | }
106 |
107 | /**
108 | * 设置隐藏时的回调
109 | *
110 | * @param onDismissListener
111 | */
112 | public void setOnDismissListener(DialogInterface.OnDismissListener onDismissListener) {
113 | dlg.setOnDismissListener(onDismissListener);
114 | }
115 |
116 | }
117 |
--------------------------------------------------------------------------------
/lib/src/main/res/layout/layout_alert.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 | * 一些数据的校验
13 | *
14 | * @author Michael Lee
15 | * create at 2016-1-28 上午10:56:01
16 | *
17 | */
18 | public class AntiDataUtils {
19 |
20 | private AntiDataUtils() {
21 |
22 | }
23 |
24 | /**
25 | * 判断是不是手机号
26 | *
27 | * @param number
28 | * 号码
29 | * @return 是手机号返回true
30 | */
31 | public static boolean isPhoneNumber(String number) {
32 | boolean flag;
33 | try {
34 | Pattern regex = Pattern.compile("^(((1[3-9][0-9]))\\d{8})");
35 | Matcher matcher = regex.matcher(number);
36 | flag = matcher.matches();
37 | } catch (Exception e) {
38 | flag = false;
39 | }
40 | return flag;
41 | }
42 |
43 | /**
44 | * 判断是否是只有小数点后两位的金额
45 | *
46 | * @param money
47 | * @return
48 | */
49 | public static boolean isMoney(String money) {
50 | boolean flag;
51 | try {
52 | Pattern regex = Pattern.compile("^(([1-9]\\d{0,9})|0)(\\.\\d{1,2})?$");
53 | Matcher matcher = regex.matcher(money);
54 | flag = matcher.matches();
55 | } catch (Exception e) {
56 | flag = false;
57 | }
58 | return flag;
59 | }
60 |
61 | /**
62 | * 保留两位小数
63 | *
64 | * @param value
65 | * @return
66 | */
67 | public static String formatMoney(double value) {
68 | try {
69 | BigDecimal bd = new BigDecimal(value);
70 | bd = bd.setScale(2, RoundingMode.HALF_UP);
71 | return bd.toString();
72 | } catch (Exception e) {
73 | return String.valueOf(value);
74 | }
75 | }
76 |
77 | /**
78 | * 保留两位小数
79 | *
80 | * @param value
81 | * @return
82 | */
83 | public static String formatMoney(String value) {
84 | try {
85 | BigDecimal bd = new BigDecimal(value);
86 | bd = bd.setScale(2, RoundingMode.HALF_UP);
87 | return bd.toString();
88 | } catch (Exception e) {
89 | return value;
90 | }
91 | }
92 |
93 | /**
94 | * 判断字符串是否为空
95 | * @param str
96 | */
97 | public static boolean isEmpty(String str) {
98 | return str == null || str.length() == 0;
99 | }
100 |
101 | /**
102 | * 是否为身份证
103 | *
104 | * @param idcard
105 | * @return
106 | */
107 | public static boolean isIdCard(String idcard) {
108 | if (AntiDataUtils.isEmpty(idcard)) {
109 | return false;
110 | }
111 | idcard.toLowerCase(Locale.getDefault());
112 | try {
113 | if (idcard.length() < 18) {
114 | return false;
115 | }
116 | /*身份证校验*/
117 | int[] i_card_number = new int[idcard.length() - 1];
118 | char[] c_card_number = idcard.toCharArray();
119 |
120 | for (int i = 0; i < idcard.length() - 1; i++) {
121 | i_card_number[i] = Integer.parseInt(Character.toString(c_card_number[i]));
122 | }
123 |
124 | int[] key = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 };
125 | int num = 0;
126 | char nTail = '0';
127 |
128 | for (int i = 0; i < i_card_number.length; i++) {
129 | num += i_card_number[i] * key[i];
130 | }
131 |
132 | num %= 11;
133 |
134 | switch (num) {
135 | case 0: {
136 | nTail = '1';
137 | break;
138 | }
139 | case 1: {
140 | nTail = '0';
141 | break;
142 | }
143 | case 2: {
144 | nTail = 'x';
145 | break;
146 | }
147 | case 3: {
148 | nTail = '9';
149 | break;
150 | }
151 | case 4: {
152 | nTail = '8';
153 | break;
154 | }
155 | case 5: {
156 | nTail = '7';
157 | break;
158 | }
159 | case 6: {
160 | nTail = '6';
161 | break;
162 | }
163 | case 7: {
164 | nTail = '5';
165 | break;
166 | }
167 | case 8: {
168 | nTail = '4';
169 | break;
170 | }
171 | case 9: {
172 | nTail = '3';
173 | break;
174 | }
175 | case 10: {
176 | nTail = '2';
177 | break;
178 | }
179 | }
180 |
181 | if (!Character.toString(nTail).equals(idcard.substring(17))) {
182 | //身份证验证失败
183 | return false;
184 | } else {
185 | return true;
186 | }
187 | } catch (Exception e) {
188 | return false;
189 | }
190 | }
191 | }
192 |
--------------------------------------------------------------------------------
/lib/src/main/java/dog/abcd/lib/utils/AntiImageUtils.java:
--------------------------------------------------------------------------------
1 | package dog.abcd.lib.utils;
2 |
3 | import java.io.ByteArrayInputStream;
4 | import java.io.ByteArrayOutputStream;
5 | import java.io.IOException;
6 |
7 | import android.graphics.Bitmap;
8 | import android.graphics.BitmapFactory;
9 | import android.graphics.Bitmap.CompressFormat;
10 | import android.util.Base64;
11 |
12 | /**
13 | * 图片处理
14 | * 对图片进行尺寸和质量压缩以及base64编码
15 | *
16 | * @author Michael Lee
17 | * create at 2016-1-28 上午11:19:34
18 | */
19 | public class AntiImageUtils {
20 |
21 | private AntiImageUtils() {
22 |
23 | }
24 |
25 | /**
26 | * 缩放大小,不改变尺寸(压缩质量)
27 | *
28 | * @param image
29 | * @return
30 | */
31 | public static Bitmap compressImage(Bitmap image) {
32 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
33 | image.compress(Bitmap.CompressFormat.JPEG, 100, baos);// 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
34 | int options = 100;
35 | while (baos.toByteArray().length / 1024 > 512) { // 循环判断如果压缩后图片是否大于1M,大于继续压缩
36 | baos.reset();// 重置baos即清空baos
37 | options -= 10;// 每次都减少10
38 | image.compress(Bitmap.CompressFormat.JPEG, options, baos);// 这里压缩options%,把压缩后的数据存放到baos中
39 |
40 | }
41 | ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把压缩后的数据baos存放到ByteArrayInputStream中
42 | Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);// 把ByteArrayInputStream数据生成图片
43 | return bitmap;
44 | }
45 |
46 | /**
47 | * 缩放尺寸并减小大小(压缩尺寸后并在压缩质量)
48 | *
49 | * @param image
50 | * @param ww
51 | * 宽度
52 | * @param hh
53 | * 高度
54 | * @return
55 | */
56 | public static Bitmap comp(Bitmap image, float ww, float hh) {
57 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
58 | image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
59 | if (baos.toByteArray().length / 1024 > 1024) {// 判断如果图片大于1M,进行压缩避免在生成图片(BitmapFactory.decodeStream)时溢出
60 | baos.reset();// 重置baos即清空baos
61 | image.compress(Bitmap.CompressFormat.JPEG, 50, baos);// 这里压缩50%,把压缩后的数据存放到baos中
62 | }
63 | ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
64 | BitmapFactory.Options newOpts = new BitmapFactory.Options();
65 | // 开始读入图片,此时把options.inJustDecodeBounds 设回true了
66 | newOpts.inJustDecodeBounds = true;
67 | Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);
68 | newOpts.inJustDecodeBounds = false;
69 | int w = newOpts.outWidth;
70 | int h = newOpts.outHeight;
71 | // 缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
72 | int be = 1;// be=1表示不缩放
73 | if (w > h && w > ww) {// 如果宽度大的话根据宽度固定大小缩放
74 | be = (int) (newOpts.outWidth / ww);
75 | } else if (w < h && h > hh) {// 如果高度高的话根据宽度固定大小缩放
76 | be = (int) (newOpts.outHeight / hh);
77 | }
78 | if (be <= 0)
79 | be = 1;
80 | newOpts.inSampleSize = be;// 设置缩放比例
81 | // newOpts.inPreferredConfig = Config.RGB_565;// 降低图片从ARGB888到RGB565
82 | // 重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了
83 | isBm = new ByteArrayInputStream(baos.toByteArray());
84 | bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);
85 | return compressImage(bitmap);// 压缩好比例大小后再进行质量压缩
86 | }
87 |
88 | /**
89 | * 把图片转换成流输出成字符串
90 | *
91 | * @param bitmap
92 | */
93 | public static String disposeImage(Bitmap bitmap) {
94 | if (bitmap == null) {
95 | AntiLog.e("disposeImage", "NULL!");
96 | return "";
97 | }
98 | ByteArrayOutputStream outputStream = null;
99 | try {
100 | outputStream = new ByteArrayOutputStream();
101 | /*
102 | * 读取和压缩图片
103 | */
104 | bitmap.compress(CompressFormat.JPEG, 50, outputStream);
105 | String imgBase64 = new String(Base64.encode(outputStream.toByteArray(), Base64.DEFAULT));
106 | return imgBase64;
107 | } catch (Exception e) {
108 | AntiLog.e("disposeImage", e.toString());
109 | if (null != outputStream) {
110 | try {
111 | outputStream.close();
112 | } catch (IOException ex) {
113 | ex.printStackTrace();
114 | }
115 | }
116 | return "";
117 | }
118 | }
119 |
120 | /**
121 | * base64转为bitmap
122 | *
123 | * @param base64Data
124 | * base64的字符串
125 | * @return
126 | */
127 | public static Bitmap base64ToBitmap(String base64Data) {
128 | byte[] bytes = Base64.decode(base64Data, Base64.DEFAULT);
129 | return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/demo/src/main/java/dog/abcd/demo/BlankFragment.java:
--------------------------------------------------------------------------------
1 | package dog.abcd.demo;
2 |
3 | import android.content.Intent;
4 | import android.os.AsyncTask;
5 | import android.os.Bundle;
6 | import android.support.v4.app.Fragment;
7 | import android.util.Log;
8 | import android.view.LayoutInflater;
9 | import android.view.View;
10 | import android.view.ViewGroup;
11 | import android.widget.Button;
12 | import android.widget.ImageView;
13 | import android.widget.TextView;
14 |
15 | import com.android.volley.NetworkResponse;
16 | import com.android.volley.VolleyError;
17 |
18 | import dog.abcd.lib.alert.AstiAlert;
19 | import dog.abcd.lib.network.AntiNetwork;
20 | import dog.abcd.lib.network.AntiNetworkConvert;
21 | import dog.abcd.lib.network.AntiNetworkException;
22 | import dog.abcd.lib.network.AntiNetworkListener;
23 | import dog.abcd.lib.utils.AntiImageLoader;
24 | import dog.abcd.lib.watcher.AntiChangedListener;
25 | import dog.abcd.lib.watcher.AntiWatcher;
26 |
27 | public class BlankFragment extends Fragment implements AntiChangedListener {
28 |
29 | View view;
30 |
31 | TextView textView;
32 |
33 | ImageView imageView;
34 |
35 | Button button;
36 |
37 | @Override
38 | public View onCreateView(LayoutInflater inflater, ViewGroup container,
39 | Bundle savedInstanceState) {
40 | view = inflater.inflate(R.layout.fragment_blank, container, false);
41 | textView = view.findViewById(R.id.text);
42 | imageView = view.findViewById(R.id.image);
43 | button = view.findViewById(R.id.button);
44 | //注册消息通知
45 | AntiWatcher.register(this);
46 | init();
47 | return view;
48 | }
49 |
50 | @Override
51 | public void onDestroy() {
52 | super.onDestroy();
53 | //注销消息通知
54 | AntiWatcher.unregister(this);
55 | }
56 |
57 | public void init() {
58 | //加载网络图片
59 | AntiImageLoader.getInstance().display("http://img.weixinyidu.com/151212/c96ee601.jpg", imageView);
60 | //发起网络请求
61 | getBaiduNetwork().create().start((new AntiNetworkListener() {
62 | @Override
63 | public void success(AntiNetwork network, NetworkResponse result) {
64 | textView.setText(AntiNetworkConvert.convertResponseToString(result));
65 | }
66 |
67 | @Override
68 | public void error(AntiNetwork network, AntiNetworkException error) {
69 | AstiAlert.builder(network.getContext())
70 | .setTitle("错误信息")
71 | .setMessage(error.getMessage())
72 | .setTAG(BlankFragment.class.getSimpleName())
73 | .create().show();
74 | }
75 | }));
76 |
77 |
78 | //发起网络请求
79 | new AsyncTask
30 | *
31 | * @author Michael Lee
32 | * create at 2017/1/22 下午 13:26
33 | */
34 | class AntiNetworkStack extends HurlStack {
35 |
36 | private OkHttpClient okHttpClient;
37 |
38 | public AntiNetworkStack() {
39 | this(new OkHttpClient());
40 | }
41 |
42 | public AntiNetworkStack(OkHttpClient okHttpClient) {
43 | this(okHttpClient, null, 0);
44 | }
45 |
46 | /**
47 | * @param okHttpClient
48 | * @param context 用于生成证书,传null则不验证https
49 | * @param certID raw文件夹中https证书id,传0则不验证https
50 | */
51 | public AntiNetworkStack(OkHttpClient okHttpClient, Context context, int certID) {
52 | super(null, buildSSLSocketFactory(context, certID));
53 | this.okHttpClient = okHttpClient;
54 | }
55 |
56 | @Override
57 | protected HttpURLConnection createConnection(URL url) throws IOException {
58 | OkUrlFactory okUrlFactory = new OkUrlFactory(okHttpClient);
59 | return okUrlFactory.open(url);
60 | }
61 |
62 | private static SSLSocketFactory buildSSLSocketFactory(Context context,
63 | int certRawResId) {
64 | if (context == null || certRawResId == 0) {
65 | return null;
66 | }
67 | KeyStore keyStore = null;
68 | try {
69 | keyStore = buildKeyStore(context, certRawResId);
70 | } catch (KeyStoreException e) {
71 | e.printStackTrace();
72 | } catch (CertificateException e) {
73 | e.printStackTrace();
74 | } catch (NoSuchAlgorithmException e) {
75 | e.printStackTrace();
76 | } catch (IOException e) {
77 | e.printStackTrace();
78 | }
79 |
80 | String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
81 | TrustManagerFactory tmf = null;
82 | try {
83 | tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
84 | tmf.init(keyStore);
85 |
86 | } catch (NoSuchAlgorithmException e) {
87 | e.printStackTrace();
88 | } catch (KeyStoreException e) {
89 | e.printStackTrace();
90 | }
91 |
92 | SSLContext sslContext = null;
93 | try {
94 | sslContext = SSLContext.getInstance("TLS");
95 | } catch (NoSuchAlgorithmException e) {
96 | e.printStackTrace();
97 | }
98 | try {
99 | sslContext.init(null, tmf.getTrustManagers(), null);
100 | } catch (KeyManagementException e) {
101 | e.printStackTrace();
102 | }
103 |
104 | return sslContext.getSocketFactory();
105 |
106 | }
107 |
108 | private static KeyStore buildKeyStore(Context context, int certRawResId)
109 | throws KeyStoreException, CertificateException,
110 | NoSuchAlgorithmException, IOException {
111 | String keyStoreType = KeyStore.getDefaultType();
112 | KeyStore keyStore = KeyStore.getInstance(keyStoreType);
113 | keyStore.load(null, null);
114 |
115 | Certificate cert = readCert(context, certRawResId);
116 | keyStore.setCertificateEntry("ca", cert);
117 |
118 | return keyStore;
119 | }
120 |
121 | private static Certificate readCert(Context context, int certResourceID) {
122 | InputStream inputStream = context.getResources().openRawResource(
123 | certResourceID);
124 | Certificate ca = null;
125 |
126 | CertificateFactory cf = null;
127 | try {
128 | cf = CertificateFactory.getInstance("X.509");
129 | ca = cf.generateCertificate(inputStream);
130 |
131 | } catch (CertificateException e) {
132 | e.printStackTrace();
133 | }
134 | return ca;
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/lib/src/main/java/dog/abcd/lib/alert/AstiAlert.java:
--------------------------------------------------------------------------------
1 | package dog.abcd.lib.alert;
2 |
3 | import android.content.Context;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.View.OnClickListener;
7 | import android.widget.Button;
8 | import android.widget.TextView;
9 |
10 | import dog.abcd.lib.R;
11 |
12 | import dog.abcd.lib.utils.AntiDataUtils;
13 | import dog.abcd.lib.utils.AntiScreenUtils;
14 |
15 | /**
16 | * 带按钮提示框
17 | * 带一个按钮需要用户确认的重要信息的提示框
18 | *
19 | * @author Michael Lee
20 | * create at 2016年2月15日 上午9:21:02
21 | */
22 | public class AstiAlert extends AstiAlertBase {
23 |
24 | private View alertView;
25 | private Button btnCancel;
26 | private TextView tvMessage, tvTitle, tvMessageHide;
27 | private boolean cancelable;
28 |
29 | public static Builder builder(Context context) {
30 | return new Builder(context);
31 | }
32 |
33 | private AstiAlert(Context context, String TAG, String title, String message, String btnText, OnClickListener onClickListener, boolean cancelable) {
34 | super(context, TAG);
35 | alertView = initView(title, message, btnText, onClickListener);
36 | this.cancelable = cancelable;
37 | }
38 |
39 | protected View initView(String title, String message, String btnText, final OnClickListener onClickListener) {
40 | View view = LayoutInflater.from(getContext()).inflate(R.layout.layout_alert, null);
41 | tvMessage = (TextView) view.findViewById(R.id.dialog_message);
42 | tvTitle = (TextView) view.findViewById(R.id.dialog_title);
43 | if (!AntiDataUtils.isEmpty(title)) {
44 | tvTitle.setText(title);
45 | }
46 | tvMessageHide = (TextView) view.findViewById(R.id.dialog_message_hide);
47 | if (!AntiDataUtils.isEmpty(message)) {
48 | tvMessage.setText(message);
49 | tvMessageHide.setText(message);
50 | }
51 | tvMessageHide.setMaxHeight((int) (AntiScreenUtils.getScreenHeight(getContext()) / 2.5));
52 | // 为确认按钮添加事件,执行退出应用操作
53 | btnCancel = (Button) view.findViewById(R.id.dialog_ok);
54 | if (!AntiDataUtils.isEmpty(btnText)) {
55 | btnCancel.setText(btnText);
56 | }
57 | btnCancel.setOnClickListener(new OnClickListener() {
58 |
59 | @Override
60 | public void onClick(View v) {
61 | if (onClickListener != null) {
62 | onClickListener.onClick(v);
63 | }
64 | dismiss();
65 | }
66 |
67 | });
68 | return view;
69 | }
70 |
71 | @Override
72 | protected View createView() {
73 | return alertView;
74 | }
75 |
76 | @Override
77 | protected boolean cancelable() {
78 | return cancelable;
79 | }
80 |
81 |
82 | /**
83 | * 获取按钮
84 | *
85 | * @return
86 | */
87 | public Button getButton() {
88 | return btnCancel;
89 | }
90 |
91 | /**
92 | * 获取标题
93 | *
94 | * @return
95 | */
96 | public TextView getTvTitle() {
97 | return tvTitle;
98 | }
99 |
100 | /**
101 | * 获取提示文字控件
102 | *
103 | * @return
104 | */
105 | public TextView getTvMessage() {
106 | return tvMessage;
107 | }
108 |
109 | public static class Builder {
110 |
111 | public Builder(Context context) {
112 | this.context = context;
113 | }
114 |
115 | private Context context;
116 | private String TAG;
117 | private String title, message, btnStr;
118 | private boolean cancelable = false;
119 | private OnClickListener onClickListener;
120 |
121 | public Builder setTAG(String TAG) {
122 | this.TAG = TAG;
123 | return this;
124 | }
125 |
126 | public Builder setOnClickListener(OnClickListener onClickListener) {
127 | this.onClickListener = onClickListener;
128 | return this;
129 | }
130 |
131 | public Builder setTitle(String title) {
132 | this.title = title;
133 | return this;
134 | }
135 |
136 | public Builder setMessage(String message) {
137 | this.message = message;
138 | return this;
139 | }
140 |
141 | public Builder setBtnStr(String btnStr) {
142 | this.btnStr = btnStr;
143 | return this;
144 | }
145 |
146 | /**
147 | * 默认是FALSE
148 | *
149 | * @param cancelable
150 | * @return
151 | */
152 | public Builder setCancelable(boolean cancelable) {
153 | this.cancelable = cancelable;
154 | return this;
155 | }
156 |
157 | public AstiAlert create() {
158 | return new AstiAlert(context, TAG, title, message, btnStr, onClickListener, cancelable);
159 | }
160 |
161 | }
162 |
163 | }
164 |
--------------------------------------------------------------------------------
/lib/src/main/java/dog/abcd/lib/views/AstiClearEditText.java:
--------------------------------------------------------------------------------
1 | package dog.abcd.lib.views;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Context;
5 | import android.graphics.drawable.Drawable;
6 | import android.text.Editable;
7 | import android.text.TextWatcher;
8 | import android.util.AttributeSet;
9 | import android.view.MotionEvent;
10 | import android.view.View;
11 | import android.view.View.OnFocusChangeListener;
12 | import android.view.animation.Animation;
13 | import android.view.animation.CycleInterpolator;
14 | import android.view.animation.TranslateAnimation;
15 | import android.widget.EditText;
16 |
17 | import dog.abcd.lib.R;
18 |
19 | /**
20 | * 可清除内容输入框
21 | * 带删除按钮的输入框,在XML中使用的时候设置DrawableRight作为删除按钮使用,如果没有设置则引用默认图片
22 | *
23 | * @author Michael Lee
24 | * create at 2016年2月15日 上午9:20:20
25 | */
26 | @SuppressLint("ClickableViewAccessibility")
27 | public class AstiClearEditText extends EditText implements OnFocusChangeListener, TextWatcher {
28 | /**
29 | * 删除按钮的引用
30 | */
31 | private Drawable mClearDrawable;
32 |
33 | /**
34 | * 控件是否有焦点
35 | */
36 | private boolean hasFoucs;
37 |
38 | public Drawable getmClearDrawable() {
39 | return mClearDrawable;
40 | }
41 |
42 | public boolean isHasFoucs() {
43 | return hasFoucs;
44 | }
45 |
46 | /**
47 | * 构造方法
48 | *
49 | * @param context
50 | */
51 | public AstiClearEditText(Context context) {
52 | this(context, null);
53 | }
54 |
55 | public AstiClearEditText(Context context, AttributeSet attrs) {
56 | // 这里构造方法也很重要,不加这个很多属性不能再XML里面定义
57 | this(context, attrs, android.R.attr.editTextStyle);
58 | }
59 |
60 | public AstiClearEditText(Context context, AttributeSet attrs, int defStyle) {
61 | super(context, attrs, defStyle);
62 | init();
63 | }
64 |
65 | @SuppressWarnings("deprecation")
66 | private void init() {
67 | // 获取EditText的DrawableRight,假如没有设置我们就使用默认的图片
68 | mClearDrawable = getCompoundDrawables()[2];
69 | if (mClearDrawable == null) {
70 | // throw new
71 | // NullPointerException("You can add drawableRight attribute in
72 | // XML");
73 | mClearDrawable = getResources().getDrawable(R.drawable.text_clean);
74 | }
75 |
76 | mClearDrawable.setBounds(0, 0, mClearDrawable.getIntrinsicWidth(), mClearDrawable.getIntrinsicHeight());
77 | // 默认设置隐藏图标
78 | setClearIconVisible(false);
79 | // 设置焦点改变的监听
80 | setOnFocusChangeListener(this);
81 | // 设置输入框里面内容发生改变的监听
82 | addTextChangedListener(this);
83 | }
84 |
85 | /**
86 | * 因为我们不能直接给EditText设置点击事件,所以我们用记住我们按下的位置来模拟点击事件 当我们按下的位置 在 EditText的宽度 -
87 | * 图标到控件右边的间距 - 图标的宽度 和 EditText的宽度 - 图标到控件右边的间距之间我们就算点击了图标,竖直方向就没有考虑
88 | */
89 | @Override
90 | public boolean onTouchEvent(MotionEvent event) {
91 | if (event.getAction() == MotionEvent.ACTION_UP) {
92 | if (getCompoundDrawables()[2] != null) {
93 |
94 | boolean touchable = event.getX() > (getWidth() - getTotalPaddingRight())
95 | && (event.getX() < ((getWidth() - getPaddingRight())));
96 |
97 | if (touchable) {
98 | this.setText("");
99 | }
100 | }
101 | }
102 |
103 | return super.onTouchEvent(event);
104 | }
105 |
106 | /**
107 | * 当ClearEditText焦点发生变化的时候,判断里面字符串长度设置清除图标的显示与隐藏
108 | */
109 | @Override
110 | public void onFocusChange(View v, boolean hasFocus) {
111 | this.hasFoucs = hasFocus;
112 | if (hasFocus) {
113 | setClearIconVisible(getText().length() > 0);
114 | } else {
115 | setClearIconVisible(false);
116 | }
117 | }
118 |
119 | /**
120 | * 设置清除图标的显示与隐藏,调用setCompoundDrawables为EditText绘制上去
121 | *
122 | * @param visible
123 | */
124 | protected void setClearIconVisible(boolean visible) {
125 | Drawable right = visible ? mClearDrawable : null;
126 | setCompoundDrawables(getCompoundDrawables()[0], getCompoundDrawables()[1], right, getCompoundDrawables()[3]);
127 | }
128 |
129 | /**
130 | * 当输入框里面内容发生变化的时候回调的方法
131 | */
132 | @Override
133 | public void onTextChanged(CharSequence s, int start, int count, int after) {
134 | if (hasFoucs) {
135 | setClearIconVisible(s.length() > 0);
136 | }
137 | }
138 |
139 | @Override
140 | public void beforeTextChanged(CharSequence s, int start, int count, int after) {
141 | }
142 |
143 | @Override
144 | public void afterTextChanged(Editable s) {
145 |
146 | }
147 |
148 | /**
149 | * 设置晃动动画
150 | */
151 | public void setShakeAnimation() {
152 | this.setAnimation(shakeAnimation(5));
153 | }
154 |
155 | /**
156 | * 晃动动画
157 | *
158 | * @param counts 1秒钟晃动多少下
159 | * @return
160 | */
161 | public static Animation shakeAnimation(int counts) {
162 | Animation translateAnimation = new TranslateAnimation(0, 10, 0, 0);
163 | translateAnimation.setInterpolator(new CycleInterpolator(counts));
164 | translateAnimation.setDuration(1000);
165 | return translateAnimation;
166 | }
167 |
168 | }
169 |
--------------------------------------------------------------------------------
/lib/src/main/java/dog/abcd/lib/views/AstiCircleImageView.java:
--------------------------------------------------------------------------------
1 | package dog.abcd.lib.views;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.graphics.Canvas;
6 | import android.graphics.Color;
7 | import android.graphics.Paint;
8 | import android.graphics.PorterDuff;
9 | import android.graphics.PorterDuffXfermode;
10 | import android.graphics.RectF;
11 | import android.graphics.Xfermode;
12 | import android.graphics.drawable.Drawable;
13 | import android.graphics.drawable.NinePatchDrawable;
14 | import android.util.AttributeSet;
15 | import android.widget.ImageView;
16 |
17 | /**
18 | *
19 | * 自定义圆形图片框
20 | * 头像类型圆形图片框
21 | *
22 | * @author Michael Lee
23 | * create at 2016年2月15日 上午9:19:30
24 | */
25 | public class AstiCircleImageView extends ImageView {
26 |
27 | private static final Xfermode MASK_XFERMODE;
28 | // 显示图片
29 | private Bitmap mask;
30 | // 背景
31 | private Paint paint;
32 | // 边框粗细
33 | private int mBorderWidth = 3;
34 | // 边框颜色
35 | private int mBorderColor = Color.parseColor("#FFFFFF");
36 |
37 | private boolean useDefaultStyle = false;
38 |
39 | public static Xfermode getMaskXfermode() {
40 | return MASK_XFERMODE;
41 | }
42 |
43 | public Bitmap getMask() {
44 | return mask;
45 | }
46 |
47 | public Paint getPaint() {
48 | return paint;
49 | }
50 |
51 | public int getmBorderWidth() {
52 | return mBorderWidth;
53 | }
54 |
55 | public int getmBorderColor() {
56 | return mBorderColor;
57 | }
58 |
59 | public boolean isUseDefaultStyle() {
60 | return useDefaultStyle;
61 | }
62 |
63 | static {
64 | PorterDuff.Mode localMode = PorterDuff.Mode.DST_IN;
65 | MASK_XFERMODE = new PorterDuffXfermode(localMode);
66 | }
67 |
68 | /**
69 | * 构造方法
70 | *
71 | * @param paramContext
72 | */
73 | public AstiCircleImageView(Context paramContext) {
74 | super(paramContext);
75 | }
76 |
77 | public AstiCircleImageView(Context paramContext,
78 | AttributeSet paramAttributeSet) {
79 | this(paramContext, paramAttributeSet, 0);
80 | }
81 |
82 | public AstiCircleImageView(Context paramContext,
83 | AttributeSet paramAttributeSet, int paramInt) {
84 | super(paramContext, paramAttributeSet, paramInt);
85 | }
86 |
87 |
88 | public void setUseDefaultStyle(boolean useDefaultStyle) {
89 | this.useDefaultStyle = useDefaultStyle;
90 | }
91 |
92 | /**
93 | * 设置边框宽度和颜色
94 | * @param borderWidth
95 | * @param borderColor
96 | */
97 | public void setBorder(int borderWidth,int borderColor){
98 | this.mBorderColor = borderColor;
99 | this.mBorderWidth = borderWidth;
100 | invalidate();
101 | }
102 |
103 | @Override
104 | protected void onDraw(Canvas paramCanvas) {
105 | if (useDefaultStyle) {
106 | super.onDraw(paramCanvas);
107 | return;
108 | }
109 | final Drawable localDrawable = getDrawable();
110 | if (localDrawable == null)
111 | return;
112 | if (localDrawable instanceof NinePatchDrawable) {
113 | return;
114 | }
115 | if (this.paint == null) {
116 | final Paint localPaint = new Paint();
117 | localPaint.setFilterBitmap(false);
118 | localPaint.setAntiAlias(true);
119 | localPaint.setXfermode(MASK_XFERMODE);
120 | this.paint = localPaint;
121 | }
122 | final int width = getWidth();
123 | final int height = getHeight();
124 | /** 保存layer */
125 | int layer = paramCanvas.saveLayer(0.0F, 0.0F, width, height, null, 31);
126 | super.onDraw(paramCanvas);
127 | if ((this.mask == null) || (this.mask.isRecycled())) {
128 | this.mask = createOvalBitmap(width, height);
129 | }
130 | /** 将bitmap画到canvas上面 */
131 | paramCanvas.drawBitmap(this.mask, 0.0F, 0.0F, this.paint);
132 | /** 将画布复制到layer上 */
133 | paramCanvas.restoreToCount(layer);
134 | drawBorder(paramCanvas, width, height);
135 | }
136 |
137 | /**
138 | * 绘制最外面的边框
139 | *
140 | * @param canvas
141 | * @param width
142 | * @param height
143 | */
144 | private void drawBorder(Canvas canvas, final int width, final int height) {
145 | if (mBorderWidth == 0) {
146 | return;
147 | }
148 | final Paint mBorderPaint = new Paint();
149 | mBorderPaint.setStyle(Paint.Style.STROKE);
150 | mBorderPaint.setAntiAlias(true);
151 | mBorderPaint.setColor(mBorderColor);
152 | mBorderPaint.setStrokeWidth(mBorderWidth);
153 | /**
154 | * 坐标x:view宽度的一般 坐标y:view高度的一般 半径r:因为是view宽度的一半-border
155 | */
156 | canvas.drawCircle(width >> 1, height >> 1, (width >> 1) - mBorderWidth,
157 | mBorderPaint);
158 | canvas = null;
159 | }
160 |
161 | /**
162 | * 获取一个bitmap,目的是用来承载drawable;
163 | *
18 | * 首先在在Activity中首先需要重写onRequestPermissionsResult方法,在方法中调用此类中的handlePermission方法即可。
19 | * 在需要请求权限的时候调用此类中的requestPermission方法即可
20 | *
21 | * @author Michael Lee
22 | * create at 2017/2/23 下午 13:04
23 | */
24 | public class AntiPermissionUtil {
25 |
26 | private Map
15 | * 用于异步加载图片,需要在Application中调用init方法
16 | *
17 | * @author Michael Lee
18 | * create at 2016-1-28 上午10:41:53
19 | */
20 | public class AntiImageLoader {
21 | private DisplayImageOptions options;
22 | private ImageLoader imageLoader;
23 |
24 | private static AntiImageLoader instance;
25 |
26 | public static AntiImageLoader getInstance() {
27 | if (instance == null) {
28 | try {
29 | throw new Exception("please init AntiImageLoader in your application first");
30 | } catch (Exception e) {
31 | e.printStackTrace();
32 | }
33 | }
34 | return instance;
35 | }
36 |
37 | private AntiImageLoader() {
38 | }
39 |
40 | /**
41 | * 显示图片
42 | *
43 | * @param uri 图片地址
44 | * @param imageView 图片控件
45 | */
46 | public void display(String uri, ImageView imageView) {
47 | imageLoader.displayImage(uri, imageView, options);
48 | }
49 |
50 | /**
51 | * 显示图片
52 | *
53 | * @param uri 图片地址
54 | * @param imageView 图片控件
55 | * @param options 自定义option
56 | */
57 | public void display(String uri, ImageView imageView,
58 | DisplayImageOptions options) {
59 | imageLoader.displayImage(uri, imageView, options);
60 | }
61 |
62 | /**
63 | * 显示图片
64 | *
65 | * @param uri 图片地址
66 | * @param imageView 图片控件
67 | * @param options 自定义option
68 | * @param listenser 图片加载监听
69 | */
70 | public void display(String uri, ImageView imageView,
71 | DisplayImageOptions options, ImageLoadingListener listenser) {
72 | imageLoader.displayImage(uri, imageView, options, listenser);
73 | }
74 |
75 | /**
76 | * 需要在Application中初始化
77 | *
78 | * @param context 上下文
79 | * @param loadingImageId 加载过程中显示的图片
80 | * @param emptyImageId 加载内容为空显示的图片
81 | * @param failImageId 加载失败显示的图片
82 | */
83 | public static void init(Context context, int loadingImageId, int emptyImageId,
84 | int failImageId) {
85 | instance = new AntiImageLoader();
86 | instance.imageLoader = ImageLoader.getInstance();
87 | instance.imageLoader.init(ImageLoaderConfiguration.createDefault(context));
88 | instance.options = new DisplayImageOptions.Builder()
89 | // 加载过程中显示的图片
90 | .showImageOnLoading(loadingImageId)
91 | // 加载内容为空显示的图片
92 | .showImageForEmptyUri(emptyImageId)
93 | // 加载失败显示的图片
94 | .showImageOnFail(failImageId)
95 | // 是否緩存都內存中
96 | .cacheInMemory(true)
97 | // 是否緩存到sd卡上
98 | .cacheOnDisc(true).considerExifParams(true)
99 | .bitmapConfig(Bitmap.Config.RGB_565)
100 | .displayer(new FadeInBitmapDisplayer(200)).build();
101 | }
102 |
103 | /**
104 | * 需要在Application中初始化
105 | *
106 | * @param context 上下文
107 | * @param options 自定义Option
108 | */
109 | public static void init(Context context, DisplayImageOptions options) {
110 | instance = new AntiImageLoader();
111 | instance.imageLoader = ImageLoader.getInstance();
112 | instance.imageLoader.init(ImageLoaderConfiguration.createDefault(context));
113 | instance.options = options;
114 | }
115 |
116 | /**
117 | * 需要在Application中初始化
118 | *
119 | * @param context 上下文
120 | * 以默认Option显示
121 | */
122 | public static void init(Context context) {
123 | instance = new AntiImageLoader();
124 | instance.imageLoader = ImageLoader.getInstance();
125 | instance.imageLoader.init(ImageLoaderConfiguration.createDefault(context));
126 | instance.options = new DisplayImageOptions.Builder()
127 | // 加载过程中显示的图片
128 | .showImageOnLoading(null)
129 | // 加载内容为空显示的图片
130 | .showImageForEmptyUri(null)
131 | // 加载失败显示的图片
132 | .showImageOnFail(null)
133 | // 是否緩存都內存中
134 | .cacheInMemory(true)
135 | // 是否緩存到sd卡上
136 | .cacheOnDisc(true).considerExifParams(true)
137 | .bitmapConfig(Bitmap.Config.RGB_565)
138 | .displayer(new FadeInBitmapDisplayer(200)).build();
139 | }
140 |
141 | /**
142 | * 获取ImageLoader
143 | *
144 | * @return ImageLoader
145 | */
146 | public ImageLoader getImageLoader() {
147 | return imageLoader;
148 | }
149 |
150 | /**
151 | * 获取显示设置
152 | *
153 | * @return 显示设置
154 | */
155 | public DisplayImageOptions getDisplayImageOptions() {
156 | return options;
157 | }
158 | }
159 |
--------------------------------------------------------------------------------
/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 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/lib/src/main/java/dog/abcd/lib/alert/AstiAlertDialog.java:
--------------------------------------------------------------------------------
1 | package dog.abcd.lib.alert;
2 |
3 | import android.content.Context;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.View.OnClickListener;
7 | import android.widget.Button;
8 | import android.widget.TextView;
9 |
10 | import dog.abcd.lib.R;
11 |
12 | import dog.abcd.lib.utils.AntiDataUtils;
13 |
14 | /**
15 | * 自定义弹窗
16 | * 带两个按钮的提示窗口
17 | *
18 | * @author Michael Lee
19 | * create at 2016年2月15日 上午9:22:03
20 | */
21 | public class AstiAlertDialog extends AstiAlertBase {
22 | private Button btnLeft;
23 | private Button btnRight;
24 | private TextView tvTitle;
25 | private TextView tvMessage;
26 | private boolean cancelable;
27 | View alertView;
28 |
29 | public static Builder builder(Context context) {
30 | return new Builder( context );
31 | }
32 |
33 | private AstiAlertDialog(Context context, String TAG, String title, String message, String btnLeftStr, String btnRightStr, OnClickListener leftOnClick, OnClickListener rightOnClick, boolean cancelable) {
34 | super( context, TAG );
35 | alertView = initView( title, message, btnLeftStr, btnRightStr, leftOnClick, rightOnClick );
36 | this.cancelable = cancelable;
37 | }
38 |
39 | protected View initView(String title, String message, String btnLeftStr, String btnRightStr, final OnClickListener leftOnClick, final OnClickListener rightOnClick) {
40 | View view = LayoutInflater.from( getContext() ).inflate( R.layout.layout_alert_dialog, null );
41 | tvMessage = ((TextView) view
42 | .findViewById( R.id.tv_message ));
43 | if (!AntiDataUtils.isEmpty( message )) {
44 | tvMessage.setText( message );
45 | }
46 | tvTitle = ((TextView) view.findViewById( R.id.tv_title ));
47 | if (!AntiDataUtils.isEmpty( message )) {
48 | tvTitle.setText( title );
49 | }
50 | // 为确认按钮添加事件,执行退出应用操作
51 | btnRight = (Button) view.findViewById( R.id.btn_right );
52 | if (!AntiDataUtils.isEmpty( btnRightStr )) {
53 | btnRight.setText( btnRightStr );
54 | }
55 | btnRight.setOnClickListener( new OnClickListener() {
56 | @Override
57 | public void onClick(View v) {
58 | if (rightOnClick != null) {
59 | rightOnClick.onClick( v );
60 | }
61 | dismiss();
62 | }
63 | } );
64 | btnLeft = (Button) view.findViewById( R.id.btn_left );
65 | if (!AntiDataUtils.isEmpty( btnLeftStr )) {
66 | btnLeft.setText( btnLeftStr );
67 | }
68 | btnLeft.setOnClickListener( new OnClickListener() {
69 |
70 | @Override
71 | public void onClick(View v) {
72 | if (leftOnClick != null) {
73 | leftOnClick.onClick( v );
74 | }
75 | dismiss();
76 | }
77 |
78 | } );
79 | return view;
80 | }
81 |
82 | @Override
83 | protected View createView() {
84 | return alertView;
85 | }
86 |
87 | @Override
88 | protected boolean cancelable() {
89 | return cancelable;
90 | }
91 |
92 | public TextView getTvMessage() {
93 | return tvMessage;
94 | }
95 |
96 | public Button getBtnLeft() {
97 | return btnLeft;
98 | }
99 |
100 | public Button getBtnRight() {
101 | return btnRight;
102 | }
103 |
104 | public TextView getTvTitle() {
105 | return tvTitle;
106 | }
107 |
108 | public static class Builder {
109 | Context context;
110 |
111 | private Builder(Context context) {
112 | this.context = context;
113 | }
114 |
115 | private String TAG;
116 | private String title;
117 | private String message;
118 | private String leftBtnStr;
119 | private String rightBtnStr;
120 | private OnClickListener leftOnClick, rightOnClick;
121 | private boolean cancelable = false;
122 |
123 | public Builder setTAG(String TAG) {
124 | this.TAG = TAG;
125 | return this;
126 | }
127 |
128 | public Builder setTitle(String title) {
129 | this.title = title;
130 | return this;
131 | }
132 |
133 | public Builder setMessage(String message) {
134 | this.message = message;
135 | return this;
136 | }
137 |
138 | public Builder setLeftBtnStr(String leftBtnStr) {
139 | this.leftBtnStr = leftBtnStr;
140 | return this;
141 | }
142 |
143 | public Builder setRightBtnStr(String rightBtnStr) {
144 | this.rightBtnStr = rightBtnStr;
145 | return this;
146 | }
147 |
148 | public Builder setLeftOnClick(OnClickListener leftOnClick) {
149 | this.leftOnClick = leftOnClick;
150 | return this;
151 | }
152 |
153 | public Builder setRightOnClick(OnClickListener rightOnClick) {
154 | this.rightOnClick = rightOnClick;
155 | return this;
156 | }
157 |
158 | /**
159 | * 默认是FALSE
160 | *
161 | * @param cancelable
162 | * @return
163 | */
164 | public Builder setCancelable(boolean cancelable) {
165 | this.cancelable = cancelable;
166 | return this;
167 | }
168 |
169 | public AstiAlertDialog create() {
170 | return new AstiAlertDialog( context, TAG, title, message, leftBtnStr, rightBtnStr, leftOnClick, rightOnClick, cancelable );
171 | }
172 |
173 | }
174 |
175 | }
176 |
--------------------------------------------------------------------------------
/lib/src/main/java/dog/abcd/lib/views/AstiFlowLayout.java:
--------------------------------------------------------------------------------
1 | package dog.abcd.lib.views;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import android.annotation.SuppressLint;
7 | import android.content.Context;
8 | import android.util.AttributeSet;
9 | import android.view.View;
10 | import android.view.ViewGroup;
11 |
12 | /**
13 | * 流布局控件
14 | * 流布局自定义控件
15 | *
16 | * @author ramon
17 | * create at 2016年2月15日 下午12:02:16
18 | */
19 |
20 | public class AstiFlowLayout extends ViewGroup {
21 |
22 | // 存储所有子View
23 | private List> mAllChildViews = new ArrayList
>();
24 | // 每一行的高度
25 | private List
12 | * 包括时间的获取和转换
13 | *
14 | * @author Michael Lee
15 | * create at 2016-1-28 上午11:18:21
16 | */
17 | @SuppressLint("SimpleDateFormat")
18 | public class AntiDateUtils {
19 |
20 | private static final String TAG = "AntiDateUtils";
21 |
22 | public static final SimpleDateFormat yyyyMMdd = new SimpleDateFormat("yyyy-MM-dd");
23 | public static final SimpleDateFormat yyyyMMddHHmmss = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
24 | public static final SimpleDateFormat yyyyMMddForChina = new SimpleDateFormat("yyyy年MM月dd日");
25 | public static final SimpleDateFormat yyyyMMddHHmmssForChina = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
26 |
27 | private AntiDateUtils() {
28 |
29 | }
30 |
31 | /**
32 | * 获取系统时间
33 | *
34 | * @return Long类型
35 | */
36 | public static long getCurrentDate() {
37 | return new Date().getTime();
38 | }
39 |
40 | /**
41 | * string转long
42 | *
43 | * @param dateString 时间字符串
44 | * @param dateFormat SimpleDateFormat
45 | * @return 如果出错则返回当前日期的long,并打印错误信息
46 | */
47 | public static long convertToLong(String dateString, SimpleDateFormat dateFormat) {
48 | try {
49 | return dateFormat.parse(dateString).getTime();
50 | } catch (ParseException e) {
51 | e.printStackTrace();
52 | return getCurrentDate();
53 | }
54 | }
55 |
56 | /**
57 | * string转date
58 | *
59 | * @param dateString 时间字符串
60 | * @param dateFormat SimpleDateFormat
61 | * @return 如果出错则返回当前日期,并打印错误信息
62 | */
63 | public static Date convertToDate(String dateString, SimpleDateFormat dateFormat) {
64 | try {
65 | return dateFormat.parse(dateString);
66 | } catch (ParseException e) {
67 | e.printStackTrace();
68 | return new Date();
69 | }
70 | }
71 |
72 | /**
73 | * long转String
74 | *
75 | * @param dateLong 时间戳
76 | * @param dateFormat SimpleDateFormat
77 | * @return
78 | */
79 | public static String convertToString(long dateLong, SimpleDateFormat dateFormat) {
80 | return dateFormat.format(new Date(dateLong));
81 | }
82 |
83 | /**
84 | * date转String
85 | *
86 | * @param date 时间
87 | * @param dateFormat SimpleDateFormat
88 | * @return
89 | */
90 | public static String convertToString(Date date, SimpleDateFormat dateFormat) {
91 | return dateFormat.format(date);
92 | }
93 |
94 | /**
95 | * 得到本周周一
96 | *
97 | * @return
98 | */
99 | public static String getMondayOfThisWeek(SimpleDateFormat dateFormat) {
100 | Calendar c = Calendar.getInstance();
101 | // 一周第一天是否为星期天
102 | boolean isFirstSunday = (c.getFirstDayOfWeek() == Calendar.SUNDAY);
103 | // 获取周几
104 | int weekDay = c.get(Calendar.DAY_OF_WEEK);
105 | // 若一周第一天为星期天,则-1
106 | if (isFirstSunday) {
107 | weekDay = weekDay - 1;
108 | if (weekDay == 0) {
109 | weekDay = 7;
110 | }
111 | }
112 | int weekend = 1 - weekDay;
113 | c.add(Calendar.DATE, weekend);
114 | return convertToString(c.getTime(), dateFormat);
115 | }
116 |
117 | /**
118 | * 得到本周周日
119 | *
120 | * @return
121 | */
122 | public static String getSundayOfThisWeek(SimpleDateFormat dateFormat) {
123 | Calendar c = Calendar.getInstance();
124 | // 一周第一天是否为星期天
125 | boolean isFirstSunday = (c.getFirstDayOfWeek() == Calendar.SUNDAY);
126 | // 获取周几
127 | int weekDay = c.get(Calendar.DAY_OF_WEEK);
128 | // 若一周第一天为星期天,则-1
129 | if (isFirstSunday) {
130 | weekDay = weekDay - 1;
131 | if (weekDay == 0) {
132 | weekDay = 7;
133 | }
134 | }
135 | int weekend = 7 - weekDay;
136 | c.add(Calendar.DATE, weekend);
137 | return convertToString(c.getTime(), dateFormat);
138 | }
139 |
140 | /**
141 | * 获取当前一周的开头和结尾
142 | *
143 | * @return
144 | */
145 | public static String getThisWeek(SimpleDateFormat dateFormat) {
146 | return getMondayOfThisWeek(dateFormat) + "~" + getSundayOfThisWeek(dateFormat);
147 | }
148 |
149 | /**
150 | * 传入一天的值,获取昨天
151 | *
152 | * @param today 传入的时间需要和dateformat格式相同,返回相同格式
153 | * @param dateFormat
154 | * @return
155 | */
156 | public static String getYestoday(String today, SimpleDateFormat dateFormat) {
157 | long time = convertToLong(today, dateFormat);
158 | Calendar c = Calendar.getInstance();
159 | c.setTime(new java.sql.Date(time));
160 | c.add(Calendar.DAY_OF_YEAR, -1);
161 | return convertToString(c.getTime(), dateFormat);
162 | }
163 |
164 |
165 | /**
166 | * 传入一天的值,获取明天
167 | *
168 | * @param today 传入的时间需要和dateformat格式相同,返回相同格式
169 | * @param dateFormat
170 | * @return
171 | */
172 | public static String getTomorrow(String today, SimpleDateFormat dateFormat) {
173 | long time = convertToLong(today, dateFormat);
174 | Calendar c = Calendar.getInstance();
175 | c.setTime(new java.sql.Date(time));
176 | c.add(Calendar.DAY_OF_YEAR, 1);
177 | return convertToString(c.getTime(), dateFormat);
178 | }
179 |
180 | /**
181 | * 判断是否时间前后
182 | *
183 | * @param big
184 | * @param small
185 | * @param dateFormat
186 | * @return 返回TRUE则代表前面那一个时间更晚
187 | */
188 | public static boolean isBigger(String big, String small, SimpleDateFormat dateFormat) {
189 | long bigTime = convertToLong(big, dateFormat);
190 | long smallTime = convertToLong(small, dateFormat);
191 | return bigTime > smallTime;
192 | }
193 |
194 | }
--------------------------------------------------------------------------------
/lib/src/main/java/dog/abcd/lib/utils/AntiScreenUtils.java:
--------------------------------------------------------------------------------
1 | package dog.abcd.lib.utils;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.app.Activity;
5 | import android.content.Context;
6 | import android.content.res.Resources;
7 | import android.graphics.Bitmap;
8 | import android.graphics.Rect;
9 | import android.util.DisplayMetrics;
10 | import android.util.Log;
11 | import android.view.KeyCharacterMap;
12 | import android.view.KeyEvent;
13 | import android.view.View;
14 | import android.view.ViewConfiguration;
15 | import android.view.WindowManager;
16 |
17 | /**
18 | * 屏幕操作
19 | * 获取屏幕尺寸,截图,单位换算
20 | *
21 | * @author Michael Lee
22 | * create at 2016-1-28 下午1:47:48
23 | */
24 | public class AntiScreenUtils {
25 | private AntiScreenUtils() {
26 | /* cannot be instantiated */
27 | throw new UnsupportedOperationException( "cannot be instantiated" );
28 | }
29 |
30 | /**
31 | * 获取屏幕宽度
32 | *
33 | * @param context
34 | * @return
35 | */
36 | public static int getScreenWidth(Context context) {
37 | WindowManager wm = (WindowManager) context
38 | .getSystemService( Context.WINDOW_SERVICE );
39 | DisplayMetrics outMetrics = new DisplayMetrics();
40 | wm.getDefaultDisplay().getMetrics( outMetrics );
41 | return outMetrics.widthPixels;
42 | }
43 |
44 | /**
45 | * 获取屏幕高度
46 | *
47 | * @param context
48 | * @return
49 | */
50 | public static int getScreenHeight(Context context) {
51 | WindowManager wm = (WindowManager) context
52 | .getSystemService( Context.WINDOW_SERVICE );
53 | DisplayMetrics outMetrics = new DisplayMetrics();
54 | wm.getDefaultDisplay().getMetrics( outMetrics );
55 | return outMetrics.heightPixels;
56 | }
57 |
58 | /**
59 | * 获取状态栏高度
60 | *
61 | * @param context
62 | * @return
63 | */
64 | public static int getStatusHeight(Context context) {
65 |
66 | int statusHeight = -1;
67 | try {
68 | Class> clazz = Class.forName( "com.android.internal.R$dimen" );
69 | Object object = clazz.newInstance();
70 | int height = Integer.parseInt( clazz.getField( "status_bar_height" )
71 | .get( object ).toString() );
72 | statusHeight = context.getResources().getDimensionPixelSize( height );
73 | } catch (Exception e) {
74 | e.printStackTrace();
75 | }
76 | return statusHeight;
77 | }
78 |
79 | /**
80 | * 获取当前屏幕截图,包含状态栏
81 | *
82 | * @param activity
83 | * @return
84 | */
85 | public static Bitmap snapShotWithStatusBar(Activity activity) {
86 | View view = activity.getWindow().getDecorView();
87 | view.setDrawingCacheEnabled( true );
88 | view.buildDrawingCache();
89 | Bitmap bmp = view.getDrawingCache();
90 | int width = getScreenWidth( activity );
91 | int height = getScreenHeight( activity );
92 | Bitmap bp = null;
93 | bp = Bitmap.createBitmap( bmp, 0, 0, width, height );
94 | view.destroyDrawingCache();
95 | return bp;
96 |
97 | }
98 |
99 | /**
100 | * 获取当前屏幕截图,不包含状态栏
101 | *
102 | * @param activity
103 | * @return
104 | */
105 | public static Bitmap snapShotWithoutStatusBar(Activity activity) {
106 | View view = activity.getWindow().getDecorView();
107 | view.setDrawingCacheEnabled( true );
108 | view.buildDrawingCache();
109 | Bitmap bmp = view.getDrawingCache();
110 | Rect frame = new Rect();
111 | activity.getWindow().getDecorView().getWindowVisibleDisplayFrame( frame );
112 | int statusBarHeight = frame.top;
113 |
114 | int width = getScreenWidth( activity );
115 | int height = getScreenHeight( activity );
116 | Bitmap bp = null;
117 | bp = Bitmap.createBitmap( bmp, 0, statusBarHeight, width, height
118 | - statusBarHeight );
119 | view.destroyDrawingCache();
120 | return bp;
121 |
122 | }
123 |
124 | /**
125 | * 获取屏幕密度
126 | *
127 | * @param context
128 | * @return
129 | */
130 | public static float getScreenDensity(Context context) {
131 | return context.getResources().getDisplayMetrics().density;
132 | }
133 |
134 | /**
135 | * dp转px
136 | *
137 | * @param context
138 | * @param dp
139 | * @return
140 | */
141 | public static int dp2Px(Context context, float dp) {
142 | final float scale = context.getResources().getDisplayMetrics().scaledDensity;
143 | return (int) (dp * scale + 0.5f);
144 | }
145 |
146 | /**
147 | * px转dp
148 | *
149 | * @param context
150 | * @param px
151 | * @return
152 | */
153 | public static int px2Dp(Context context, float px) {
154 | final float scale = context.getResources().getDisplayMetrics().density;
155 | return (int) (px / scale + 0.5f);
156 | }
157 |
158 | /**
159 | * 获取当前手机是否有虚拟按键(NavigationBar)
160 | *
161 | * @param context
162 | * @return
163 | */
164 | @SuppressLint("NewApi")
165 | public static boolean checkDeviceHasNavigationBar(Context context) {
166 |
167 | //通过判断设备是否有返回键、菜单键(不是虚拟键,是手机屏幕外的按键)来确定是否有navigation bar
168 | boolean hasMenuKey = ViewConfiguration.get( context )
169 | .hasPermanentMenuKey();
170 | boolean hasBackKey = KeyCharacterMap
171 | .deviceHasKey( KeyEvent.KEYCODE_BACK );
172 |
173 | if (!hasMenuKey && !hasBackKey) {
174 | return true;
175 | }
176 | return false;
177 | }
178 |
179 |
180 | /**
181 | * 获取当前虚拟按键高度(NavigationBar),如果当前没有虚拟按键则返回0
182 | *
183 | * @param context
184 | * @return
185 | */
186 | public static int getNavigationBarHeight(Context context) {
187 | if (!checkDeviceHasNavigationBar( context )) {
188 | return 0;
189 | }
190 | Resources resources = context.getResources();
191 | int resourceId = resources.getIdentifier( "navigation_bar_height", "dimen", "android" );
192 | int height = resources.getDimensionPixelSize( resourceId );
193 | return height;
194 | }
195 | }
196 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AntiLib
2 |
3 | >在使用时需要在Application中初始化一些东西,包括AntiImageLoader(网络图片加载),AntiNetworkManager(网络请求)。
4 |
5 | ```gradle
6 | dependencies {
7 | implementation 'dog.abcd:antilib:1.4.1'
8 | implementation 'com.android.volley:volley:1.1.0'
9 | implementation 'com.squareup.okhttp3:okhttp:3.12.0'
10 | implementation 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
11 | implementation 'com.squareup.okhttp3:okhttp-urlconnection:3.11.0'
12 | }
13 | ```
14 |
15 | # 调用示例
16 | ## 网络请求的调用
17 | ### 网络网络请求的初始化
18 | ```java
19 | AntiNetworkManager.init(this, 0, new IDefaultParams() {
20 | @Override
21 | public Map
16 | * 用于监测数据的改变,分别调用register和unregister进行注册和注销,调用put***方法修改数据,调用get***方法获取数据
17 | *
18 | * @author Michael Lee
19 | * create at 2016-4-15 上午10:11:07
20 | */
21 | public class AntiWatcher {
22 | private AntiMessenger theMessenger = new AntiMessenger();
23 | private Map
13 | * 调用builder方法获取一个构造器,再调用create创建AntiNetwork类,再调用start或stop
14 | *
15 | * @author Michael Lee
16 | * create at 2017/1/22 下午 17:34
17 | */
18 | public class AntiNetwork {
19 |
20 | public enum Method {
21 | POST, GET
22 | }
23 |
24 | private Context context;
25 |
26 | private Method method;
27 |
28 | private String TAG;
29 |
30 | private String url;
31 |
32 | private Map
25 | * 维持一个请求队列,需要先在Application中初始化默认参数构造以及默认监听处理
26 | *
27 | * @author Michael Lee
28 | * create at 2017/1/22 下午 13:22
29 | */
30 | public class AntiNetworkManager {
31 | private static final String DEFAULT_CACHE_DIR = "AntiNetwork";
32 | private static AntiNetworkManager instance;
33 |
34 | /**
35 | * 默认参数与头的构造
36 | */
37 | public interface IDefaultParams {
38 | Map
25 | * 一些计算高度和UI显示的操作
26 | *
27 | * @author Michael Lee
28 | * create at 2016-1-28 下午1:54:42
29 | */
30 | public class AntiViewUtils {
31 |
32 | /**
33 | * 给文字设置删除线
34 | *
35 | * @param tView
36 | */
37 | public static void setDeleteLine(TextView tView) {
38 | tView.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG);
39 | tView.getPaint().setAntiAlias(true);// 抗锯齿
40 | }
41 |
42 | /**
43 | * 给文字设置下划线
44 | *
45 | * @param tView
46 | */
47 | public static void setUnderLine(TextView tView) {
48 | tView.getPaint().setFlags(Paint.UNDERLINE_TEXT_FLAG);
49 | tView.getPaint().setAntiAlias(true);// 抗锯齿
50 | }
51 |
52 | /**
53 | * 给文字设置粗体
54 | *
55 | * @param tView
56 | */
57 | public static void setBoldText(TextView tView) {
58 | tView.getPaint().setFakeBoldText(true);
59 | }
60 |
61 | /**
62 | * 设置ListView按照item来显示的高度
63 | *
64 | * @param listView
65 | */
66 | public static void setListViewHeightBasedOnChildren(ListView listView) {
67 | ListAdapter listAdapter = listView.getAdapter();
68 | if (listAdapter == null) {
69 | return;
70 | }
71 |
72 | int totalHeight = 0;
73 | for (int i = 0; i < listAdapter.getCount(); i++) {
74 | View view = listAdapter
75 | .getView(i, listView.getChildAt(i), listView);
76 | view.measure(0, 0);
77 | totalHeight += view.getMeasuredHeight();
78 | }
79 |
80 | ViewGroup.LayoutParams params = listView.getLayoutParams();
81 | params.height = totalHeight
82 | + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
83 |
84 | listView.setLayoutParams(params);
85 | }
86 |
87 | /**
88 | * 设置GridView根据item来显示高度
89 | *
90 | * @param gridView
91 | * @param cols
92 | * 每一行的个数
93 | */
94 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
95 | public static void setGridViewHeightBasedOnChildren(GridView gridView,
96 | int cols) {
97 | ListAdapter listAdapter = gridView.getAdapter();
98 | if (listAdapter == null) {
99 | return;
100 | }
101 |
102 | int totalHeight = 0;
103 | try {
104 | View view = listAdapter
105 | .getView(0, gridView.getChildAt(0), gridView);
106 | view.measure(0, 0);
107 | totalHeight = view.getMeasuredHeight();
108 | } catch (Exception e) {
109 | }
110 | int lines = (listAdapter.getCount() + (cols - 1)) / cols;
111 | int padding = 0;
112 | try {
113 | padding = gridView.getVerticalSpacing();
114 | } catch (Exception e) {
115 |
116 | }
117 | int totalPadding = padding * (lines + 1);
118 | ViewGroup.LayoutParams params = gridView.getLayoutParams();
119 | params.height = totalHeight * lines + totalPadding;
120 |
121 | gridView.setLayoutParams(params);
122 | }
123 |
124 | /**
125 | * 让一个输入框只能输入两位小数
126 | *
127 | * @param editText
128 | */
129 | public static void setPricePoint(final EditText editText) {
130 | editText.addTextChangedListener(new TextWatcher() {
131 |
132 | @Override
133 | public void onTextChanged(CharSequence s, int start, int before,
134 | int count) {
135 | if (s.toString().contains(".")) {
136 | if (s.length() - 1 - s.toString().indexOf(".") > 2) {
137 | s = s.toString().subSequence(0,
138 | s.toString().indexOf(".") + 3);
139 | editText.setText(s);
140 | editText.setSelection(s.length());
141 | }
142 | }
143 | if (s.toString().trim().substring(0).equals(".")) {
144 | s = "0" + s;
145 | editText.setText(s);
146 | editText.setSelection(2);
147 | }
148 |
149 | if (s.toString().startsWith("0")
150 | && s.toString().trim().length() > 1) {
151 | if (!s.toString().substring(1, 2).equals(".")) {
152 | editText.setText(s.subSequence(0, 1));
153 | editText.setSelection(1);
154 | return;
155 | }
156 | }
157 | }
158 |
159 | @Override
160 | public void beforeTextChanged(CharSequence s, int start, int count,
161 | int after) {
162 |
163 | }
164 |
165 | @Override
166 | public void afterTextChanged(Editable s) {
167 |
168 | }
169 |
170 | });
171 |
172 | }
173 |
174 | /**
175 | * 设置一个输入框输入的东西全部变成大写
176 | *
177 | * @param et
178 | */
179 | public static void setEditTextUpcase(EditText et) {
180 | et.setTransformationMethod(new AllCapTransformationMethod());
181 | }
182 |
183 | static class AllCapTransformationMethod extends
184 | ReplacementTransformationMethod {
185 |
186 | @Override
187 | protected char[] getOriginal() {
188 | char[] aa = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
189 | 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
190 | 'w', 'x', 'y', 'z' };
191 | return aa;
192 | }
193 |
194 | @Override
195 | protected char[] getReplacement() {
196 | char[] cc = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
197 | 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
198 | 'W', 'X', 'Y', 'Z' };
199 | return cc;
200 | }
201 |
202 | }
203 |
204 | /**
205 | * 图片宽度为match的时候获取应该显示的高度
206 | *
207 | * @param bitmap
208 | * @return
209 | */
210 | public static int getBitmapHeight(Bitmap bitmap, Context context) {
211 | float bitmapWidth = (float) bitmap.getWidth();
212 | float bitmapHeight = (float) bitmap.getHeight();
213 | float screenWidth = (float) AntiScreenUtils.getScreenWidth(context);
214 | return (int) (bitmapHeight * (screenWidth / bitmapWidth));
215 | }
216 |
217 | /**
218 | * 设置输入框最长输入长度
219 | *
220 | * @param editText
221 | * 输入框
222 | * @param maxLength
223 | * 长度
224 | */
225 | public static void setEditTextMaxLength(EditText editText, int maxLength) {
226 | editText.setFilters(new InputFilter[] { new InputFilter.LengthFilter(
227 | maxLength) });
228 | }
229 |
230 | /**
231 | * 设置输入框输入银行卡号码
232 | *
233 | * @param editText
234 | */
235 | public static void setEditBankcard(final EditText editText) {
236 | editText.addTextChangedListener(new TextWatcher() {
237 | int beforeTextLength = 0;
238 | int onTextLength = 0;
239 | boolean isChanged = false;
240 |
241 | int location = 0;// 记录光标的位置
242 | private char[] tempChar;
243 | private StringBuffer buffer = new StringBuffer();
244 | int konggeNumberB = 0;
245 |
246 | @Override
247 | public void onTextChanged(CharSequence s, int start, int before,
248 | int count) {
249 | onTextLength = s.length();
250 | buffer.append(s.toString());
251 | if (onTextLength == beforeTextLength || onTextLength <= 3
252 | || isChanged) {
253 | isChanged = false;
254 | return;
255 | }
256 | isChanged = true;
257 | }
258 |
259 | @Override
260 | public void beforeTextChanged(CharSequence s, int start, int count,
261 | int after) {
262 | beforeTextLength = s.length();
263 | if (buffer.length() > 0) {
264 | buffer.delete(0, buffer.length());
265 | }
266 | konggeNumberB = 0;
267 | for (int i = 0; i < s.length(); i++) {
268 | if (s.charAt(i) == ' ') {
269 | konggeNumberB++;
270 | }
271 | }
272 | }
273 |
274 | @Override
275 | public void afterTextChanged(Editable s) {
276 | // TODO Auto-generated method stub
277 | if (isChanged) {
278 | location = editText.getSelectionEnd();
279 | int index = 0;
280 | while (index < buffer.length()) {
281 | if (buffer.charAt(index) == ' ') {
282 | buffer.deleteCharAt(index);
283 | } else {
284 | index++;
285 | }
286 | }
287 |
288 | index = 0;
289 | int konggeNumberC = 0;
290 | while (index < buffer.length()) {
291 | if ((index == 4 || index == 9 || index == 14 || index == 19)) {
292 | buffer.insert(index, ' ');
293 | konggeNumberC++;
294 | }
295 | index++;
296 | }
297 |
298 | if (konggeNumberC > konggeNumberB) {
299 | location += (konggeNumberC - konggeNumberB);
300 | }
301 |
302 | tempChar = new char[buffer.length()];
303 | buffer.getChars(0, buffer.length(), tempChar, 0);
304 | String str = buffer.toString();
305 | if (location > str.length()) {
306 | location = str.length();
307 | } else if (location < 0) {
308 | location = 0;
309 | }
310 |
311 | editText.setText(str);
312 | try {
313 | Editable etable = editText.getText();
314 | Selection.setSelection(etable, location);
315 | } catch (Exception e) {
316 | Editable etable = editText.getText();
317 | Selection.setSelection(etable, etable.toString()
318 | .length());
319 | }
320 | isChanged = false;
321 |
322 | }
323 | }
324 |
325 | });
326 | }
327 |
328 | /**
329 | * 设置输入框不能输入emoji表情
330 | * @param editText
331 | */
332 | public static void setEditUnemojiable(final EditText editText){
333 | editText.addTextChangedListener(new TextWatcher() {
334 |
335 | private int cursorPos;
336 | private String inputAfterText;
337 | private boolean resetText;
338 | private Context context;
339 |
340 | public int getCursorPos() {
341 | return cursorPos;
342 | }
343 |
344 | public String getInputAfterText() {
345 | return inputAfterText;
346 | }
347 |
348 | public boolean isResetText() {
349 | return resetText;
350 | }
351 |
352 | public Context getTheContext() {
353 | return context;
354 | }
355 |
356 |
357 | @Override
358 | public void beforeTextChanged(CharSequence s, int start,
359 | int before, int count) {
360 | if (!resetText) {
361 | cursorPos = editText.getSelectionEnd(); // 这里用s.toString()而不直接用s是因为如果用s,
362 | // 那么,inputAfterText和s在内存中指向的是同一个地址,s改变了,
363 | // inputAfterText也就改变了,那么表情过滤就失败了
364 | inputAfterText = s.toString();
365 | }
366 |
367 | }
368 |
369 | @Override
370 | public void onTextChanged(CharSequence s, int start, int before,
371 | int count) {
372 | try {
373 | if (!resetText) {
374 | if (count >= 2) {// 表情符号的字符长度最小为2
375 | CharSequence input = s.subSequence(cursorPos,
376 | cursorPos + count);
377 | if (containsEmoji(input.toString())) {
378 | resetText = true;
379 | AntiToast.show(context, "不支持卖萌");
380 | // 是表情符号就将文本还原为输入表情符号之前的内容
381 | editText.setText(inputAfterText);
382 | CharSequence text = editText.getText();
383 | if (text instanceof Spannable) {
384 | Spannable spanText = (Spannable) text;
385 | Selection.setSelection(spanText,
386 | text.length());
387 | }
388 | }
389 | }
390 | } else {
391 | resetText = false;
392 | }
393 | } catch (Exception e) {
394 |
395 | }
396 | }
397 |
398 | @Override
399 | public void afterTextChanged(Editable editable) {
400 |
401 | }
402 |
403 | /**
404 | * 检测是否有emoji表情
405 | *
406 | * @param source
407 | * @return
408 | */
409 | public boolean containsEmoji(String source) {
410 | int len = source.length();
411 | for (int i = 0; i < len; i++) {
412 | char codePoint = source.charAt(i);
413 | if (!isEmojiCharacter(codePoint)) { // 如果不能匹配,则该字符是Emoji表情
414 | return true;
415 | }
416 | }
417 | return false;
418 | }
419 |
420 | /**
421 | * 判断是否是Emoji
422 | *
423 | * @param codePoint 比较的单个字符
424 | * @return
425 | */
426 | private boolean isEmojiCharacter(char codePoint) {
427 | return (codePoint == 0x0) || (codePoint == 0x9) || (codePoint == 0xA)
428 | || (codePoint == 0xD)
429 | || ((codePoint >= 0x20) && (codePoint <= 0xD7FF))
430 | || ((codePoint >= 0xE000) && (codePoint <= 0xFFFD))
431 | || ((codePoint >= 0x10000) && (codePoint <= 0x10FFFF));
432 | }
433 |
434 | });
435 | }
436 |
437 | }
438 |
--------------------------------------------------------------------------------
/lib/src/main/java/dog/abcd/lib/views/AstiBannerPager.java:
--------------------------------------------------------------------------------
1 | package dog.abcd.lib.views;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import dog.abcd.lib.utils.AntiImageLoader;
7 | import dog.abcd.lib.utils.AntiScreenUtils;
8 |
9 | import android.content.Context;
10 | import android.os.Handler;
11 | import android.support.v4.view.PagerAdapter;
12 | import android.support.v4.view.ViewPager;
13 | import android.support.v4.view.ViewPager.OnPageChangeListener;
14 | import android.util.AttributeSet;
15 | import android.view.Gravity;
16 | import android.view.View;
17 | import android.view.ViewGroup;
18 | import android.widget.ImageView;
19 | import android.widget.ImageView.ScaleType;
20 | import android.widget.LinearLayout;
21 | import android.widget.RelativeLayout;
22 |
23 | import dog.abcd.lib.R;
24 |
25 | /**
26 | *
27 | * 循环轮播
28 | * 先调用init方法初始化,再通过setBannerUrlList设置图片链接列表,最后setOnBannerClickListener设置监听事件
29 | *
30 | * @author Michael Lee
31 | * create at 2016-5-20 上午10:57:41
32 | */
33 | public class AstiBannerPager extends RelativeLayout {
34 |
35 | public AstiBannerPager(Context context) {
36 | this(context,null);
37 | }
38 |
39 | public AstiBannerPager(Context context, AttributeSet attrs) {
40 | this(context, attrs,0);
41 | }
42 |
43 | public AstiBannerPager(Context context, AttributeSet attrs, int defStyleAttr) {
44 | super(context, attrs, defStyleAttr);
45 | }
46 |
47 | private int circleBottomMargin = 10;
48 | private int circleSize = 8;
49 | private int circleBg = R.drawable.bg_circle_banner;
50 | private int circleBgOn = R.drawable.bg_circle_banner_on;
51 |
52 | private OnBannerClickListener onBannerClickListener;
53 |
54 | private ViewPager vPager;
55 | private LinearLayout lLayout;
56 | /**
57 | * 下面的几个点
58 | */
59 | private List