├── app ├── .gitignore ├── src │ └── main │ │ ├── res │ │ ├── drawable-xhdpi │ │ │ ├── ic_leaf.png │ │ │ ├── ic_loading.png │ │ │ └── ic_eletric_fan.png │ │ ├── layout │ │ │ ├── item_image_view.xml │ │ │ └── activity_main.xml │ │ ├── anim │ │ │ ├── delete_btn_hide.xml │ │ │ ├── delete_btn_show.xml │ │ │ ├── slide_out_bottom.xml │ │ │ └── slide_in_bottom.xml │ │ └── values │ │ │ ├── strings.xml │ │ │ ├── dimens.xml │ │ │ ├── styles.xml │ │ │ ├── attrs.xml │ │ │ └── colors.xml │ │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── user │ │ │ └── utils │ │ │ ├── util │ │ │ ├── VibrationUtils.java │ │ │ ├── ToastUtils.java │ │ │ ├── ServiceUtils.java │ │ │ ├── ActivityUtils.java │ │ │ ├── CrashUtils.java │ │ │ ├── DeviceUtils.java │ │ │ ├── CleanUtils.java │ │ │ ├── ClipboardUtils.java │ │ │ ├── EmptyUtils.java │ │ │ ├── ConstUtils.java │ │ │ ├── RegexUtils.java │ │ │ ├── BarUtils.java │ │ │ └── SizeUtils.java │ │ │ ├── weight │ │ │ ├── animator │ │ │ │ ├── AnimatorValue.java │ │ │ │ ├── AnimationFactory.java │ │ │ │ └── AnimatorValueImplements.java │ │ │ ├── swipyrefresh │ │ │ │ ├── SwipyRefreshLayoutDirection.java │ │ │ │ └── CircleImageView.java │ │ │ ├── numal │ │ │ │ ├── SelectTextView.java │ │ │ │ ├── CustomView.java │ │ │ │ ├── ProcessImageView.java │ │ │ │ └── SwipeSlideListener.java │ │ │ └── webView │ │ │ │ ├── ScrollWebView.java │ │ │ │ ├── MyWebChromeClient.java │ │ │ │ └── MyWebViewClient.java │ │ │ ├── ktutils │ │ │ ├── download │ │ │ │ ├── ProgressCallBack.kt │ │ │ │ └── DownloadObserver.kt │ │ │ ├── interfaces │ │ │ │ ├── ISubscriber.kt │ │ │ │ ├── IStringSubscriber.kt │ │ │ │ └── IBaseResultSubscriber.kt │ │ │ ├── base │ │ │ │ ├── BaseDownLoadObserver.kt │ │ │ │ ├── BaseStringObserver.kt │ │ │ │ └── BaseBaseResultObserver.kt │ │ │ ├── BaseObserver.kt │ │ │ └── bean │ │ │ │ └── BaseResult.kt │ │ │ ├── media │ │ │ ├── CustomGallery.java │ │ │ ├── DrawableUtils.java │ │ │ ├── GildeTools │ │ │ │ ├── GlideCircleTransform.java │ │ │ │ ├── GlideRoundTransform.java │ │ │ │ └── GlideUtils.java │ │ │ ├── VolleyTools │ │ │ │ └── ImageLoaderUtil.java │ │ │ ├── GLFont.java │ │ │ └── SampleSizeUtil.java │ │ │ ├── permission │ │ │ ├── annotation │ │ │ │ ├── OnMPermissionGranted.java │ │ │ │ ├── OnMPermissionDenied.java │ │ │ │ └── OnMPermissionNeverAskAgain.java │ │ │ └── util │ │ │ │ └── MPermissionUtil.java │ │ │ ├── request │ │ │ ├── okhttp │ │ │ │ └── Param.java │ │ │ ├── volley │ │ │ │ ├── BitmapCache.java │ │ │ │ ├── GsonRequest.java │ │ │ │ ├── XMLRequest.java │ │ │ │ ├── MyJsonObjectRequest.java │ │ │ │ ├── VolleyJsonObjectListenerInterface.java │ │ │ │ ├── VolleyListenerInterface.java │ │ │ │ └── VolleyErrorHelper.java │ │ │ └── xutils │ │ │ │ └── HttpUtilsOfxUtils.java │ │ │ ├── view │ │ │ ├── CommonUtils.java │ │ │ ├── ViewFindUtils.java │ │ │ ├── OpenQToChat.java │ │ │ ├── ComparatorUtil.java │ │ │ ├── AutoSpliText.java │ │ │ └── NumberFormat.java │ │ │ ├── sys │ │ │ ├── StatusBarView.java │ │ │ ├── DemoCache.java │ │ │ ├── SetTelCountTimer.java │ │ │ ├── ReflectionUtil.java │ │ │ ├── ObjectUtils.java │ │ │ └── ScreenUtil.java │ │ │ ├── storage │ │ │ ├── StorageType.java │ │ │ └── StorageUtil.java │ │ │ ├── string │ │ │ ├── MD5.java │ │ │ ├── AnimUtils.java │ │ │ ├── StringUtil.java │ │ │ ├── TextFormater.java │ │ │ ├── CyptoUtils.java │ │ │ └── HexDump.java │ │ │ ├── acache │ │ │ ├── UserUtils.java │ │ │ └── DataCacheManager.java │ │ │ ├── log │ │ │ └── LogUtil.java │ │ │ └── loaddrawable │ │ │ ├── LoadingView.java │ │ │ ├── LoadingDrawable.java │ │ │ ├── LoadingRendererFactory.java │ │ │ └── LoadingRenderer.java │ │ └── AndroidManifest.xml ├── proguard-rules.pro └── build.gradle ├── settings.gradle ├── img ├── how.png └── how2.png ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .idea └── vcs.xml ├── android └── content │ └── annotations.xml ├── .gitignore ├── gradle.properties └── gradlew.bat /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /img/how.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DaysLater/AndroidUtils/HEAD/img/how.png -------------------------------------------------------------------------------- /img/how2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DaysLater/AndroidUtils/HEAD/img/how2.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DaysLater/AndroidUtils/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_leaf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DaysLater/AndroidUtils/HEAD/app/src/main/res/drawable-xhdpi/ic_leaf.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_loading.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DaysLater/AndroidUtils/HEAD/app/src/main/res/drawable-xhdpi/ic_loading.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_eletric_fan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DaysLater/AndroidUtils/HEAD/app/src/main/res/drawable-xhdpi/ic_eletric_fan.png -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /android/content/annotations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_image_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Sep 21 15:56:40 CST 2018 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip 7 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/util/VibrationUtils.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.util; 2 | 3 | /** 4 | *
 5 |  *     author: Blankj
 6 |  *     blog  : http://blankj.com
 7 |  *     time  : 2016/9/29
 8 |  *     desc  :
 9 |  * 
10 | */ 11 | public class VibrationUtils { 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/weight/animator/AnimatorValue.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.weight.animator; 2 | 3 | import com.nineoldandroids.animation.ObjectAnimator; 4 | 5 | public interface AnimatorValue { 6 | public abstract ObjectAnimator getAnimator(); 7 | public abstract ObjectAnimator getBeforeAnimator(); 8 | public abstract void before(AnimatorValue beforeAnimatorValue); 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/ktutils/download/ProgressCallBack.kt: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.ktutils.download 2 | 3 | /** 4 | * 项目名称:AndroidUtils 5 | * 类描述:ProgressCallBack 描述: 6 | * 创建人:songlijie 7 | * 创建时间:2018/9/21 17:17 8 | * 邮箱:814326663@qq.com 9 | */ 10 | interface ProgressCallBack { 11 | fun onResponseProgressCallBack(bytesRead: Long, contentLength: Long, progress: Int, done: Boolean, filePath: String?) 12 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/ktutils/download/DownloadObserver.kt: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.ktutils.download 2 | 3 | import com.example.user.utils.ktutils.base.BaseDownLoadObserver 4 | 5 | /** 6 | * 项目名称:AndroidUtils 7 | * 类描述:DownloadObserver 描述: 8 | * 创建人:songlijie 9 | * 创建时间:2018/9/21 17:21 10 | * 邮箱:814326663@qq.com 11 | */ 12 | abstract class DownloadObserver : BaseDownLoadObserver() { 13 | override fun doOnError(errorMsg: String?) { 14 | 15 | } 16 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/weight/animator/AnimationFactory.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.weight.animator; 2 | 3 | public class AnimationFactory { 4 | public static AnimationFactory factory; 5 | 6 | public static AnimationFactory getInstance(){ 7 | if(factory==null){ 8 | return new AnimationFactory(); 9 | }else{ 10 | return factory; 11 | } 12 | } 13 | 14 | public AnimationEngine createEngine(){ 15 | return new AnimationEngine(); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/media/CustomGallery.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.media; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * 项目名称:FileUploadAndImageText 7 | * 类描述:CustomGallery 描述: CustomGallery 图片地址获取实体类 8 | * 创建人:songlijie 9 | * 创建时间:2016/12/2 14:02 10 | * 邮箱:814326663@qq.com 11 | */ 12 | public class CustomGallery implements Serializable { 13 | public String sdcardPath;//SD卡的路径 14 | public String mPath; //图片路径 15 | public long mTime;//拍照时间 16 | public String mName;//图片名称 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/permission/annotation/OnMPermissionGranted.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.permission.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * register a method invoked when permission requests are succeeded. 10 | */ 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Target(ElementType.METHOD) 13 | public @interface OnMPermissionGranted { 14 | int value(); 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/request/okhttp/Param.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.request.okhttp; 2 | 3 | /** 4 | * Created by ustc on 2016/6/30. 5 | */ 6 | public class Param { 7 | 8 | 9 | private String key; 10 | private String value; 11 | 12 | public Param(String key, String value) { 13 | this.key = key; 14 | this.value = value; 15 | } 16 | 17 | public String getKey() { 18 | return key; 19 | } 20 | 21 | public String getValue() { 22 | return value; 23 | } 24 | 25 | 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/permission/annotation/OnMPermissionDenied.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.permission.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * register a method invoked when permission requests are denied without check never ask again. 10 | */ 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Target(ElementType.METHOD) 13 | public @interface OnMPermissionDenied { 14 | int value(); 15 | } -------------------------------------------------------------------------------- /app/src/main/res/anim/delete_btn_hide.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/anim/delete_btn_show.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_out_bottom.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 9 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_in_bottom.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 10 | 11 | 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/permission/annotation/OnMPermissionNeverAskAgain.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.permission.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * register some methods handling the user's choice to permanently deny permissions checking never ask again. 10 | */ 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Target(ElementType.METHOD) 13 | public @interface OnMPermissionNeverAskAgain { 14 | int value(); 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/view/CommonUtils.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.view; 2 | 3 | /** 4 | * Created by Developer-X on 2016/5/23. 5 | * 6 | * 防止重复点击工具类 7 | */ 8 | public class CommonUtils { 9 | private static long lastClickTime; 10 | 11 | /** 12 | * 防止重复点击给个时间间隔 13 | * @return 14 | */ 15 | public static boolean isFastDoubleClick() { 16 | long time = System.currentTimeMillis(); 17 | long timeD = time - lastClickTime; 18 | if (0 < timeD && timeD < 800) { 19 | return true; 20 | } 21 | lastClickTime = time; 22 | return false; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/util/ToastUtils.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.util; 2 | 3 | import android.content.Context; 4 | import android.widget.Toast; 5 | 6 | /** 7 | *
 8 |  *     author: Blankj
 9 |  *     blog  : http://blankj.com
10 |  *     time  : 2016/9/29
11 |  *     desc  :
12 |  * 
13 | */ 14 | public class ToastUtils { 15 | public static void showLong(Context context, String msg) { 16 | Toast.makeText(context, msg, Toast.LENGTH_LONG).show(); 17 | } 18 | 19 | public static void showShort(Context context, String msg) { 20 | Toast.makeText(context, msg, Toast.LENGTH_SHORT); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the ART/Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | out/ 15 | 16 | # Gradle files 17 | .gradle/ 18 | build/ 19 | .idea 20 | 21 | # Local configuration file (sdk path, etc) 22 | local.properties 23 | 24 | # Proguard folder generated by Eclipse 25 | proguard/ 26 | 27 | # Log Files 28 | *.log 29 | 30 | # Android Studio Navigation editor temp files 31 | .navigation/ 32 | 33 | # Android Studio captures folder 34 | captures/ 35 | 36 | # Intellij 37 | *.iml 38 | # Keystore files 39 | *.jks 40 | gotye.keystore 41 | app/libs/ 42 | app/src/main/res/drawable/ 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/weight/swipyrefresh/SwipyRefreshLayoutDirection.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.weight.swipyrefresh; 2 | 3 | /** 4 | *下拉刷新的判断 5 | */ 6 | public enum SwipyRefreshLayoutDirection { 7 | 8 | TOP(0), // 只有下拉刷新 9 | BOTTOM(1), // 只有加载更多 10 | BOTH(2);// 全都有 11 | 12 | private int mValue; 13 | 14 | SwipyRefreshLayoutDirection(int value) { 15 | this.mValue = value; 16 | } 17 | 18 | public static SwipyRefreshLayoutDirection getFromInt(int value) { 19 | for (SwipyRefreshLayoutDirection direction : SwipyRefreshLayoutDirection 20 | .values()) { 21 | if (direction.mValue == value) { 22 | return direction; 23 | } 24 | } 25 | return BOTH; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Utils 4 | 确定 5 | 取消 6 | 文件浏览 7 | 未知大小 8 | 当前网络连接不稳定,数据加载缓慢,请稍候... 9 | 当前网络是wifi连接 10 | 当前网速较差,数据加载缓慢,请稍候... 11 | 无网络连接 12 | 连接服务器失败 13 | 网络异常,请稍后再试 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16dp 5 | 16dp 6 | 16sp 7 | 40dp 8 | 190dp 9 | 5dp 10 | 1dp 11 | 15dp 12 | 230dp 13 | 14 | 30dp 15 | 5dp 16 | 17 | 18 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | org.gradle.jvmargs=-Xmx1536m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/ktutils/interfaces/ISubscriber.kt: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.ktutils.interfaces 2 | 3 | import io.reactivex.disposables.Disposable 4 | 5 | 6 | 7 | /** 8 | * 项目名称:AndroidUtils 9 | * 类描述:ISubscriber 描述: 10 | * 创建人:songlijie 11 | * 创建时间:2018/9/21 15:31 12 | * 邮箱:814326663@qq.com 13 | */ 14 | interface ISubscriber { 15 | /** 16 | * doOnSubscribe 回调 17 | * 18 | * @param d Disposable 19 | */ 20 | fun doOnSubscribe(d: Disposable) 21 | 22 | /** 23 | * 错误回调 24 | * 25 | * @param errorMsg 错误信息 26 | */ 27 | fun doOnError(errorMsg: String?) 28 | 29 | /** 30 | * 成功回调 31 | * 32 | * @param t 泛型 33 | */ 34 | fun doOnNext(t: T) 35 | 36 | /** 37 | * 请求完成回调 38 | */ 39 | fun doOnCompleted() 40 | 41 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/sys/StatusBarView.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.sys; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.view.View; 6 | 7 | /** 8 | * ======================================== 9 | *

10 | * 版 权:dou361.com 版权所有 (C) 2015 11 | *

12 | * 作 者:陈冠明 13 | *

14 | * 个人网站:http://www.dou361.com 15 | *

16 | * 版 本:1.0 17 | *

18 | * 创建日期:2016/8/14 16:15 19 | *

20 | * 描 述: 21 | *

22 | *

23 | * 修订历史: 24 | *

25 | * ======================================== 26 | */ 27 | public class StatusBarView extends View { 28 | public StatusBarView(Context context, AttributeSet attrs) { 29 | super(context, attrs); 30 | } 31 | 32 | public StatusBarView(Context context) { 33 | super(context); 34 | } 35 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/ktutils/interfaces/IStringSubscriber.kt: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.ktutils.interfaces 2 | 3 | import io.reactivex.disposables.Disposable 4 | 5 | 6 | /** 7 | * 项目名称:AndroidUtils 8 | * 类描述:IStringSubscriber 描述: 9 | * 创建人:songlijie 10 | * 创建时间:2018/9/21 16:02 11 | * 邮箱:814326663@qq.com 12 | */ 13 | interface IStringSubscriber { 14 | /** 15 | * doOnSubscribe 回调 16 | * 17 | * @param d Disposable 18 | */ 19 | fun doOnSubscribe(d: Disposable) 20 | 21 | /** 22 | * 错误回调 23 | * 24 | * @param errorMsg 错误信息 25 | */ 26 | fun doOnError(errorMsg: String?) 27 | 28 | /** 29 | * 成功回调 30 | * 31 | * @param string data 32 | */ 33 | fun doOnNext(string: String) 34 | 35 | /** 36 | * 请求完成回调 37 | */ 38 | fun doOnCompleted() 39 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/sys/DemoCache.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.sys; 2 | 3 | import android.content.Context; 4 | 5 | /** 6 | * Created by jezhee on 2/20/15. 7 | */ 8 | public class DemoCache { 9 | 10 | private static Context context; 11 | 12 | private static String account; 13 | 14 | public static void clear() { 15 | account = null; 16 | } 17 | 18 | public static String getAccount() { 19 | return account; 20 | } 21 | 22 | public static void setAccount(String account) { 23 | DemoCache.account = account; 24 | } 25 | 26 | public static Context getContext() { 27 | if (context == null) { 28 | throw new RuntimeException("please setContext first!"); 29 | } 30 | return context; 31 | } 32 | 33 | public static void setContext(Context context) { 34 | DemoCache.context = context.getApplicationContext(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/ktutils/interfaces/IBaseResultSubscriber.kt: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.ktutils.interfaces 2 | 3 | import com.alibaba.fastjson.JSONObject 4 | import com.example.user.utils.ktutils.bean.BaseResult 5 | import io.reactivex.disposables.Disposable 6 | 7 | /** 8 | * 项目名称:AndroidUtils 9 | * 类描述:IBaseResultSubscriber 描述: 10 | * 创建人:songlijie 11 | * 创建时间:2018/9/21 16:00 12 | * 邮箱:814326663@qq.com 13 | */ 14 | interface IBaseResultSubscriber { 15 | /** 16 | * doOnSubscribe 回调 17 | * 18 | * @param d Disposable 19 | */ 20 | fun doOnSubscribe(d: Disposable) 21 | 22 | /** 23 | * 错误回调 24 | * 25 | * @param errorMsg 错误信息 26 | */ 27 | fun doOnError(errorMsg: String?) 28 | 29 | /** 30 | * 成功回调 31 | * 32 | * @param baseData 基础泛型 33 | */ 34 | fun doOnNext(baseData: BaseResult) 35 | 36 | /** 37 | * 请求完成回调 38 | */ 39 | fun doOnCompleted() 40 | 41 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/request/volley/BitmapCache.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.request.volley; 2 | 3 | import android.graphics.Bitmap; 4 | import android.support.v4.util.LruCache; 5 | 6 | import com.android.volley.toolbox.ImageLoader.ImageCache; 7 | 8 | public class BitmapCache implements ImageCache { 9 | private LruCache mCache; 10 | 11 | public BitmapCache() { 12 | int maxSize = 10 * 1024 * 1024; 13 | mCache = new LruCache(maxSize) { 14 | @Override 15 | protected int sizeOf(String key, Bitmap value) { 16 | return value.getRowBytes() * value.getHeight(); 17 | } 18 | }; 19 | } 20 | 21 | @Override 22 | public Bitmap getBitmap(String url) { 23 | return mCache.get(url); 24 | } 25 | 26 | @Override 27 | public void putBitmap(String url, Bitmap bitmap) { 28 | mCache.put(url, bitmap); 29 | } 30 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/ktutils/base/BaseDownLoadObserver.kt: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.ktutils.base 2 | 3 | import com.example.user.utils.ktutils.excertioncode.AllExcertion 4 | import io.reactivex.Observer 5 | import io.reactivex.disposables.Disposable 6 | import okhttp3.ResponseBody 7 | 8 | /** 9 | * 项目名称:AndroidUtils 10 | * 类描述:BaseDownLoadObserver 描述: 11 | * 创建人:songlijie 12 | * 创建时间:2018/9/21 17:07 13 | * 邮箱:814326663@qq.com 14 | */ 15 | abstract class BaseDownLoadObserver : Observer { 16 | override fun onComplete() { 17 | 18 | } 19 | 20 | override fun onSubscribe(d: Disposable) { 21 | } 22 | 23 | override fun onNext(t: ResponseBody) { 24 | } 25 | 26 | override fun onError(e: Throwable) { 27 | val message = AllExcertion().handleException(e).getErorMessage() 28 | setError(message) 29 | } 30 | 31 | /** 32 | * 失败回调 33 | * 34 | * @param errorMsg 错误信息 35 | */ 36 | protected abstract fun doOnError(errorMsg: String?) 37 | 38 | private fun setError(errorMsg: String?) { 39 | doOnError(errorMsg) 40 | } 41 | 42 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/ktutils/BaseObserver.kt: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.ktutils 2 | 3 | import com.example.user.utils.ktutils.excertioncode.AllExcertion 4 | import com.example.user.utils.ktutils.interfaces.ISubscriber 5 | import io.reactivex.Observer 6 | import io.reactivex.disposables.Disposable 7 | 8 | /** 9 | * 项目名称:AndroidUtils 10 | * 类描述:BaseObserver 描述: 11 | * 创建人:songlijie 12 | * 创建时间:2018/9/21 15:23 13 | * 邮箱:814326663@qq.com 14 | */ 15 | abstract class BaseObserver : Observer, ISubscriber { 16 | /** 17 | * 是否隐藏toast 18 | * 19 | * @return 20 | */ 21 | protected fun isHideToast(): Boolean { 22 | return false 23 | } 24 | 25 | 26 | override fun onComplete() { 27 | doOnCompleted() 28 | } 29 | 30 | override fun onSubscribe(d: Disposable) { 31 | doOnSubscribe(d) 32 | } 33 | 34 | override fun onNext(t: T) { 35 | doOnNext(t) 36 | } 37 | 38 | override fun onError(e: Throwable) { 39 | showError(e) 40 | } 41 | 42 | private fun showError(e: Throwable?) { 43 | val message = AllExcertion().handleException(e).getErorMessage() 44 | doOnError(message) 45 | } 46 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/ktutils/base/BaseStringObserver.kt: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.ktutils.base 2 | 3 | import com.example.user.utils.ktutils.excertioncode.AllExcertion 4 | import com.example.user.utils.ktutils.interfaces.IStringSubscriber 5 | import io.reactivex.Observer 6 | import io.reactivex.disposables.Disposable 7 | 8 | /** 9 | * 项目名称:AndroidUtils 10 | * 类描述:BaseStringObserver 描述: 11 | * 创建人:songlijie 12 | * 创建时间:2018/9/21 16:56 13 | * 邮箱:814326663@qq.com 14 | */ 15 | abstract class BaseStringObserver : Observer, IStringSubscriber { 16 | 17 | /** 18 | * 是否隐藏toast 19 | * 20 | * @return 21 | */ 22 | protected fun isHideToast(): Boolean { 23 | return false 24 | } 25 | 26 | 27 | override fun onComplete() { 28 | doOnCompleted() 29 | } 30 | 31 | override fun onSubscribe(d: Disposable) { 32 | doOnSubscribe(d) 33 | } 34 | 35 | override fun onNext(t: String) { 36 | doOnNext(t) 37 | } 38 | 39 | override fun onError(e: Throwable) { 40 | showError(e) 41 | } 42 | 43 | private fun showError(e: Throwable?) { 44 | val message = AllExcertion().handleException(e).getErorMessage() 45 | doOnError(message) 46 | } 47 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/ktutils/bean/BaseResult.kt: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.ktutils.bean 2 | 3 | import android.icu.lang.UCharacter.GraphemeClusterBreak.T 4 | 5 | 6 | /** 7 | * 项目名称:AndroidUtils 8 | * 类描述:BaseResult 描述: 基础数据格式 9 | * 创建人:songlijie 10 | * 创建时间:2018/9/21 17:00 11 | * 邮箱:814326663@qq.com 12 | */ 13 | class BaseResult { 14 | 15 | /** 16 | * 错误码 17 | */ 18 | private var code: Int = 0 19 | /** 20 | * 错误描述 21 | */ 22 | private var msg: String? = null 23 | 24 | /** 25 | * 数据 26 | */ 27 | private var data: T? = null 28 | 29 | fun getCode(): Int { 30 | return code 31 | } 32 | 33 | fun setCode(code: Int) { 34 | this.code = code 35 | } 36 | 37 | fun getMsg(): String? { 38 | return msg 39 | } 40 | 41 | fun setMsg(msg: String) { 42 | this.msg = msg 43 | } 44 | 45 | fun getData(): T? { 46 | return data 47 | } 48 | 49 | fun setData(data: T) { 50 | this.data = data 51 | } 52 | 53 | override fun toString(): String { 54 | return "BaseResult:{" + 55 | "code=" + code + 56 | ", msg='" + msg + '\''.toString() + 57 | ", data=" + data + 58 | '}'.toString() 59 | } 60 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/ktutils/base/BaseBaseResultObserver.kt: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.ktutils.base 2 | 3 | import com.alibaba.fastjson.JSONObject 4 | import com.example.user.utils.ktutils.bean.BaseResult 5 | import com.example.user.utils.ktutils.excertioncode.AllExcertion 6 | import com.example.user.utils.ktutils.interfaces.IBaseResultSubscriber 7 | import io.reactivex.Observer 8 | import io.reactivex.disposables.Disposable 9 | 10 | /** 11 | * 项目名称:AndroidUtils 12 | * 类描述:BaseBaseResultObserver 描述: 13 | * 创建人:songlijie 14 | * 创建时间:2018/9/21 16:06 15 | * 邮箱:814326663@qq.com 16 | */ 17 | abstract class BaseBaseResultObserver: IBaseResultSubscriber, Observer> { 18 | 19 | /** 20 | * 是否隐藏toast 21 | * 22 | * @return 23 | */ 24 | protected fun isHideToast(): Boolean { 25 | return false 26 | } 27 | 28 | override fun onComplete() { 29 | doOnCompleted() 30 | } 31 | 32 | 33 | override fun onSubscribe(d: Disposable) { 34 | doOnSubscribe(d) 35 | } 36 | 37 | override fun onNext(t: BaseResult) { 38 | doOnNext(t) 39 | } 40 | 41 | override fun onError(e: Throwable) { 42 | showError(e) 43 | } 44 | 45 | private fun showError(e: Throwable?) { 46 | val message = AllExcertion().handleException(e).getErorMessage() 47 | doOnError(message) 48 | } 49 | } -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 11 | 18 | 19 | 23 | 24 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/util/ServiceUtils.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.util; 2 | 3 | import android.app.ActivityManager; 4 | import android.app.ActivityManager.RunningServiceInfo; 5 | import android.content.ComponentName; 6 | import android.content.Context; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | *

12 |  *     author: Blankj
13 |  *     blog  : http://blankj.com
14 |  *     time  : 2016/8/2
15 |  *     desc  : 服务工具类
16 |  * 
17 | */ 18 | public class ServiceUtils { 19 | 20 | private ServiceUtils() { 21 | throw new UnsupportedOperationException("u can't instantiate me..."); 22 | } 23 | 24 | /** 25 | * 获取服务是否开启 26 | * 27 | * @param context 上下文 28 | * @param className 完整包名的服务类名 29 | * @return {@code true}: 是
{@code false}: 否 30 | */ 31 | public static boolean isRunningService(Context context, String className) { 32 | // 进程的管理者,活动的管理者 33 | ActivityManager activityManager = (ActivityManager) 34 | context.getSystemService(Context.ACTIVITY_SERVICE); 35 | // 获取正在运行的服务,最多获取1000个 36 | List runningServices = activityManager.getRunningServices(1000); 37 | // 遍历集合 38 | for (RunningServiceInfo runningServiceInfo : runningServices) { 39 | ComponentName service = runningServiceInfo.service; 40 | if (className.equals(service.getClassName())) { 41 | return true; 42 | } 43 | } 44 | return false; 45 | } 46 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/weight/numal/SelectTextView.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.weight.numal; 2 | 3 | import android.content.Context; 4 | import android.text.Selection; 5 | import android.text.Spannable; 6 | import android.util.AttributeSet; 7 | import android.view.MotionEvent; 8 | import android.widget.TextView; 9 | 10 | /** 11 | * Created by Mr.Yangxiufeng 12 | * DATE 2016/8/16 13 | * owspace 超字数显示的textview 点击显示/隐藏 14 | */ 15 | public class SelectTextView extends TextView{ 16 | public SelectTextView(Context context) { 17 | super(context); 18 | } 19 | 20 | public SelectTextView(Context context, AttributeSet attrs) { 21 | super(context, attrs); 22 | } 23 | 24 | public SelectTextView(Context context, AttributeSet attrs, int defStyleAttr) { 25 | super(context, attrs, defStyleAttr); 26 | } 27 | @Override 28 | public boolean dispatchTouchEvent(final MotionEvent event) { 29 | // FIXME simple workaround to https://code.google.com/p/android/issues/detail?id=191430 30 | int startSelection = getSelectionStart(); 31 | int endSelection = getSelectionEnd(); 32 | if (startSelection < 0 || endSelection < 0){ 33 | Selection.setSelection((Spannable) getText(), getText().length()); 34 | } else if (startSelection != endSelection) { 35 | if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { 36 | final CharSequence text = getText(); 37 | setText(null); 38 | setText(text); 39 | } 40 | } 41 | return super.dispatchTouchEvent(event); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/storage/StorageType.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.storage; 2 | 3 | public enum StorageType { 4 | TYPE_LOG(DirectoryName.LOG_DIRECTORY_NAME), 5 | TYPE_TEMP(DirectoryName.TEMP_DIRECTORY_NAME), 6 | TYPE_FILE(DirectoryName.FILE_DIRECTORY_NAME), 7 | TYPE_AUDIO(DirectoryName.AUDIO_DIRECTORY_NAME), 8 | TYPE_IMAGE(DirectoryName.IMAGE_DIRECTORY_NAME), 9 | TYPE_VIDEO(DirectoryName.VIDEO_DIRECTORY_NAME), 10 | TYPE_THUMB_IMAGE(DirectoryName.THUMB_DIRECTORY_NAME), 11 | TYPE_THUMB_VIDEO(DirectoryName.THUMB_DIRECTORY_NAME), 12 | ; 13 | private DirectoryName storageDirectoryName; 14 | private long storageMinSize; 15 | 16 | public String getStoragePath() { 17 | return storageDirectoryName.getPath(); 18 | } 19 | 20 | public long getStorageMinSize() { 21 | return storageMinSize; 22 | } 23 | 24 | StorageType(DirectoryName dirName) { 25 | this(dirName, StorageUtil.THRESHOLD_MIN_SPCAE); 26 | } 27 | 28 | StorageType(DirectoryName dirName, long storageMinSize) { 29 | this.storageDirectoryName = dirName; 30 | this.storageMinSize = storageMinSize; 31 | } 32 | 33 | enum DirectoryName { 34 | AUDIO_DIRECTORY_NAME("audio/"), 35 | DATA_DIRECTORY_NAME("data/"), 36 | FILE_DIRECTORY_NAME("file/"), 37 | LOG_DIRECTORY_NAME("log/"), 38 | TEMP_DIRECTORY_NAME("temp/"), 39 | IMAGE_DIRECTORY_NAME("image/"), 40 | THUMB_DIRECTORY_NAME("thumb/"), 41 | VIDEO_DIRECTORY_NAME("video/"), 42 | ; 43 | 44 | private String path; 45 | 46 | public String getPath() { 47 | return path; 48 | } 49 | 50 | private DirectoryName(String path) { 51 | this.path = path; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/string/MD5.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.string; 2 | 3 | import java.io.BufferedInputStream; 4 | import java.io.FileInputStream; 5 | import java.io.UnsupportedEncodingException; 6 | import java.security.MessageDigest; 7 | 8 | public class MD5 { 9 | 10 | public static String getStringMD5(String value) { 11 | if (value == null || value.trim().length() < 1) { 12 | return null; 13 | } 14 | try { 15 | return getMD5(value.getBytes("UTF-8")); 16 | } catch (UnsupportedEncodingException e) { 17 | throw new RuntimeException(e.getMessage(), e); 18 | } 19 | } 20 | 21 | public static String getMD5(byte[] source) { 22 | try { 23 | MessageDigest md5 = MessageDigest.getInstance("MD5"); 24 | return HexDump.toHex(md5.digest(source)); 25 | } catch (Exception e) { 26 | throw new RuntimeException(e.getMessage(), e); 27 | } 28 | } 29 | public static String getStreamMD5(String filePath) { 30 | String hash=null; 31 | byte[] buffer = new byte[4096]; 32 | BufferedInputStream in=null; 33 | try 34 | { 35 | MessageDigest md5 = MessageDigest.getInstance("MD5"); 36 | in = new BufferedInputStream(new FileInputStream(filePath)); 37 | int numRead = 0; 38 | while ((numRead = in.read(buffer)) > 0) { 39 | md5.update(buffer, 0, numRead); 40 | } 41 | in.close(); 42 | hash = HexDump.toHex(md5.digest()); 43 | } catch (Exception e) { 44 | e.printStackTrace(); 45 | } finally { 46 | if (in != null) { 47 | try { 48 | in.close(); 49 | } catch (Exception ex) { 50 | ex.printStackTrace(); 51 | } 52 | } 53 | } 54 | return hash; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/sys/SetTelCountTimer.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.sys; 2 | 3 | 4 | import android.os.CountDownTimer; 5 | import android.widget.Button; 6 | 7 | public class SetTelCountTimer extends CountDownTimer { 8 | public static final int TIME_COUNT = 61000;// 时间防止从100s开始显示(以倒计时120s为例子) 9 | private Button btn; 10 | private String endStrRid; 11 | /** 12 | * 参数 millisInFuture 倒计时总时间(如60S,120s等) 参数 countDownInterval 渐变时间(每次倒计1s) 13 | * 14 | * 参数 btn 点击的按钮(因为Button是Button子类,为了通用我的参数设置为Button) 15 | * 16 | * 参数 endStrRid 倒计时结束后,按钮对应显示的文字 17 | */ 18 | public SetTelCountTimer(long millisInFuture, long countDownInterval, 19 | Button btn, String endStrRid) { 20 | super(millisInFuture, countDownInterval); 21 | this.btn = btn; 22 | 23 | this.endStrRid = endStrRid; 24 | } 25 | 26 | /** 27 | * 28 | * 参数上面有注释 29 | */ 30 | public SetTelCountTimer(Button btn, String endStrRid) { 31 | super(TIME_COUNT, 1000); 32 | this.btn = btn; 33 | this.endStrRid = endStrRid; 34 | } 35 | 36 | public SetTelCountTimer(Button btn) { 37 | super(TIME_COUNT, 1000); 38 | this.btn = btn; 39 | 40 | this.endStrRid ="点击重新获取"; 41 | } 42 | 43 | public SetTelCountTimer(Button tv_varify, int normalColor, int timingColor) { 44 | this(tv_varify); 45 | 46 | } 47 | 48 | // 计时完毕时触发 49 | @Override 50 | public void onFinish() { 51 | 52 | btn.setText(endStrRid); 53 | btn.setEnabled(true); 54 | } 55 | 56 | // 计时过程显示 57 | @Override 58 | public void onTick(long millisUntilFinished) { 59 | 60 | btn.setEnabled(false); 61 | btn.setText("剩余"+millisUntilFinished / 1000 + "秒"); 62 | } 63 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/acache/UserUtils.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.acache; 2 | 3 | import android.content.Context; 4 | 5 | import java.io.BufferedReader; 6 | import java.io.File; 7 | import java.io.FileInputStream; 8 | import java.io.FileOutputStream; 9 | import java.io.InputStreamReader; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | 13 | public class UserUtils { 14 | // 保存用户信息的业务方法 15 | public static boolean saveInfo(Context context, String name, 16 | String word) { 17 | try { 18 | //得到nanme和word 19 | String result = name + "###" + word; 20 | //得到路徑 21 | String path = context.getFilesDir().getPath(); 22 | //创建file对象 23 | File file = new File(path, "user.text"); 24 | //获取文件输出流 25 | FileOutputStream fos = new FileOutputStream(file); 26 | //写入结果 27 | fos.write(result.getBytes()); 28 | //关闭流 29 | fos.close(); 30 | return true; 31 | } catch (Exception e) { 32 | e.printStackTrace(); 33 | return false; 34 | } 35 | } 36 | //读取用户信息的方法 37 | public static Map readInfo(Context context){ 38 | try{//创建map对象 39 | Map map = new HashMap(); 40 | //获取文件路径 41 | String path = context.getFilesDir().getPath(); 42 | //创建file对象 43 | File file = new File(path,"user.text"); 44 | //创建输入流 45 | FileInputStream fis = new FileInputStream(file); 46 | //创建读取方法 47 | BufferedReader br = new BufferedReader(new InputStreamReader(fis)); 48 | //获取读取的内容 49 | String line = br.readLine(); 50 | String[] split = line.split("###"); 51 | //获取name 52 | String name = split[0]; 53 | //获取password 54 | String word = split[1]; 55 | //把name和password存到map中 56 | map.put("name", name); 57 | map.put("word", word); 58 | //返回map 59 | return map; 60 | }catch(Exception e){ 61 | e.printStackTrace(); 62 | return null; 63 | } 64 | } 65 | } 66 | 67 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/weight/webView/ScrollWebView.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.weight.webView; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.util.Log; 6 | import android.webkit.WebView; 7 | 8 | /** 9 | * 项目名称:QianShan 10 | * 类描述:ScrollWebView 可滑动的webview 11 | * 创建人:slj 12 | * 创建时间:2016-8-22 11:58 13 | * 修改人:slj 14 | * 修改时间:2016-8-22 11:58 15 | * 修改备注: 16 | * 邮箱:slj@bjlingzhuo.com 17 | */ 18 | public class ScrollWebView extends WebView { 19 | public OnScrollChangeListener listener; 20 | 21 | public ScrollWebView(Context context, AttributeSet attrs, int defStyle) { 22 | super(context, attrs, defStyle); 23 | } 24 | 25 | public ScrollWebView(Context context, AttributeSet attrs) { 26 | super(context, attrs); 27 | } 28 | 29 | public ScrollWebView(Context context) { 30 | super(context); 31 | } 32 | 33 | @Override 34 | protected void onScrollChanged(int l, int t, int oldl, int oldt) { 35 | 36 | super.onScrollChanged(l, t, oldl, oldt); 37 | 38 | float webcontent = getContentHeight() * getScale();// webview的高度 39 | float webnow = getHeight() + getScrollY();// 当前webview的高度 40 | Log.i("TAG1", "webview.getScrollY()====>>" + getScrollY()); 41 | if (Math.abs(webcontent - webnow) < 1) { 42 | // 已经处于底端 43 | listener.onPageEnd(l, t, oldl, oldt); 44 | } else if (getScrollY() == 0) { 45 | // 已经处于顶端 46 | listener.onPageTop(l, t, oldl, oldt); 47 | } else { 48 | listener.onScrollChanged(l, t, oldl, oldt); 49 | } 50 | 51 | } 52 | 53 | public void setOnScrollChangeListener(OnScrollChangeListener listener) { 54 | 55 | this.listener = listener; 56 | 57 | } 58 | 59 | public interface OnScrollChangeListener { 60 | public void onPageEnd(int l, int t, int oldl, int oldt); 61 | public void onPageTop(int l, int t, int oldl, int oldt); 62 | public void onScrollChanged(int l, int t, int oldl, int oldt); 63 | 64 | } 65 | 66 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/media/DrawableUtils.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.media; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.drawable.BitmapDrawable; 5 | import android.graphics.drawable.Drawable; 6 | import android.graphics.drawable.GradientDrawable; 7 | import android.graphics.drawable.StateListDrawable; 8 | import android.os.Build; 9 | 10 | public class DrawableUtils { 11 | 12 | /** 13 | * 创建一个图片 14 | * @param contentColor 内部填充颜色 15 | * @param strokeColor 描边颜色 16 | * @param radius 圆角 17 | */ 18 | public static GradientDrawable createDrawable(int contentColor, int strokeColor, int radius) { 19 | GradientDrawable drawable = new GradientDrawable(); // 生成Shape 20 | drawable.setGradientType(GradientDrawable.RECTANGLE); // 设置矩形 21 | drawable.setColor(contentColor);// 内容区域的颜色 22 | drawable.setStroke(1, strokeColor); // 四周描边,描边后四角真正为圆角,不会出现黑色阴影。如果父窗体是可以滑动的,需要把父View设置setScrollCache(false) 23 | drawable.setCornerRadius(radius); // 设置四角都为圆角 24 | return drawable; 25 | } 26 | 27 | /** 28 | * 创建一个图片选择器 29 | * @param normalState 普通状态的图片 30 | * @param pressedState 按压状态的图片 31 | */ 32 | public static StateListDrawable createSelector(Drawable normalState, Drawable pressedState) { 33 | StateListDrawable bg = new StateListDrawable(); 34 | bg.addState(new int[]{android.R.attr.state_pressed, android.R.attr.state_enabled}, pressedState); 35 | bg.addState(new int[]{android.R.attr.state_enabled}, normalState); 36 | bg.addState(new int[]{}, normalState); 37 | return bg; 38 | } 39 | 40 | /** 获取图片的大小 */ 41 | public static int getDrawableSize(Drawable drawable) { 42 | if (drawable == null) { 43 | return 0; 44 | } 45 | Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap(); 46 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) { 47 | return bitmap.getByteCount(); 48 | } else { 49 | return bitmap.getRowBytes() * bitmap.getHeight(); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/media/GildeTools/GlideCircleTransform.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.media.GildeTools; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.BitmapShader; 6 | import android.graphics.Canvas; 7 | import android.graphics.Paint; 8 | 9 | import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; 10 | import com.bumptech.glide.load.resource.bitmap.BitmapTransformation; 11 | 12 | /** 13 | * Glide下载圆形图片的方法 14 | */ 15 | public class GlideCircleTransform extends BitmapTransformation { 16 | public GlideCircleTransform(Context context) { 17 | super(context); 18 | } 19 | 20 | @Override 21 | protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) { 22 | return circleCrop(pool, toTransform); 23 | } 24 | 25 | private static Bitmap circleCrop(BitmapPool pool, Bitmap source) { 26 | if (source == null) return null; 27 | 28 | int size = Math.min(source.getWidth(), source.getHeight()); 29 | int x = (source.getWidth() - size) / 2; 30 | int y = (source.getHeight() - size) / 2; 31 | 32 | // TODO this could be acquired from the pool too 33 | Bitmap squared = Bitmap.createBitmap(source, x, y, size, size); 34 | 35 | Bitmap result = pool.get(size, size, Bitmap.Config.ARGB_8888); 36 | if (result == null) { 37 | result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); 38 | } 39 | 40 | Canvas canvas = new Canvas(result); 41 | Paint paint = new Paint(); 42 | paint.setShader(new BitmapShader(squared, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP)); 43 | paint.setAntiAlias(true); 44 | float r = size / 2f; 45 | canvas.drawCircle(r, r, r, paint); 46 | return result; 47 | } 48 | 49 | @Override 50 | public String getId() { 51 | return getClass().getName(); 52 | } 53 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/request/volley/GsonRequest.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.request.volley; 2 | 3 | import com.android.volley.NetworkResponse; 4 | import com.android.volley.ParseError; 5 | import com.android.volley.Request; 6 | import com.android.volley.Response; 7 | import com.android.volley.toolbox.HttpHeaderParser; 8 | import com.google.gson.Gson; 9 | 10 | import java.io.UnsupportedEncodingException; 11 | 12 | /** 13 | * Gson方式请求类 14 | * @param 15 | */ 16 | public class GsonRequest extends Request { 17 | 18 | private final Response.Listener mListener; 19 | 20 | private Gson mGson; 21 | 22 | private Class mClass; 23 | 24 | public GsonRequest(int method, String url, Class clazz, Response.Listener listener, 25 | Response.ErrorListener errorListener) { 26 | super(method, url, errorListener); 27 | mGson = new Gson(); 28 | mClass = clazz; 29 | mListener = listener; 30 | } 31 | 32 | @Override 33 | public String getBodyContentType() { 34 | return super.getBodyContentType(); 35 | } 36 | 37 | public GsonRequest(String url, Class clazz, Response.Listener listener, 38 | Response.ErrorListener errorListener) { 39 | this(Method.GET, url, clazz, listener, errorListener); 40 | } 41 | 42 | @Override 43 | protected Response parseNetworkResponse(NetworkResponse response) { 44 | try { 45 | String jsonString = new String(response.data, 46 | HttpHeaderParser.parseCharset(response.headers)); 47 | return Response.success(mGson.fromJson(jsonString, mClass), 48 | HttpHeaderParser.parseCacheHeaders(response)); 49 | } catch (UnsupportedEncodingException e) { 50 | return Response.error(new ParseError(e)); 51 | } 52 | } 53 | 54 | @Override 55 | protected void deliverResponse(T response) { 56 | mListener.onResponse(response); 57 | } 58 | 59 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/view/ViewFindUtils.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.view; 2 | 3 | import android.util.SparseArray; 4 | import android.view.View; 5 | 6 | @SuppressWarnings({"unchecked"}) 7 | public class ViewFindUtils { 8 | /** 9 | * ViewHolder简洁写法,避免适配器中重复定义ViewHolder,减少代码量 用法: 10 | *

11 | *

12 |      * if (convertView == null)
13 |      * {
14 |      * 	convertView = View.inflate(context, R.layout.ad_demo, null);
15 |      * }
16 |      * TextView tv_demo = ViewHolderUtils.get(convertView, R.id.tv_demo);
17 |      * ImageView iv_demo = ViewHolderUtils.get(convertView, R.id.iv_demo);
18 |      * 
19 | */ 20 | public static T hold(View view, int id) { 21 | SparseArray viewHolder = (SparseArray) view.getTag(); 22 | if (viewHolder == null) { 23 | viewHolder = new SparseArray(); 24 | view.setTag(viewHolder); 25 | } 26 | View childView = viewHolder.get(id); 27 | if (childView == null) { 28 | childView = view.findViewById(id); 29 | viewHolder.put(id, childView); 30 | } 31 | return (T) childView; 32 | } 33 | /** 34 | * 替换holder里面的onClick方法 35 | * @param view 36 | * @param listener 37 | * @param ids 38 | */ 39 | public static void setOnHolderViewClickListener(View view, View.OnClickListener listener,int... ids){ 40 | for (int id: ids) { 41 | hold(view,id).setOnClickListener(listener); 42 | } 43 | } 44 | /** 45 | * 替代findviewById方法 46 | */ 47 | public static T find(View view, int id) { 48 | return (T) view.findViewById(id); 49 | } 50 | 51 | /** 52 | * 替换setonClick方法 53 | * @param view 54 | * @param listener 55 | * @param ids 56 | */ 57 | public static void setOnClickListener(View view, View.OnClickListener listener,int... ids){ 58 | for (int id: ids) { 59 | find(view,id).setOnClickListener(listener); 60 | } 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/log/LogUtil.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.log; 2 | 3 | public class LogUtil { 4 | public static final void init(String logFile, int level) { 5 | LogImpl.init(logFile, level); 6 | } 7 | 8 | public static final void v(String tag, String msg) { 9 | LogImpl.v(tag, buildMessage(msg)); 10 | } 11 | 12 | public static final void v(String tag, String msg, Throwable thr) { 13 | LogImpl.v(tag, buildMessage(msg), thr); 14 | } 15 | 16 | public static final void d(String tag, String msg) { 17 | LogImpl.d(tag, buildMessage(msg)); 18 | } 19 | 20 | public static final void d(String tag, String msg, Throwable thr) { 21 | LogImpl.d(tag, buildMessage(msg), thr); 22 | } 23 | 24 | public static final void i(String tag, String msg) { 25 | LogImpl.i(tag, buildMessage(msg)); 26 | } 27 | 28 | public static final void i(String tag, String msg, Throwable thr) { 29 | LogImpl.i(tag, buildMessage(msg), thr); 30 | } 31 | 32 | public static final void w(String tag, String msg) { 33 | LogImpl.w(tag, buildMessage(msg)); 34 | } 35 | 36 | public static final void w(String tag, String msg, Throwable thr) { 37 | LogImpl.w(tag, buildMessage(msg), thr); 38 | } 39 | 40 | public static final void w(String tag, Throwable thr) { 41 | LogImpl.w(tag, buildMessage(""), thr); 42 | } 43 | 44 | public static final void e(String tag, String msg) { 45 | LogImpl.e(tag, buildMessage(msg)); 46 | } 47 | 48 | public static final void e(String tag, String msg, Throwable thr) { 49 | LogImpl.e(tag, buildMessage(msg), thr); 50 | } 51 | 52 | public static final void ui(String msg) { 53 | LogImpl.i("ui", buildMessage(msg)); 54 | } 55 | 56 | public static final void res(String msg) { 57 | LogImpl.i("RES", buildMessage(msg)); 58 | } 59 | 60 | public static final void audio(String msg) { 61 | LogImpl.i("AudioRecorder", buildMessage(msg)); 62 | } 63 | 64 | public static String getLogFileName(String cat) { 65 | return LogImpl.getLogFileName(cat); 66 | } 67 | 68 | private static String buildMessage(String msg) { 69 | return msg; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/media/GildeTools/GlideRoundTransform.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.media.GildeTools; 2 | 3 | import android.content.Context; 4 | import android.content.res.Resources; 5 | import android.graphics.Bitmap; 6 | import android.graphics.BitmapShader; 7 | import android.graphics.Canvas; 8 | import android.graphics.Paint; 9 | import android.graphics.RectF; 10 | import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; 11 | import com.bumptech.glide.load.resource.bitmap.BitmapTransformation; 12 | 13 | /** 14 | * Gilde下载转换圆角的方法 默认圆角为4dp 可自定义圆角dp 15 | */ 16 | public class GlideRoundTransform extends BitmapTransformation { 17 | 18 | private static float radius = 0f; 19 | 20 | public GlideRoundTransform(Context context) { 21 | this(context, 4); 22 | } 23 | 24 | public GlideRoundTransform(Context context, int dp) { 25 | super(context); 26 | radius = Resources.getSystem().getDisplayMetrics().density * dp; 27 | } 28 | 29 | @Override 30 | protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) { 31 | return roundCrop(pool, toTransform); 32 | } 33 | 34 | private static Bitmap roundCrop(BitmapPool pool, Bitmap source) { 35 | if (source == null) return null; 36 | 37 | Bitmap result = pool.get(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888); 38 | if (result == null) { 39 | result = Bitmap.createBitmap(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888); 40 | } 41 | 42 | Canvas canvas = new Canvas(result); 43 | Paint paint = new Paint(); 44 | paint.setShader(new BitmapShader(source, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP)); 45 | paint.setAntiAlias(true); 46 | RectF rectF = new RectF(0f, 0f, source.getWidth(), source.getHeight()); 47 | canvas.drawRoundRect(rectF, radius, radius, paint); 48 | return result; 49 | } 50 | 51 | @Override 52 | public String getId() { 53 | return getClass().getName() + Math.round(radius); 54 | } 55 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/weight/animator/AnimatorValueImplements.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.weight.animator; 2 | 3 | import android.view.View; 4 | import com.nineoldandroids.animation.ObjectAnimator; 5 | import com.nineoldandroids.animation.TypeEvaluator; 6 | 7 | public class AnimatorValueImplements implements AnimatorValue{ 8 | 9 | private ObjectAnimator objectAnimator; 10 | private AnimatorValue beforeAnimatorValue; 11 | 12 | public AnimatorValueImplements(View view, String proName, int... values){ 13 | createProNameInt(view, proName,values); 14 | } 15 | 16 | public AnimatorValueImplements(View view, String proName, float... values){ 17 | createProNameFloat(view, proName,values); 18 | } 19 | 20 | public AnimatorValueImplements(Object object, TypeEvaluator typeEvaluator, String proName, Object... values){ 21 | createProNameObject(object, typeEvaluator, proName, values); 22 | } 23 | 24 | public ObjectAnimator createProNameInt(View view, String proName, int... values) { 25 | objectAnimator=ObjectAnimator.ofInt(view, proName, values); 26 | return objectAnimator; 27 | } 28 | 29 | public ObjectAnimator createProNameFloat(View view, String proName, float... values) { 30 | objectAnimator=ObjectAnimator.ofFloat(view, proName, values); 31 | return objectAnimator; 32 | } 33 | 34 | public ObjectAnimator createProNameObject(Object object, TypeEvaluator typeEvaluator, String proName, Object... values) { 35 | objectAnimator=ObjectAnimator.ofObject(object, proName, typeEvaluator, values); 36 | return objectAnimator; 37 | } 38 | 39 | @Override 40 | public void before(AnimatorValue beforeAnimatorValue){ 41 | this.beforeAnimatorValue=beforeAnimatorValue; 42 | } 43 | 44 | @Override 45 | public ObjectAnimator getAnimator() { 46 | if(objectAnimator!=null){ 47 | return objectAnimator; 48 | }else{ 49 | return new ObjectAnimator(); 50 | } 51 | 52 | } 53 | 54 | @Override 55 | public ObjectAnimator getBeforeAnimator() { 56 | if(beforeAnimatorValue!=null){ 57 | return beforeAnimatorValue.getAnimator(); 58 | }else{ 59 | return null; 60 | } 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/string/AnimUtils.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.string; 2 | 3 | import android.view.View; 4 | import com.example.user.utils.weight.animator.AnimationFactory; 5 | import com.example.user.utils.weight.animator.AnimatorValue; 6 | import com.example.user.utils.weight.animator.AnimatorValueImplements; 7 | import com.nineoldandroids.animation.Animator; 8 | 9 | /** 10 | * 项目名称:AndroidUtils 11 | * 类描述:AnimUtils 描述: 动画工具类 12 | * 创建人:songlijie 13 | * 创建时间:2017/5/17 14:19 14 | * 邮箱:814326663@qq.com 15 | */ 16 | public class AnimUtils { 17 | /** 18 | * 获取AnimatorValue对象 19 | * 20 | * @param animView 作用动画的view 21 | * @param proName Alpha ScaleX 22 | * @param duration 时长 23 | * @param values 如 new AnimatorValueImplements(im_guide,"ScaleX",1.5f,1.4f,1.3f,1.2f,1.1f,1f); 24 | * @return 25 | */ 26 | public static AnimatorValue getAnimatorValue(View animView, String proName, long duration, float... values) { 27 | AnimatorValue animatorValue = new AnimatorValueImplements(animView, proName, values); 28 | animatorValue.getAnimator().setDuration(duration); 29 | return animatorValue; 30 | } 31 | 32 | /** 33 | * 获取AnimatorValue对象 34 | * 35 | * @param animView 作用动画的view 36 | * @param proName Alpha ScaleX 37 | * @param duration 时长 38 | * @param values 如 new AnimatorValueImplements(im_guide,"ScaleX",1.5f,1.4f,1.3f,1.2f,1.1f,1f); 39 | * @return 40 | */ 41 | public static AnimatorValue getAnimatorValue(View animView, String proName, long duration, int... values) { 42 | AnimatorValue animatorValue = new AnimatorValueImplements(animView, proName, values); 43 | animatorValue.getAnimator().setDuration(duration); 44 | return animatorValue; 45 | } 46 | 47 | /** 48 | * 开启动画 49 | * 50 | * @param listener 51 | * @param animatorValues 52 | */ 53 | public static void startAnimator(Animator.AnimatorListener listener, AnimatorValue... animatorValues) { 54 | AnimationFactory.getInstance().createEngine().startTogetherByLink( 55 | listener, animatorValues); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/request/volley/XMLRequest.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.request.volley; 2 | 3 | import com.android.volley.NetworkResponse; 4 | import com.android.volley.ParseError; 5 | import com.android.volley.Request; 6 | import com.android.volley.Response; 7 | import com.android.volley.toolbox.HttpHeaderParser; 8 | 9 | import org.xmlpull.v1.XmlPullParser; 10 | import org.xmlpull.v1.XmlPullParserException; 11 | import org.xmlpull.v1.XmlPullParserFactory; 12 | 13 | import java.io.StringReader; 14 | import java.io.UnsupportedEncodingException; 15 | 16 | /** 17 | * xml方式请求类 18 | */ 19 | public class XMLRequest extends Request { 20 | 21 | private final Response.Listener mListener; 22 | 23 | public XMLRequest(int method, String url, Response.Listener listener, 24 | Response.ErrorListener errorListener) { 25 | super(method, url, errorListener); 26 | mListener = listener; 27 | } 28 | 29 | public XMLRequest(String url, Response.Listener listener, Response.ErrorListener errorListener) { 30 | this(Method.GET, url, listener, errorListener); 31 | } 32 | 33 | @Override 34 | protected Response parseNetworkResponse(NetworkResponse response) { 35 | try { 36 | String xmlString = new String(response.data, 37 | HttpHeaderParser.parseCharset(response.headers)); 38 | XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); 39 | XmlPullParser xmlPullParser = factory.newPullParser(); 40 | xmlPullParser.setInput(new StringReader(xmlString)); 41 | return Response.success(xmlPullParser, HttpHeaderParser.parseCacheHeaders(response)); 42 | } catch (UnsupportedEncodingException e) { 43 | return Response.error(new ParseError(e)); 44 | } catch (XmlPullParserException e) { 45 | return Response.error(new ParseError(e)); 46 | } 47 | } 48 | 49 | @Override 50 | protected void deliverResponse(XmlPullParser response) { 51 | mListener.onResponse(response); 52 | } 53 | 54 | } -------------------------------------------------------------------------------- /app/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/request/volley/MyJsonObjectRequest.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.request.volley; 2 | 3 | import android.util.Log; 4 | 5 | import com.android.volley.NetworkResponse; 6 | import com.android.volley.ParseError; 7 | import com.android.volley.Response; 8 | import com.android.volley.toolbox.HttpHeaderParser; 9 | import com.android.volley.toolbox.JsonRequest; 10 | 11 | import org.json.JSONException; 12 | import org.json.JSONObject; 13 | 14 | import java.io.UnsupportedEncodingException; 15 | 16 | public class MyJsonObjectRequest extends JsonRequest { 17 | 18 | private static final String TAG = MyJsonObjectRequest.class.getSimpleName(); 19 | String stringRequest; 20 | 21 | /** 22 | * 这里的method必须是Method.POST,也就是必须带参数。 23 | * 如果不想带参数,可以用JsonObjectRequest,给它构造参数传null。GET方式请求。 24 | * @param post 25 | * @param url 26 | * @param stringRequest 格式应该是 "key1=value1&key2=value2" 27 | * @param listener 28 | * @param errorListener 29 | */ 30 | public MyJsonObjectRequest(int post, String url, String stringRequest, 31 | Response.Listener listener, Response.ErrorListener errorListener) { 32 | super(Method.POST, url, stringRequest, listener, errorListener); 33 | this.stringRequest = stringRequest; 34 | } 35 | 36 | @Override 37 | public String getBodyContentType() { 38 | return "application/x-www-form-urlencoded; charset=" + getParamsEncoding(); 39 | } 40 | 41 | @Override 42 | protected Response parseNetworkResponse(NetworkResponse response) { 43 | try { 44 | String jsonString = new String(response.data, 45 | HttpHeaderParser.parseCharset(response.headers, PROTOCOL_CHARSET)); 46 | Log.d(TAG,"response.headers:"+response.headers); 47 | return Response.success(new JSONObject(jsonString), 48 | HttpHeaderParser.parseCacheHeaders(response)); 49 | } catch (UnsupportedEncodingException e) { 50 | return Response.error(new ParseError(e)); 51 | } catch (JSONException je) { 52 | return Response.error(new ParseError(je)); 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/request/volley/VolleyJsonObjectListenerInterface.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.request.volley; 2 | 3 | import android.content.Context; 4 | 5 | import com.android.volley.Response; 6 | import com.android.volley.VolleyError; 7 | 8 | /** 9 | * Created by Administrator on 2016/7/4. 10 | */ 11 | public abstract class VolleyJsonObjectListenerInterface { 12 | public Context mContext; 13 | public static Response.ErrorListener mErrorListener; 14 | public static Response.Listener JSONObject; 15 | public static VolleyJsonObjectListenerInterface volleyJsonListenerInterface; 16 | public VolleyJsonObjectListenerInterface(){ 17 | Response.Listener responseObjListener; 18 | Response.ErrorListener errorObjListener; 19 | } 20 | public VolleyJsonObjectListenerInterface(Context context, VolleyJsonObjectListenerInterface volleyJsonListenerInterface) { 21 | this.mContext = context; 22 | this.volleyJsonListenerInterface = volleyJsonListenerInterface; 23 | } 24 | public VolleyJsonObjectListenerInterface(Context context, Response.Listener responseObjListener, Response.ErrorListener errorObjListener) { 25 | this.mContext = context; 26 | this.mErrorListener = errorObjListener; 27 | this.JSONObject = responseObjListener; 28 | } 29 | // 请求成功时的回调函数 30 | public abstract void onMySuccessObj(org.json.JSONObject result); 31 | // 请求失败时的回调函数 32 | public abstract void onMyErrorObj(VolleyError error); 33 | // 创建请求的事件监听 34 | public Response.Listener responseObjListener() { 35 | JSONObject = new Response.Listener() { 36 | @Override 37 | public void onResponse(org.json.JSONObject s) { 38 | onMySuccessObj(s); 39 | } 40 | }; 41 | return JSONObject; 42 | } 43 | // 创建请求失败的事件监听 44 | public Response.ErrorListener errorObjListener() { 45 | mErrorListener = new Response.ErrorListener() { 46 | @Override 47 | public void onErrorResponse(VolleyError volleyError) { 48 | onMyErrorObj(volleyError); 49 | } 50 | }; 51 | return mErrorListener; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/request/volley/VolleyListenerInterface.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.request.volley; 2 | 3 | import android.content.Context; 4 | 5 | import com.android.volley.Response; 6 | import com.android.volley.VolleyError; 7 | 8 | public abstract class VolleyListenerInterface { 9 | private Context mContext; 10 | private Response.Listener mListener; 11 | private Response.ErrorListener mErrorListener; 12 | private VolleyListenerInterface volleyListenerInterface; 13 | 14 | /** 15 | * 初始化接口建议不要使用 16 | * @param context 17 | * @param listener 18 | * @param errorListener 19 | */ 20 | public VolleyListenerInterface(Context context, Response.Listener listener, Response.ErrorListener errorListener) { 21 | this.mContext = context; 22 | this.mErrorListener = errorListener; 23 | this.mListener = listener; 24 | } 25 | 26 | /** 27 | * 初始化接口 不建议使用 28 | * @param context 29 | * @param listenerInterface 30 | */ 31 | public VolleyListenerInterface(Context context, VolleyListenerInterface listenerInterface) { 32 | this.mContext = context; 33 | this.volleyListenerInterface = listenerInterface; 34 | } 35 | 36 | /** 37 | * 初始化接口,建议直接使用 38 | */ 39 | public VolleyListenerInterface(){ 40 | Response.Listener listener; 41 | Response.ErrorListener errorListener; 42 | } 43 | 44 | // 请求成功时的回调函数 45 | public abstract void onMySuccess(String result); 46 | // 请求失败时的回调函数 47 | public abstract void onMyError(VolleyError error); 48 | 49 | // 创建请求的事件监听 50 | public Response.Listener responseListener() { 51 | mListener = new Response.Listener() { 52 | @Override 53 | public void onResponse(String s) { 54 | onMySuccess(s); 55 | } 56 | }; 57 | return mListener; 58 | } 59 | // 创建请求失败的事件监听 60 | public Response.ErrorListener errorListener() { 61 | mErrorListener = new Response.ErrorListener() { 62 | @Override 63 | public void onErrorResponse(VolleyError volleyError) { 64 | onMyError(volleyError); 65 | } 66 | }; 67 | return mErrorListener; 68 | } 69 | 70 | } -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | #ff313131 7 | #ff030303 8 | #ff9b9b9b 9 | #fff8f7f5 10 | #ff000000 11 | #ff000000 12 | #ffc0c0c0 13 | 14 | #ff990000 15 | #ff009900 16 | #ff000099 17 | #ffffffff 18 | #ff000000 19 | #ff212324 20 | 21 | #ffc6c5c4 22 | #ff727272 23 | #ffd4d4d4 24 | #ffffffff 25 | 26 | #ff000000 27 | #ff000000 28 | #ffc3c3c3 29 | #ff000000 30 | #ffebe1c4 31 | #ff000000 32 | #ffad8a5a 33 | 34 | #FF9600 35 | #02D1AC 36 | #FFD200 37 | #bcd9da 38 | #FF3892 39 | #6c6868 40 | 41 | @color/orange 42 | @color/aqua 43 | @color/yellow 44 | @color/blue 45 | @color/green 46 | @color/pink 47 | 48 | 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/weight/numal/CustomView.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.weight.numal; 2 | 3 | 4 | import android.annotation.SuppressLint; 5 | import android.content.Context; 6 | import android.graphics.Canvas; 7 | import android.graphics.Color; 8 | import android.graphics.Paint; 9 | import android.graphics.Rect; 10 | import android.util.AttributeSet; 11 | import android.view.View; 12 | 13 | /** 14 | * 自定义带进度的CustomView 相当于蒙版view 15 | */ 16 | public class CustomView extends View { 17 | 18 | private Paint mPaint;//画笔 19 | 20 | Context context; 21 | private boolean isfinished = false; 22 | int progress = 0; 23 | 24 | public CustomView(Context context) { 25 | this(context, null); 26 | } 27 | 28 | public CustomView(Context context, AttributeSet attrs) { 29 | this(context, attrs, 0); 30 | } 31 | 32 | public CustomView(Context context, AttributeSet attrs, int defStyleAttr) { 33 | super(context, attrs, defStyleAttr); 34 | this.context = context; 35 | mPaint = new Paint(); 36 | } 37 | 38 | @SuppressLint("DrawAllocation") 39 | @Override 40 | protected void onDraw(Canvas canvas) { 41 | super.onDraw(canvas); 42 | if (isfinished) { 43 | return; 44 | } 45 | mPaint.setAntiAlias(true); // 消除锯齿 46 | mPaint.setStyle(Paint.Style.FILL); 47 | 48 | mPaint.setColor(Color.parseColor("#70000000"));//半透明 49 | canvas.drawRect(0, 0, getWidth(), getHeight() - getHeight() * progress / 100, mPaint); 50 | 51 | mPaint.setColor(Color.parseColor("#00000000"));//全透明 52 | canvas.drawRect(0, getHeight() - getHeight() * progress / 100, getWidth(), getHeight(), mPaint); 53 | 54 | mPaint.setTextSize(30); 55 | mPaint.setColor(Color.parseColor("#FFFFFF")); 56 | mPaint.setStrokeWidth(2); 57 | Rect rect = new Rect(); 58 | mPaint.getTextBounds("100%", 0, "100%".length(), rect);//确定文字的宽度 59 | canvas.drawText(progress + "%", getWidth() / 2 - rect.width() / 2, getHeight() / 2, mPaint); 60 | 61 | } 62 | 63 | public void setProgress(int progress) { 64 | this.progress = progress; 65 | postInvalidate(); 66 | } 67 | 68 | public void finish() { 69 | isfinished = true; 70 | postInvalidate(); 71 | } 72 | } 73 | 74 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/view/OpenQToChat.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.view; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.content.pm.PackageInfo; 6 | import android.content.pm.PackageManager; 7 | import android.net.Uri; 8 | import android.widget.Toast; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * 项目名称:AndroidUtils 14 | * 类描述:OpenQToChat 描述: 跳转咨询qq聊天的工具类 15 | * 创建人:songlijie 16 | * 创建时间:2017/5/15 14:56 17 | * 邮箱:814326663@qq.com 18 | */ 19 | public class OpenQToChat { 20 | 21 | /** 22 | * 打开QQ去咨询QQ 23 | * 24 | * @param context 上下文对象 25 | * @param qq 要跳转的QQ号 chat_type为wpa 26 | */ 27 | public static void OpenQQToChatNumal(Context context, String qq) { 28 | if (isQQClientAvailable(context)) { 29 | String qqUrl = "mqqwpa://im/chat?chat_type=wpa&uin=" + qq + "&version=1"; 30 | context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(qqUrl))); 31 | } else { 32 | Toast.makeText(context, "您的手机暂未安装QQ客户端", Toast.LENGTH_SHORT).show(); 33 | } 34 | } 35 | 36 | /** 37 | * 打开QQ去咨询企业QQ 38 | * 39 | * @param context 上下文对象 40 | * @param qq 要跳转的QQ号 chat_type为crm src_type为web 41 | */ 42 | public static void OpenQQToChatCompany(Context context, String qq) { 43 | if (isQQClientAvailable(context)) { 44 | String url = "mqqwpa://im/chat?chat_type=crm&uin=" + qq + "&version=1&src_type=web&web_src=http:://wpa.b.qq.com"; 45 | context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); 46 | } else { 47 | Toast.makeText(context, "您的手机暂未安装QQ客户端", Toast.LENGTH_SHORT).show(); 48 | } 49 | } 50 | 51 | 52 | /** 53 | * 判断qq是否可用 54 | * @param context 上下文对象 55 | * @return true or false 56 | */ 57 | public static boolean isQQClientAvailable(Context context) { 58 | final PackageManager packageManager = context.getPackageManager(); 59 | List pinfo = packageManager.getInstalledPackages(0); 60 | if (pinfo != null) { 61 | for (int i = 0; i < pinfo.size(); i++) { 62 | String pn = pinfo.get(i).packageName; 63 | if (pn.equals("com.tencent.mobileqq")) { 64 | return true; 65 | } 66 | } 67 | } 68 | return false; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/weight/webView/MyWebChromeClient.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.weight.webView; 2 | 3 | import android.content.Context; 4 | import android.view.View; 5 | import android.webkit.JsPromptResult; 6 | import android.webkit.JsResult; 7 | import android.webkit.WebChromeClient; 8 | import android.webkit.WebView; 9 | import android.widget.ProgressBar; 10 | 11 | /** 12 | * 项目名称:QianShan 13 | * 类描述:MyWebChromeClient 辅助WebView处理Javascript的对话框,网站图标,网站title,加载进度 14 | * 创建人:slj 15 | * 创建时间:2016-8-22 13:26 16 | * 修改人:slj 17 | * 修改时间:2016-8-22 13:26 18 | * 修改备注: 19 | * 邮箱:slj@bjlingzhuo.com 20 | */ 21 | public class MyWebChromeClient extends WebChromeClient { 22 | private Context context; 23 | private ProgressBar webView_ProgressBar;//进度条显示进度 24 | private WebView webView;//进度条 25 | public MyWebChromeClient(Context context) { 26 | this.context = context; 27 | } 28 | public void setWebView(WebView view, ProgressBar webView_ProgressBar){ 29 | this.webView_ProgressBar = webView_ProgressBar; 30 | onProgressChanged(view,0); 31 | } 32 | @Override 33 | public void onProgressChanged(WebView view, int newProgress) { 34 | if (newProgress == 100) { 35 | webView_ProgressBar.setVisibility(View.GONE); 36 | } else { 37 | if (View.INVISIBLE == webView_ProgressBar.getVisibility()) { 38 | webView_ProgressBar.setVisibility(View.VISIBLE); 39 | } 40 | webView_ProgressBar.setProgress(newProgress); 41 | } 42 | super.onProgressChanged(view, newProgress); 43 | } 44 | 45 | @Override 46 | public boolean onJsAlert(WebView view, String url, String message, JsResult result) { 47 | return super.onJsAlert(view, url, message, result); 48 | } 49 | 50 | @Override 51 | public boolean onJsConfirm(WebView view, String url, String message, JsResult result) { 52 | return super.onJsConfirm(view, url, message, result); 53 | } 54 | 55 | @Override 56 | public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) { 57 | return super.onJsPrompt(view, url, message, defaultValue, result); 58 | } 59 | 60 | @Override 61 | public boolean onJsBeforeUnload(WebView view, String url, String message, JsResult result) { 62 | return super.onJsBeforeUnload(view, url, message, result); 63 | } 64 | 65 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/media/VolleyTools/ImageLoaderUtil.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.media.VolleyTools; 2 | 3 | import android.graphics.Bitmap; 4 | import android.widget.ImageView; 5 | 6 | import com.android.volley.Response; 7 | import com.android.volley.VolleyError; 8 | import com.android.volley.toolbox.ImageLoader; 9 | import com.android.volley.toolbox.ImageRequest; 10 | import com.android.volley.toolbox.NetworkImageView; 11 | import com.example.user.utils.request.volley.BitmapCache; 12 | import com.example.user.utils.request.volley.VolleyRequestUtil; 13 | 14 | public class ImageLoaderUtil { 15 | 16 | /* 17 | * 通过ImageRequest来显示网络图片 18 | * */ 19 | public static void setImageRequest(String url, final ImageView imageView,final int resId) { 20 | ImageRequest imageRequest = new ImageRequest(url, new Response.Listener() { 21 | @Override 22 | public void onResponse(Bitmap bitmap) { 23 | imageView.setImageBitmap(bitmap); 24 | } 25 | }, 0, 0, Bitmap.Config.RGB_565, new Response.ErrorListener() { 26 | @Override 27 | public void onErrorResponse(VolleyError volleyError) { 28 | imageView.setBackgroundResource(resId); 29 | } 30 | }); 31 | VolleyRequestUtil.getInstance().getRequestQueue().add(imageRequest); 32 | VolleyRequestUtil.getInstance().getRequestQueue().start(); 33 | } 34 | 35 | /* 36 | * 通过ImageLoader来显示网络图片 37 | * */ 38 | public static void setImageLoader(String url, ImageView imageView, int defaultImageResId, int errorImageResId) { 39 | ImageLoader loader = new ImageLoader(VolleyRequestUtil.getInstance().getRequestQueue(), new BitmapCache()); 40 | ImageLoader.ImageListener imageListener = ImageLoader.getImageListener(imageView, defaultImageResId, errorImageResId); 41 | loader.get(url, imageListener); 42 | } 43 | 44 | /* 45 | * 通过Volley的NetWorkImageView来显示网络图片 46 | * */ 47 | public static void setNetWorkImageView(String url, NetworkImageView netWorkImageView, int defaultImageResId, int errorImageResId) { 48 | ImageLoader loader = new ImageLoader(VolleyRequestUtil.getInstance().getRequestQueue(), new BitmapCache()); 49 | netWorkImageView.setDefaultImageResId(defaultImageResId); 50 | netWorkImageView.setErrorImageResId(errorImageResId); 51 | netWorkImageView.setImageUrl(url, loader); 52 | } 53 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in E:\DevelopTools\studio_sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -optimizations !code/simplification/arithmetic 19 | -allowaccessmodification 20 | -repackageclasses '' 21 | -keepattributes *Annotation* 22 | -dontpreverify 23 | -dontwarn android.support.** 24 | 25 | -keep public class * extends android.app.Activity 26 | 27 | -keep public class * extends android.app.Application 28 | 29 | -keep public class * extends android.app.Service 30 | 31 | -keep public class * extends android.content.BroadcastReceiver 32 | 33 | -keep public class * extends android.content.ContentProvider 34 | 35 | -keep public class * extends android.view.View { 36 | public (android.content.Context); 37 | public (android.content.Context,android.util.AttributeSet); 38 | public (android.content.Context,android.util.AttributeSet,int); 39 | public void set*(...); 40 | } 41 | -keep public class * { 42 | ; 43 | ; 44 | } 45 | -keepclasseswithmembernames class * { 46 | native ; 47 | } 48 | -keepclasseswithmembers class * { 49 | public (android.content.Context,android.util.AttributeSet); 50 | } 51 | 52 | -keepclasseswithmembers class * { 53 | public (android.content.Context,android.util.AttributeSet,int); 54 | } 55 | 56 | -keepclassmembers class * extends android.content.Context { 57 | public void *(android.view.View); 58 | public void *(android.view.MenuItem); 59 | } 60 | 61 | -keepclassmembers class * extends android.os.Parcelable { 62 | static ** CREATOR; 63 | } 64 | 65 | -keepclassmembers class **.R$* { 66 | public static ; 67 | } 68 | -keepclasseswithmembernames class * { 69 | public static ; 70 | } 71 | 72 | -keepclassmembers class * { 73 | @android.webkit.JavascriptInterface 74 | ; 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/loaddrawable/LoadingView.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.loaddrawable; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.util.AttributeSet; 6 | import android.view.View; 7 | import android.widget.ImageView; 8 | 9 | import com.example.user.utils.R; 10 | 11 | public class LoadingView extends ImageView { 12 | private LoadingDrawable mLoadingDrawable; 13 | 14 | public LoadingView(Context context) { 15 | super(context); 16 | } 17 | 18 | public LoadingView(Context context, AttributeSet attrs) { 19 | super(context, attrs); 20 | initAttrs(context, attrs); 21 | } 22 | 23 | private void initAttrs(Context context, AttributeSet attrs) { 24 | try { 25 | TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.LoadingView); 26 | int loadingRendererId = ta.getInt(R.styleable.LoadingView_loading_renderer, 0); 27 | LoadingRenderer loadingRenderer = LoadingRendererFactory.createLoadingRenderer(context, loadingRendererId); 28 | setLoadingRenderer(loadingRenderer); 29 | ta.recycle(); 30 | } catch (Exception e) { 31 | e.printStackTrace(); 32 | } 33 | } 34 | 35 | public void setLoadingRenderer(LoadingRenderer loadingRenderer) { 36 | mLoadingDrawable = new LoadingDrawable(loadingRenderer); 37 | setImageDrawable(mLoadingDrawable); 38 | } 39 | 40 | @Override 41 | protected void onAttachedToWindow() { 42 | super.onAttachedToWindow(); 43 | startAnimation(); 44 | } 45 | 46 | @Override 47 | protected void onDetachedFromWindow() { 48 | super.onDetachedFromWindow(); 49 | stopAnimation(); 50 | } 51 | 52 | @Override 53 | protected void onVisibilityChanged(View changedView, int visibility) { 54 | super.onVisibilityChanged(changedView, visibility); 55 | 56 | final boolean visible = visibility == VISIBLE && getVisibility() == VISIBLE; 57 | if (visible) { 58 | startAnimation(); 59 | } else { 60 | stopAnimation(); 61 | } 62 | } 63 | 64 | private void startAnimation() { 65 | if (mLoadingDrawable != null) { 66 | mLoadingDrawable.start(); 67 | } 68 | } 69 | 70 | private void stopAnimation() { 71 | if (mLoadingDrawable != null) { 72 | mLoadingDrawable.stop(); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/weight/numal/ProcessImageView.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.weight.numal; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.Context; 5 | import android.graphics.Canvas; 6 | import android.graphics.Color; 7 | import android.graphics.Paint; 8 | import android.graphics.Rect; 9 | import android.util.AttributeSet; 10 | import android.view.ViewGroup.LayoutParams; 11 | import android.widget.ImageView; 12 | 13 | /** 14 | * 自定义带进度的Imagview 15 | */ 16 | public class ProcessImageView extends ImageView { 17 | 18 | private Paint mPaint;// 画笔 19 | Context context = null; 20 | int progress = 0; 21 | private boolean isfinished = false; 22 | 23 | public ProcessImageView(Context context) { 24 | super(context); 25 | // TODO Auto-generated constructor stub 26 | } 27 | 28 | public ProcessImageView(Context context, AttributeSet attrs) { 29 | this(context, attrs, 0); 30 | } 31 | 32 | public ProcessImageView(Context context, AttributeSet attrs, 33 | int defStyleAttr) { 34 | super(context, attrs, defStyleAttr); 35 | this.context = context; 36 | mPaint = new Paint(); 37 | } 38 | 39 | @SuppressLint("DrawAllocation") 40 | @Override 41 | protected void onDraw(Canvas canvas) { 42 | super.onDraw(canvas); 43 | if (isfinished) { 44 | return; 45 | } 46 | mPaint.setAntiAlias(true); // 消除锯齿 47 | mPaint.setStyle(Paint.Style.FILL); 48 | mPaint.setColor(Color.parseColor("#70000000"));// 半透明 49 | canvas.drawRect(0, 0, getWidth(), getHeight() - getHeight() * progress 50 | / 100, mPaint); 51 | mPaint.setColor(Color.parseColor("#00000000"));// 全透明 52 | canvas.drawRect(0, getHeight() - getHeight() * progress / 100, 53 | getWidth(), getHeight(), mPaint); 54 | 55 | mPaint.setTextSize(30); 56 | mPaint.setColor(Color.parseColor("#FFFFFF")); 57 | mPaint.setStrokeWidth(2); 58 | Rect rect = new Rect(); 59 | mPaint.getTextBounds("100%", 0, "100%".length(), rect);// 确定文字的宽度 60 | canvas.drawText(progress + "%", getWidth() / 2 - rect.width() / 2, 61 | getHeight() / 2, mPaint); 62 | 63 | } 64 | 65 | public void setProgress(int progress) { 66 | this.progress = progress; 67 | postInvalidate(); 68 | } 69 | 70 | public void finish() { 71 | isfinished = true; 72 | postInvalidate(); 73 | } 74 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/loaddrawable/LoadingDrawable.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.loaddrawable; 2 | 3 | import android.graphics.Canvas; 4 | import android.graphics.ColorFilter; 5 | import android.graphics.PixelFormat; 6 | import android.graphics.Rect; 7 | import android.graphics.drawable.Animatable; 8 | import android.graphics.drawable.Drawable; 9 | 10 | /** 11 | * 加在动画的drawable 12 | */ 13 | public class LoadingDrawable extends Drawable implements Animatable { 14 | private final LoadingRenderer mLoadingRender; 15 | 16 | private final Callback mCallback = new Callback() { 17 | @Override 18 | public void invalidateDrawable(Drawable d) { 19 | invalidateSelf(); 20 | } 21 | 22 | @Override 23 | public void scheduleDrawable(Drawable d, Runnable what, long when) { 24 | scheduleSelf(what, when); 25 | } 26 | 27 | @Override 28 | public void unscheduleDrawable(Drawable d, Runnable what) { 29 | unscheduleSelf(what); 30 | } 31 | }; 32 | 33 | public LoadingDrawable(LoadingRenderer loadingRender) { 34 | this.mLoadingRender = loadingRender; 35 | this.mLoadingRender.setCallback(mCallback); 36 | } 37 | 38 | @Override 39 | protected void onBoundsChange(Rect bounds) { 40 | super.onBoundsChange(bounds); 41 | this.mLoadingRender.setBounds(bounds); 42 | } 43 | 44 | @Override 45 | public void draw(Canvas canvas) { 46 | if (!getBounds().isEmpty()) { 47 | this.mLoadingRender.draw(canvas); 48 | } 49 | } 50 | 51 | @Override 52 | public void setAlpha(int alpha) { 53 | this.mLoadingRender.setAlpha(alpha); 54 | } 55 | 56 | @Override 57 | public void setColorFilter(ColorFilter cf) { 58 | this.mLoadingRender.setColorFilter(cf); 59 | } 60 | 61 | @Override 62 | public int getOpacity() { 63 | return PixelFormat.TRANSLUCENT; 64 | } 65 | 66 | @Override 67 | public void start() { 68 | this.mLoadingRender.start(); 69 | } 70 | 71 | @Override 72 | public void stop() { 73 | this.mLoadingRender.stop(); 74 | } 75 | 76 | @Override 77 | public boolean isRunning() { 78 | return this.mLoadingRender.isRunning(); 79 | } 80 | 81 | @Override 82 | public int getIntrinsicHeight() { 83 | return (int) this.mLoadingRender.mHeight; 84 | } 85 | 86 | @Override 87 | public int getIntrinsicWidth() { 88 | return (int) this.mLoadingRender.mWidth; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/media/GLFont.java: -------------------------------------------------------------------------------- 1 | 2 | package com.example.user.utils.media; 3 | 4 | /** 5 | * @author leolaurel 6 | * @version 1.0.0 2012-7-5 7 | */ 8 | 9 | import android.graphics.Bitmap; 10 | import android.graphics.Canvas; 11 | import android.graphics.Color; 12 | import android.graphics.Paint; 13 | import android.graphics.Paint.FontMetrics; 14 | import android.graphics.Typeface; 15 | 16 | public class GLFont { 17 | /* 18 | * 默认采用白色字体,宋体文字加粗 19 | */ 20 | public static Bitmap getImage(int width, int height ,String mString, int size) { 21 | return getImage(width, height, mString, size, Color.RED, Typeface.create("宋体",Typeface.BOLD)); 22 | } 23 | 24 | public static Bitmap getImage(int width, int height ,String mString,int size ,int color) { 25 | return getImage(width, height, mString, size, color, Typeface.create("宋体",Typeface.BOLD)); 26 | } 27 | 28 | public static Bitmap getImage(int width, int height ,String mString,int size ,int color, String familyName) { 29 | return getImage(width, height, mString, size, color, Typeface.create(familyName,Typeface.BOLD)); 30 | } 31 | 32 | public static Bitmap getImage(int width, int height ,String mString,int size, int color, Typeface font) { 33 | int x = width; 34 | int y = height; 35 | 36 | Bitmap bmp = Bitmap.createBitmap(x, y, Bitmap.Config.ARGB_8888); 37 | //图象大小要根据文字大小算下,以和文本长度对应 38 | Canvas canvasTemp = new Canvas(bmp); 39 | canvasTemp.drawColor(Color.BLACK); 40 | Paint p = new Paint(); 41 | p.setColor(color); 42 | p.setTypeface(font); 43 | p.setAntiAlias(true);//去除锯齿 44 | p.setFilterBitmap(true);//对位图进行滤波处理 45 | p.setTextSize(scalaFonts(size)); 46 | float tX = (x - getFontlength(p, mString))/2; 47 | float tY = (y - getFontHeight(p))/2+getFontLeading(p); 48 | canvasTemp.drawText(mString,tX,tY,p); 49 | 50 | return bmp; 51 | } 52 | 53 | /** 54 | * 根据屏幕系数比例获取文字大小 55 | * @return 56 | */ 57 | private static float scalaFonts(int size) { 58 | //暂未实现 59 | return size; 60 | } 61 | 62 | /** 63 | * @return 返回指定笔和指定字符串的长度 64 | */ 65 | public static float getFontlength(Paint paint, String str) { 66 | return paint.measureText(str); 67 | } 68 | /** 69 | * @return 返回指定笔的文字高度 70 | */ 71 | public static float getFontHeight(Paint paint) { 72 | FontMetrics fm = paint.getFontMetrics(); 73 | return fm.descent - fm.ascent; 74 | } 75 | /** 76 | * @return 返回指定笔离文字顶部的基准距离 77 | */ 78 | public static float getFontLeading(Paint paint) { 79 | FontMetrics fm = paint.getFontMetrics(); 80 | return fm.leading- fm.ascent; 81 | } 82 | } 83 | 84 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/util/ActivityUtils.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.util; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.os.Bundle; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | /** 12 | *
13 |  *     author: Blankj
14 |  *     blog  : http://blankj.com
15 |  *     time  : 2016/9/23
16 |  *     desc  : Activity相关工具类
17 |  * 
18 | */ 19 | public class ActivityUtils { 20 | private static List activityList = new ArrayList<>(); 21 | private ActivityUtils() { 22 | throw new UnsupportedOperationException("u can't instantiate me..."); 23 | } 24 | 25 | /** 26 | * 判断是否存在Activity 27 | * 28 | * @param context 上下文 29 | * @param packageName 包名 30 | * @param className activity全路径类名 31 | * @return {@code true}: 是
{@code false}: 否 32 | */ 33 | public static boolean isExistActivity(Context context, String packageName, String className) { 34 | Intent intent = new Intent(); 35 | intent.setClassName(packageName, className); 36 | return !(context.getPackageManager().resolveActivity(intent, 0) == null || 37 | intent.resolveActivity(context.getPackageManager()) == null || 38 | context.getPackageManager().queryIntentActivities(intent, 0).size() == 0); 39 | } 40 | 41 | /** 42 | * 打开Activity 43 | * 44 | * @param context 上下文 45 | * @param packageName 包名 46 | * @param className 全类名 47 | */ 48 | public static void launchActivity(Context context, String packageName, String className) { 49 | launchActivity(context, packageName, className, null); 50 | } 51 | 52 | /** 53 | * 打开Activity 54 | * 55 | * @param context 上下文 56 | * @param packageName 包名 57 | * @param className 全类名 58 | * @param bundle bundle 59 | */ 60 | public static void launchActivity(Context context, String packageName, String className, Bundle bundle) { 61 | context.startActivity(IntentUtils.getComponentIntent(packageName, className, bundle)); 62 | } 63 | 64 | public static void add(Activity activity){ 65 | activityList.add(activity); 66 | } 67 | 68 | public static void remove(Activity activity){ 69 | activityList.remove(activity); 70 | } 71 | 72 | public static List getActivityList(){ 73 | if (activityList==null){ 74 | activityList = new ArrayList<>(); 75 | } 76 | return activityList; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/weight/numal/SwipeSlideListener.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.weight.numal; 2 | 3 | import android.widget.AbsListView; 4 | import android.widget.ListView; 5 | 6 | import java.util.HashSet; 7 | import java.util.Set; 8 | 9 | /** 10 | * 项目名称:AndroidUtils 11 | * 类描述:SwipeSlideListener 描述: 侧滑删除layout的监听器 侧滑Layout 12 | * 创建人:songlijie 13 | * 创建时间:2017/5/17 11:58 14 | * 邮箱:814326663@qq.com 15 | */ 16 | public class SwipeSlideListener implements SwipeListLayout.OnSwipeStatusListener { 17 | private Set sets = new HashSet(); 18 | private SwipeListLayout slipListLayout; 19 | public SwipeSlideListener(SwipeListLayout slipListLayout) { 20 | this.slipListLayout = slipListLayout; 21 | } 22 | @Override 23 | public void onStatusChanged(SwipeListLayout.Status status) { 24 | if (status == SwipeListLayout.Status.Open) { 25 | //若有其他的item的状态为Open,则Close,然后移除 26 | if (sets.size() > 0) { 27 | for (SwipeListLayout s : sets) { 28 | s.setStatus(SwipeListLayout.Status.Close, true); 29 | sets.remove(s); 30 | } 31 | } 32 | sets.add(slipListLayout); 33 | } else { 34 | if (sets.contains(slipListLayout)){ 35 | sets.remove(slipListLayout); 36 | } 37 | } 38 | } 39 | 40 | @Override 41 | public void onStartCloseAnimation() { 42 | 43 | } 44 | 45 | @Override 46 | public void onStartOpenAnimation() { 47 | 48 | } 49 | 50 | /** 51 | * 设置listview的滑动监听 52 | * @param view 53 | */ 54 | public void ListViewScroll(ListView view){ 55 | view.setOnScrollListener(new AbsListView.OnScrollListener() { 56 | 57 | @Override 58 | public void onScrollStateChanged(AbsListView view, int scrollState) { 59 | switch (scrollState) { 60 | //当listview开始滑动时,若有item的状态为Open,则Close,然后移除 61 | case SCROLL_STATE_TOUCH_SCROLL: 62 | if (sets.size() > 0) { 63 | for (SwipeListLayout s : sets) { 64 | s.setStatus(SwipeListLayout.Status.Close, true); 65 | sets.remove(s); 66 | } 67 | } 68 | break; 69 | 70 | } 71 | } 72 | 73 | @Override 74 | public void onScroll(AbsListView view, int firstVisibleItem, 75 | int visibleItemCount, int totalItemCount) { 76 | 77 | } 78 | }); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/view/ComparatorUtil.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.view; 2 | 3 | import com.alibaba.fastjson.JSONArray; 4 | import com.alibaba.fastjson.JSONObject; 5 | import java.util.ArrayList; 6 | import java.util.Collections; 7 | import java.util.Comparator; 8 | import java.util.HashMap; 9 | import java.util.Iterator; 10 | import java.util.List; 11 | import java.util.Map; 12 | 13 | /** 14 | * 项目名称:AndroidUtils 15 | * 类描述:ComparatorUtil 描述: 排序的工具类 16 | * 创建人:songlijie 17 | * 创建时间:2017/5/16 10:58 18 | * 邮箱:814326663@qq.com 19 | */ 20 | public class ComparatorUtil { 21 | 22 | /** 23 | * 分组排序 把一类的分组到一起 24 | * 25 | * @param array 集合 26 | * @param srckey array中包含的object中的一个key 27 | * @return Map> map 集合 28 | */ 29 | public static Map> handleData(JSONArray array, String srckey) { 30 | Map> map = new HashMap>(); 31 | for (int i = 0; i < array.size(); i++) { 32 | JSONObject json = array.getJSONObject(i); 33 | String teamId = json.getString(srckey); 34 | if (map.containsKey(teamId)) { 35 | List list = map.get(teamId); 36 | list.add(json); 37 | } else { 38 | List list = new ArrayList(); 39 | list.add(json); 40 | map.put(teamId, list); 41 | } 42 | } 43 | return map; 44 | } 45 | 46 | /** 47 | * 获取map中集合 48 | * 49 | * @param data map数据 50 | * @param srcKey jsonobject中的key 51 | * @param comparator 排序方法 如果不排序则传null 52 | * @return List 返回集合 53 | */ 54 | public static List getItems(Map> data, String srcKey, Comparator comparator) { 55 | List myActivityItems = new ArrayList<>(); 56 | Iterator iter = data.entrySet().iterator(); 57 | while (iter.hasNext()) { 58 | Map.Entry entry = (Map.Entry) iter.next(); 59 | String entryKey = (String) entry.getKey(); 60 | List val = (List) entry.getValue(); 61 | // 对list进行排序 62 | if (comparator != null) { 63 | Collections.sort(val, comparator); 64 | } 65 | String userId = val.get(0).getString(srcKey); 66 | for (int i = 0; i < val.size(); i++) { 67 | JSONObject object = val.get(i); 68 | JSONObject jsonObject = new JSONObject(); 69 | jsonObject.put(srcKey, userId); 70 | jsonObject.put("object", object.toJSONString()); 71 | myActivityItems.add(jsonObject); 72 | } 73 | } 74 | return myActivityItems; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'kotlin-android' 3 | 4 | android { 5 | compileSdkVersion 25 6 | buildToolsVersion "25.0.2" 7 | defaultConfig { 8 | minSdkVersion 14 9 | targetSdkVersion 25 10 | versionCode 1 11 | versionName "1.7" 12 | } 13 | 14 | lintOptions { 15 | abortOnError false 16 | checkReleaseBuilds false 17 | // 防止在发布的时候出现因MissingTranslation导致Build Failed! 18 | disable 'MissingTranslation' 19 | } 20 | buildTypes { 21 | release { 22 | minifyEnabled false 23 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 24 | } 25 | } 26 | task makeJar(type: Copy) { 27 | //删除存在的 28 | delete 'build/libs/androidutils.jar' 29 | //设置拷贝的文件 30 | from('build/intermediates/bundles/release/') 31 | //打进jar包后的文件目录 32 | into('build/libs/') 33 | //将classes.jar放入build/libs/目录下 34 | //include ,exclude参数来设置过滤 35 | //(我们只关心classes.jar这个文件) 36 | include('classes.jar') 37 | //重命名 38 | rename('classes.jar', 'androidutils.jar') 39 | } 40 | makeJar.dependsOn(build) 41 | compileOptions { 42 | sourceCompatibility JavaVersion.VERSION_1_7 43 | targetCompatibility JavaVersion.VERSION_1_7 44 | } 45 | } 46 | 47 | dependencies { 48 | compile fileTree(include: ['*.jar'], dir: 'libs') 49 | compile 'com.android.support:appcompat-v7:25.1.1' 50 | compile 'com.squareup.okhttp3:okhttp:3.5.0' 51 | compile 'com.alibaba:fastjson:1.2.21' 52 | compile 'eu.the4thfloor.volley:com.android.volley:2015.05.28' 53 | compile 'com.google.code.gson:gson:2.8.0' 54 | compile 'com.github.chrisbanes.photoview:library:1.2.4' 55 | compile 'com.github.bumptech.glide:glide:3.7.0' 56 | // compile 'com.github.bumptech.glide:glide:4.1.1' 57 | compile 'org.xutils:xutils:3.5.0' 58 | //时间选择器 59 | compile 'com.jzxiang.pickerview:TimePickerDialog:1.0.1' 60 | compile 'org.jsoup:jsoup:1.10.2' 61 | //鲁班多图压缩 62 | compile 'me.shaohui.advancedluban:library:1.3.2' 63 | //nineoldandroid 64 | compile 'com.nineoldandroids:library:2.4.0' 65 | // rxjava 66 | compile "io.reactivex.rxjava2:rxjava:2.1.0" 67 | compile 'io.reactivex.rxjava2:rxandroid:2.0.1' 68 | //retrofit依赖 69 | compile 'com.squareup.retrofit2:retrofit:2.2.0' 70 | compile 'com.squareup.retrofit2:converter-gson:2.2.0' 71 | compile 'com.squareup.retrofit2:converter-scalars:2.2.0' 72 | compile 'com.squareup.retrofit2:adapter-rxjava2:2.2.0' 73 | //OKhttp3的依赖 74 | compile 'com.squareup.okhttp3:logging-interceptor:3.5.0' 75 | //kotlin依赖 76 | compile "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 77 | } 78 | repositories { 79 | jcenter() 80 | } 81 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/string/StringUtil.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.string; 2 | 3 | import android.text.TextUtils; 4 | 5 | import java.util.Locale; 6 | import java.util.UUID; 7 | 8 | public class StringUtil { 9 | 10 | public static String getPercentString(float percent) { 11 | return String.format(Locale.US, "%d%%", (int) (percent * 100)); 12 | } 13 | /** 14 | * 删除字符串中的空白符 15 | * 16 | * @param content 17 | * @return String 18 | */ 19 | public static String removeBlanks(String content) { 20 | if (content == null) { 21 | return null; 22 | } 23 | StringBuilder buff = new StringBuilder(); 24 | buff.append(content); 25 | for (int i = buff.length() - 1; i >= 0; i--) { 26 | if (' ' == buff.charAt(i) || ('\n' == buff.charAt(i)) || ('\t' == buff.charAt(i)) 27 | || ('\r' == buff.charAt(i))) { 28 | buff.deleteCharAt(i); 29 | } 30 | } 31 | return buff.toString(); 32 | } 33 | /** 34 | * 获取32位uuid 35 | * 36 | * @return 37 | */ 38 | public static String get32UUID() { 39 | return UUID.randomUUID().toString().replaceAll("-", ""); 40 | } 41 | 42 | public static boolean isEmpty(String input) { 43 | return TextUtils.isEmpty(input); 44 | } 45 | 46 | /** 47 | * 生成唯一号 48 | * 49 | * @return 50 | */ 51 | public static String get36UUID() { 52 | UUID uuid = UUID.randomUUID(); 53 | String uniqueId = uuid.toString(); 54 | return uniqueId; 55 | } 56 | 57 | public static String makeMd5(String source) { 58 | return MD5.getStringMD5(source); 59 | } 60 | 61 | public static final String filterUCS4(String str) { 62 | if (TextUtils.isEmpty(str)) { 63 | return str; 64 | } 65 | 66 | if (str.codePointCount(0, str.length()) == str.length()) { 67 | return str; 68 | } 69 | 70 | StringBuilder sb = new StringBuilder(); 71 | 72 | int index = 0; 73 | while (index < str.length()) { 74 | int codePoint = str.codePointAt(index); 75 | index += Character.charCount(codePoint); 76 | if (Character.isSupplementaryCodePoint(codePoint)) { 77 | continue; 78 | } 79 | 80 | sb.appendCodePoint(codePoint); 81 | } 82 | 83 | return sb.toString(); 84 | } 85 | 86 | /** 87 | * counter ASCII character as one, otherwise two 88 | * 89 | * @param str 90 | * @return count 91 | */ 92 | public static int counterChars(String str) { 93 | // return 94 | if (TextUtils.isEmpty(str)) { 95 | return 0; 96 | } 97 | int count = 0; 98 | for (int i = 0; i < str.length(); i++) { 99 | int tmp = (int) str.charAt(i); 100 | if (tmp > 0 && tmp < 127) { 101 | count += 1; 102 | } else { 103 | count += 2; 104 | } 105 | } 106 | return count; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/util/CrashUtils.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.util; 2 | 3 | import android.content.Context; 4 | import android.os.Looper; 5 | 6 | /** 7 | *
 8 |  *     author: Blankj
 9 |  *     blog  : http://blankj.com
10 |  *     time  : 2016/9/27
11 |  *     desc  :
12 |  * 
13 | */ 14 | public class CrashUtils implements Thread.UncaughtExceptionHandler { 15 | 16 | private Thread.UncaughtExceptionHandler mDefaultHandler; 17 | private static CrashUtils INSTANCE; 18 | private Context mContext; 19 | 20 | private CrashUtils() { 21 | throw new AssertionError(); 22 | } 23 | 24 | public static CrashUtils getInstance() { 25 | if (INSTANCE == null) 26 | INSTANCE = new CrashUtils(); 27 | return INSTANCE; 28 | } 29 | 30 | public void init(Context context) { // 在Application中初始化 31 | mContext = context; 32 | 33 | mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();// 获取系统默认的UncaughtException处理器 34 | Thread.setDefaultUncaughtExceptionHandler(this);// 设置该CrashHandler为程序的默认处理器 35 | } 36 | @Override 37 | public void uncaughtException(Thread thread, Throwable ex) { 38 | if (!handleException(ex) && mDefaultHandler != null) { 39 | // 如果自定义的没有处理则让系统默认的异常处理器来处理 40 | mDefaultHandler.uncaughtException(thread, ex); 41 | } 42 | } 43 | 44 | /** 45 | * 自定义错误处理、收集错误信息、发送错误报告 46 | * 47 | * @param ex 异常信息 48 | * @return true 如果处理了该异常信息;否则返回false. 49 | */ 50 | public boolean handleException(Throwable ex) { 51 | if (ex == null || mContext == null) 52 | return false; 53 | final String crashReport = getCrashReport(mContext, ex); 54 | new Thread() { 55 | public void run() { 56 | Looper.prepare(); 57 | LogUtils.e("CrashHandler", crashReport); // 打印异常信息,也可保存至文件 方便远程调试 58 | Looper.loop(); 59 | } 60 | 61 | }.start(); 62 | return true; 63 | } 64 | 65 | /** 66 | * 获取APP崩溃异常报告 67 | * 68 | * @param ex 69 | * @return 70 | */ 71 | private String getCrashReport(Context context, Throwable ex) { 72 | // PackageInfo pinfo = AppUtils.getPackageInfo(context); 73 | StringBuffer exceptionStr = new StringBuffer(); 74 | // exceptionStr.append("Version: " + pinfo.versionName + "(" + pinfo.versionCode + ")\n"); 75 | exceptionStr.append("Android: " + android.os.Build.VERSION.RELEASE + "(" + android.os.Build.MODEL + ")\n"); 76 | exceptionStr.append("Exception: " + ex.getMessage() + "\n"); 77 | StackTraceElement[] elements = ex.getStackTrace(); 78 | for (int i = 0; i < elements.length; i++) { 79 | exceptionStr.append(elements[i].toString() + "\n"); 80 | } 81 | return exceptionStr.toString(); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/view/AutoSpliText.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.view; 2 | 3 | import android.graphics.Paint; 4 | import android.graphics.drawable.Drawable; 5 | import android.widget.TextView; 6 | 7 | /** 8 | * Created by Developer-X on 2016/5/27. 9 | * 解决TextView显示自动换行问题 10 | */ 11 | public class AutoSpliText { 12 | public int itemWidth = 0; 13 | 14 | private String autoSplitText(final TextView tv, int width) { 15 | final String rawText = tv.getText().toString(); //原始文本 16 | final Paint tvPaint = tv.getPaint(); //paint,包含字体等信息 17 | final float tvWidth = width - tv.getPaddingLeft() - tv.getPaddingRight(); //控件可用宽度 18 | 19 | //将原始文本按行拆分 20 | String[] rawTextLines = rawText.replaceAll("\r", "").split("\n"); 21 | StringBuilder sbNewText = new StringBuilder(); 22 | for (String rawTextLine : rawTextLines) { 23 | if (tvPaint.measureText(rawTextLine) <= tvWidth) { 24 | //如果整行宽度在控件可用宽度之内,就不处理了 25 | sbNewText.append(rawTextLine); 26 | } else { 27 | //如果整行宽度超过控件可用宽度,则按字符测量,在超过可用宽度的前一个字符处手动换行 28 | float lineWidth = 0; 29 | for (int cnt = 0; cnt != rawTextLine.length(); ++cnt) { 30 | char ch = rawTextLine.charAt(cnt); 31 | lineWidth += tvPaint.measureText(String.valueOf(ch)); 32 | if (lineWidth <= tvWidth) { 33 | sbNewText.append(ch); 34 | } else { 35 | sbNewText.append("\n"); 36 | lineWidth = 0; 37 | --cnt; 38 | } 39 | } 40 | } 41 | sbNewText.append("\n"); 42 | } 43 | 44 | //把结尾多余的\n去掉 45 | if (!rawText.endsWith("\n")) { 46 | sbNewText.deleteCharAt(sbNewText.length() - 1); 47 | } 48 | 49 | return sbNewText.toString(); 50 | } 51 | 52 | /** 53 | * TextView不换行 54 | * @param tv 55 | */ 56 | public void autoText(final TextView tv) { 57 | if (itemWidth == 0) { 58 | tv.post(new Runnable() { 59 | @Override 60 | public void run() { 61 | Drawable ds[] = tv.getCompoundDrawables(); 62 | Drawable left = ds[0]; 63 | Drawable right = ds[2]; 64 | 65 | itemWidth = tv.getWidth() - (left==null?0:left.getIntrinsicWidth()+tv.getCompoundDrawablePadding()) - (right==null?0:right.getIntrinsicWidth()+tv.getCompoundDrawablePadding()) ; 66 | final String newText = autoSplitText(tv, itemWidth); 67 | tv.setText(newText); 68 | 69 | } 70 | }); 71 | } else { 72 | final String newText = autoSplitText(tv, itemWidth); 73 | tv.setText(newText); 74 | } 75 | 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/string/TextFormater.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.string; 2 | 3 | import android.content.Context; 4 | 5 | import java.text.DecimalFormat; 6 | 7 | /** 8 | * Created by huangfangyi on 2016/12/24. 9 | * qq 84543217 10 | */ 11 | 12 | 13 | public class TextFormater { 14 | private static final int GB_SP_DIFF = 160; 15 | private static final int[] secPosvalueList = new int[]{1601, 1637, 1833, 2078, 2274, 2302, 2433, 2594, 2787, 3106, 3212, 3472, 3635, 3722, 3730, 3858, 4027, 4086, 4390, 4558, 4684, 4925, 5249, 5600}; 16 | private static final char[] firstLetter = new char[]{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'w', 'x', 'y', 'z'}; 17 | 18 | public TextFormater() { 19 | } 20 | 21 | public static String getDataSize(long var0) { 22 | DecimalFormat var2 = new DecimalFormat("###.00"); 23 | return var0 < 1024L?var0 + "bytes":(var0 < 1048576L?var2.format((double)((float)var0 / 1024.0F)) + "KB":(var0 < 1073741824L?var2.format((double)((float)var0 / 1024.0F / 1024.0F)) + "MB":(var0 < 0L?var2.format((double)((float)var0 / 1024.0F / 1024.0F / 1024.0F)) + "GB":"error"))); 24 | } 25 | 26 | public static String getKBDataSize(long var0) { 27 | DecimalFormat var2 = new DecimalFormat("###.00"); 28 | return var0 < 1024L?var0 + "KB":(var0 < 1048576L?var2.format((double)((float)var0 / 1024.0F)) + "MB":(var0 < 1073741824L?var2.format((double)((float)var0 / 1024.0F / 1024.0F)) + "GB":"error")); 29 | } 30 | 31 | public static String formatStr(Context var0, int var1, String var2) { 32 | String var3 = var0.getText(var1).toString(); 33 | return String.format(var3, new Object[]{var2}); 34 | } 35 | 36 | public static String getFirstLetter(String var0) { 37 | String var1 = var0.toLowerCase(); 38 | StringBuffer var2 = new StringBuffer(); 39 | 40 | for(int var5 = 0; var5 < var1.length(); ++var5) { 41 | char var3 = var1.charAt(var5); 42 | char[] var4 = new char[]{var3}; 43 | byte[] var6 = (new String(var4)).getBytes(); 44 | if(var6[0] < 128 && var6[0] > 0) { 45 | var2.append(var4); 46 | } else { 47 | var2.append(convert(var6)); 48 | } 49 | } 50 | 51 | return var2.toString().substring(0, 1); 52 | } 53 | 54 | private static char convert(byte[] var0) { 55 | char var1 = 45; 56 | boolean var2 = false; 57 | 58 | int var3; 59 | for(var3 = 0; var3 < var0.length; ++var3) { 60 | var0[var3] = (byte)(var0[var3] - 160); 61 | } 62 | 63 | int var4 = var0[0] * 100 + var0[1]; 64 | 65 | for(var3 = 0; var3 < 23; ++var3) { 66 | if(var4 >= secPosvalueList[var3] && var4 < secPosvalueList[var3 + 1]) { 67 | var1 = firstLetter[var3]; 68 | break; 69 | } 70 | } 71 | 72 | return var1; 73 | } 74 | } 75 | 76 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/view/NumberFormat.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.view; 2 | 3 | import android.text.Html; 4 | 5 | import java.text.DecimalFormat; 6 | 7 | /** 8 | * double类型转String位数保留两位小数 9 | */ 10 | public class NumberFormat { 11 | // public static String formatRound(double data) { 12 | // DecimalFormat df = new DecimalFormat("#0.00"); 13 | // return df.format(data); 14 | // } 15 | public static double parseDouble(String s) { 16 | if (s == null) { 17 | return 0; 18 | } 19 | try { 20 | return Double.parseDouble(s); 21 | } catch (NumberFormatException e) { 22 | return 0; 23 | } 24 | } 25 | 26 | /** 27 | * 默认给f加上前缀¥ 可修改 和后缀,不需要就填null 28 | * @param f 29 | * @param end 30 | * @return 31 | */ 32 | public static CharSequence formatSpecialPrice(double f, String end) { 33 | return formatSpecialPrice(f, "¥", end); 34 | } 35 | 36 | /** 37 | * 给f加上前缀 可修改 和后缀,不需要就填null 38 | * @param f 39 | * @param start 40 | * @param end 41 | * @return 42 | */ 43 | public static CharSequence formatSpecialPrice(double f, String start, 44 | String end) { 45 | DecimalFormat df = new DecimalFormat("#0.00"); 46 | String s = df.format(f); 47 | String[] ss = s.split("\\."); 48 | if (ss.length != 2) { 49 | return ""; 50 | } 51 | if (end == null) { 52 | end = ""; 53 | } 54 | if (start == null) { 55 | start = ""; 56 | } 57 | return Html.fromHtml("" + start + "" + ss[0] 58 | + "." + ss[1] + end + ""); 59 | } 60 | 61 | /** 62 | * 保留两位小数 63 | * @param f 64 | * @return 65 | */ 66 | public static String doubleToString(double f) { 67 | long t = Math.round(f * 100); 68 | StringBuilder sb = new StringBuilder(); 69 | sb.append(t / 100).append("."); 70 | long num = t % 100; 71 | if (num < 9) { 72 | sb.append("0"); 73 | } 74 | sb.append(num); 75 | return sb.toString(); 76 | } 77 | 78 | /** 79 | * 保留两位小数 80 | * @param f 81 | * @param end 82 | * @return 83 | */ 84 | public static String doubleToString(double f, String end) { 85 | long t = Math.round(f * 100); 86 | StringBuilder sb = new StringBuilder(); 87 | sb.append(t / 100).append("."); 88 | long num = t % 100; 89 | if (num < 9) { 90 | sb.append("0"); 91 | } 92 | sb.append(num).append(end); 93 | return sb.toString(); 94 | } 95 | 96 | // public static String formatPrice(float f) { 97 | // return String.format("%.02f", f); 98 | // } 99 | // 100 | // public static String formatPrice(double d) { 101 | // return String.format("%.02f", d); 102 | // } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/weight/webView/MyWebViewClient.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.weight.webView; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.app.ProgressDialog; 5 | import android.content.Context; 6 | import android.graphics.Bitmap; 7 | import android.net.http.SslError; 8 | import android.text.TextUtils; 9 | import android.webkit.SslErrorHandler; 10 | import android.webkit.WebView; 11 | import android.webkit.WebViewClient; 12 | 13 | /** 14 | * 项目名称:QianShan 15 | * 类描述:MyWebViewClient 帮助WebView处理各种通知、请求事件的(带dialog) 16 | * 创建人:slj 17 | * 创建时间:2016-8-22 11:58 18 | * 修改人:slj 19 | * 修改时间:2016-8-22 11:58 20 | * 修改备注: 21 | * 邮箱:slj@bjlingzhuo.com 22 | */ 23 | public class MyWebViewClient extends WebViewClient { 24 | private Context context; 25 | private ProgressDialog progressDialog; 26 | private String message = null ;//默认的是null 27 | public MyWebViewClient(Context context) { 28 | this.context=context; 29 | } 30 | @Override 31 | public boolean shouldOverrideUrlLoading(WebView view, String url) { //网页加载时的连接的网址 32 | view.loadUrl(url); 33 | return false; 34 | } 35 | 36 | /** 37 | * 设置展示的webview 38 | * @param view 39 | * @param url 40 | */ 41 | @SuppressLint("JavascriptInterface") 42 | public void setWebView(WebView view , String url){ 43 | onPageStarted(view,url,null); 44 | shouldOverrideUrlLoading(view,url); 45 | onPageFinished(view,url); 46 | } 47 | 48 | /** 49 | * 设置进度弹出框的显示文字 50 | * @param message 51 | */ 52 | public void setMessage(String message){ 53 | this.message = message; 54 | } 55 | /** 56 | * 设置进度弹出框的显示文字 57 | * @param message 58 | */ 59 | public void setMessage(int message){ 60 | this.message = context.getString(message); 61 | } 62 | @Override 63 | public void onPageStarted(WebView view, String url, Bitmap favicon) {//网页页面开始加载的时候 64 | if (progressDialog == null) { 65 | progressDialog = new ProgressDialog(context); 66 | if (message == null || TextUtils.isEmpty(message)) 67 | progressDialog.setMessage("正在加载,请稍候...."); 68 | else 69 | progressDialog.setMessage(message); 70 | 71 | progressDialog.show(); 72 | view.setEnabled(false);// 当加载网页的时候将网页进行隐藏 73 | } 74 | super.onPageStarted(view, url, favicon); 75 | } 76 | 77 | @Override 78 | public void onPageFinished(WebView view, String url) {//网页加载结束的时候 79 | //super.onPageFinished(view, url); 80 | if (progressDialog != null && progressDialog.isShowing()) { 81 | progressDialog.dismiss(); 82 | progressDialog = null; 83 | view.setEnabled(true); 84 | } 85 | super.onPageFinished(view, url); 86 | } 87 | @Override 88 | public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { 89 | //handler.cancel(); // Android默认的处理方式 90 | handler.proceed(); // 接受所有网站的证书 91 | //handleMessage(Message msg); // 进行其他处理 92 | super.onReceivedSslError(view, handler, error); 93 | } 94 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/sys/ReflectionUtil.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.sys; 2 | 3 | import android.text.TextUtils; 4 | import android.util.Log; 5 | 6 | import java.lang.reflect.Field; 7 | import java.lang.reflect.Method; 8 | 9 | /** 10 | * 反射工具类 11 | * 通过反射获得对应函数功能 12 | */ 13 | public class ReflectionUtil { 14 | 15 | /** 16 | * 通过类对象,运行指定方法 17 | * @param obj 类对象 18 | * @param methodName 方法名 19 | * @param params 参数值 20 | * @return 失败返回null 21 | */ 22 | public static Object invokeMethod(Object obj, String methodName, Object[] params) { 23 | if (obj == null || TextUtils.isEmpty(methodName)) { 24 | return null; 25 | } 26 | 27 | Class clazz = obj.getClass(); 28 | try { 29 | Class[] paramTypes = null; 30 | if (params != null) { 31 | paramTypes = new Class[params.length]; 32 | for (int i = 0; i < params.length; ++i) { 33 | paramTypes[i] = params[i].getClass(); 34 | } 35 | } 36 | Method method = clazz.getMethod(methodName, paramTypes); 37 | method.setAccessible(true); 38 | return method.invoke(obj, params); 39 | } catch (NoSuchMethodException e) { 40 | Log.i("reflect", "method " + methodName + " not found in " + obj.getClass().getName()); 41 | } catch (Exception e) { 42 | e.printStackTrace(); 43 | } 44 | return null; 45 | } 46 | 47 | /** 48 | * 通过类对象,获取指定文件 49 | * @param obj 类对象 50 | * @param fieldName 文件名 51 | * @return 52 | */ 53 | public static Object getFieldValue(Object obj, String fieldName) { 54 | if (obj == null || TextUtils.isEmpty(fieldName)) { 55 | return null; 56 | } 57 | 58 | Class clazz = obj.getClass(); 59 | while (clazz != Object.class) { 60 | try { 61 | Field field = clazz.getDeclaredField(fieldName); 62 | field.setAccessible(true); 63 | return field.get(obj); 64 | } catch (Exception e) { 65 | } 66 | clazz = clazz.getSuperclass(); 67 | } 68 | Log.e("reflect", "get field " + fieldName + " not found in " + obj.getClass().getName()); 69 | return null; 70 | } 71 | 72 | /** 73 | * 通过类对象,给指定文件设置数据 74 | * @param obj 类对象 75 | * @param fieldName 文件名 76 | * @param value 文件内容 77 | */ 78 | public static void setFieldValue(Object obj, String fieldName, Object value) { 79 | if (obj == null || TextUtils.isEmpty(fieldName)) { 80 | return; 81 | } 82 | 83 | Class clazz = obj.getClass(); 84 | while (clazz != Object.class) { 85 | try { 86 | Field field = clazz.getDeclaredField(fieldName); 87 | field.setAccessible(true); 88 | field.set(obj, value); 89 | return; 90 | } catch (Exception e) { 91 | } 92 | clazz = clazz.getSuperclass(); 93 | } 94 | Log.e("reflect", "set field " + fieldName + " not found in " + obj.getClass().getName()); 95 | } 96 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/loaddrawable/LoadingRendererFactory.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.loaddrawable; 2 | 3 | import android.content.Context; 4 | import android.util.SparseArray; 5 | import java.lang.reflect.Constructor; 6 | import com.example.user.utils.loaddrawable.circle.jump.CollisionLoadingRenderer; 7 | import com.example.user.utils.loaddrawable.circle.jump.DanceLoadingRenderer; 8 | import com.example.user.utils.loaddrawable.circle.jump.GuardLoadingRenderer; 9 | import com.example.user.utils.loaddrawable.circle.jump.SwapLoadingRenderer; 10 | import com.example.user.utils.loaddrawable.circle.rotate.GearLoadingRenderer; 11 | import com.example.user.utils.loaddrawable.circle.rotate.LevelLoadingRenderer; 12 | import com.example.user.utils.loaddrawable.circle.rotate.MaterialLoadingRenderer; 13 | import com.example.user.utils.loaddrawable.circle.rotate.WhorlLoadingRenderer; 14 | import com.example.user.utils.loaddrawable.goods.BalloonLoadingRenderer; 15 | import com.example.user.utils.loaddrawable.goods.WaterBottleLoadingRenderer; 16 | import com.example.user.utils.loaddrawable.scenery.DayNightLoadingRenderer; 17 | import com.example.user.utils.loaddrawable.scenery.ElectricFanLoadingRenderer; 18 | 19 | /** 20 | * 动画加载工厂 21 | */ 22 | 23 | public final class LoadingRendererFactory { 24 | 25 | private static final SparseArray> LOADING_RENDERERS = new SparseArray<>(); 26 | 27 | static { 28 | //circle rotate 29 | LOADING_RENDERERS.put(0, MaterialLoadingRenderer.class); 30 | LOADING_RENDERERS.put(1, LevelLoadingRenderer.class); 31 | LOADING_RENDERERS.put(2, WhorlLoadingRenderer.class); 32 | LOADING_RENDERERS.put(3, GearLoadingRenderer.class); 33 | //circle jump 34 | LOADING_RENDERERS.put(4, SwapLoadingRenderer.class); 35 | LOADING_RENDERERS.put(5, GuardLoadingRenderer.class); 36 | LOADING_RENDERERS.put(6, DanceLoadingRenderer.class); 37 | LOADING_RENDERERS.put(7, CollisionLoadingRenderer.class); 38 | //scenery 39 | LOADING_RENDERERS.put(8, DayNightLoadingRenderer.class); 40 | LOADING_RENDERERS.put(9, ElectricFanLoadingRenderer.class); 41 | //goods 42 | LOADING_RENDERERS.put(10, BalloonLoadingRenderer.class); 43 | LOADING_RENDERERS.put(11, WaterBottleLoadingRenderer.class); 44 | } 45 | 46 | private LoadingRendererFactory() { 47 | } 48 | 49 | public static LoadingRenderer createLoadingRenderer(Context context, int loadingRendererId) throws Exception { 50 | Class loadingRendererClazz = LOADING_RENDERERS.get(loadingRendererId); 51 | Constructor[] constructors = loadingRendererClazz.getDeclaredConstructors(); 52 | for (Constructor constructor : constructors) { 53 | Class[] parameterTypes = constructor.getParameterTypes(); 54 | if (parameterTypes != null 55 | && parameterTypes.length == 1 56 | && parameterTypes[0].equals(Context.class)) { 57 | constructor.setAccessible(true); 58 | return (LoadingRenderer) constructor.newInstance(context); 59 | } 60 | } 61 | 62 | throw new InstantiationException(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/acache/DataCacheManager.java: -------------------------------------------------------------------------------- 1 | package com.huaiseng.xinglu.message; 2 | 3 | import java.io.File; 4 | import java.math.BigDecimal; 5 | 6 | import android.content.Context; 7 | import android.os.Environment; 8 | 9 | /** 10 | * 计算缓存大小、清空缓存操作类 11 | * 12 | * @author Developer_x 13 | * @version 14 | * @date 15 | */ 16 | public class DataCacheManager { 17 | /** 18 | * 检查当前项目文件缓存的大小 19 | * 20 | * @param context 21 | * @return 22 | * @throws Exception 23 | */ 24 | public static String getTotalCacheSize(Context context) throws Exception { 25 | long cacheSize = getFolderSize(context.getCacheDir()); 26 | if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { 27 | cacheSize += getFolderSize(context.getExternalCacheDir()); 28 | } 29 | return getFormatSize(cacheSize); 30 | } 31 | 32 | /** 33 | * 清空当前项目的缓存 34 | * 35 | * @param context 36 | */ 37 | public static void clearAllCache(Context context) { 38 | deleteDir(context.getCacheDir()); 39 | if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { 40 | deleteDir(context.getExternalCacheDir()); 41 | } 42 | } 43 | 44 | /** 45 | * 删除缓存文件夹 46 | * 47 | * @param dir 48 | * @return 49 | */ 50 | private static boolean deleteDir(File dir) { 51 | if (dir != null && dir.isDirectory()) { 52 | String[] children = dir.list(); 53 | for (int i = 0; i < children.length; i++) { 54 | boolean success = deleteDir(new File(dir, children[i])); 55 | if (!success) { 56 | return false; 57 | } 58 | } 59 | } 60 | return dir.delete(); 61 | } 62 | 63 | /** 64 | * 计算当前文件夹的大小 65 | * 66 | * @param file 67 | * @return 68 | */ 69 | public static long getFolderSize(File file) { 70 | long size = 0; 71 | try { 72 | File[] fileList = file.listFiles(); 73 | for (int i = 0; i < fileList.length; i++) { 74 | // 如果下面还有文件 75 | if (fileList[i].isDirectory()) 76 | size = size + getFolderSize(fileList[i]); 77 | else 78 | size = size + fileList[i].length(); 79 | } 80 | } catch (Exception e) { 81 | e.printStackTrace(); 82 | } 83 | return size; 84 | } 85 | 86 | /** 87 | * 格式化单位 88 | * 89 | * @param size 90 | * @return 91 | */ 92 | public static String getFormatSize(double size) { 93 | double kiloByte = size / 1024; 94 | if (kiloByte < 1) { 95 | return size + ""; 96 | } 97 | double megaByte = kiloByte / 1024; 98 | if (megaByte < 1) { 99 | BigDecimal result1 = new BigDecimal(Double.toString(kiloByte)); 100 | return result1.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "KB"; 101 | } 102 | double gigaByte = megaByte / 1024; 103 | if (gigaByte < 1) { 104 | BigDecimal result2 = new BigDecimal(Double.toString(megaByte)); 105 | return result2.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "MB"; 106 | } 107 | double teraBytes = gigaByte / 1024; 108 | if (teraBytes < 1) { 109 | BigDecimal result3 = new BigDecimal(Double.toString(gigaByte)); 110 | return result3.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "GB"; 111 | } 112 | BigDecimal result4 = new BigDecimal(teraBytes); 113 | return result4.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "TB"; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/request/volley/VolleyErrorHelper.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.request.volley; 2 | 3 | import android.content.Context; 4 | 5 | import com.android.volley.AuthFailureError; 6 | import com.android.volley.NetworkError; 7 | import com.android.volley.NetworkResponse; 8 | import com.android.volley.NoConnectionError; 9 | import com.android.volley.ServerError; 10 | import com.android.volley.TimeoutError; 11 | import com.android.volley.VolleyError; 12 | import com.example.user.utils.R; 13 | import com.google.gson.Gson; 14 | import com.google.gson.reflect.TypeToken; 15 | 16 | import java.util.HashMap; 17 | import java.util.Map; 18 | 19 | /** 20 | * Volley请求获取错误信息的帮助类 21 | */ 22 | public class VolleyErrorHelper { 23 | /** 24 | * Returns appropriate message which is to be displayed to the user 25 | * against the specified error object. 26 | * 27 | * @param error 28 | * @param context 29 | * @return 30 | */ 31 | public static String getMessage(Object error, Context context) { 32 | if (error instanceof TimeoutError) { 33 | return context.getResources().getString(R.string.generic_server_down); 34 | } 35 | else if (isServerProblem(error)) { 36 | return handleServerError(error, context); 37 | } 38 | else if (isNetworkProblem(error)) { 39 | return context.getResources().getString(R.string.no_internet); 40 | } 41 | return context.getResources().getString(R.string.generic_error); 42 | } 43 | /** 44 | * Determines whether the error is related to network 45 | * @param error 46 | * @return 47 | */ 48 | private static boolean isNetworkProblem(Object error) { 49 | return (error instanceof NetworkError) || (error instanceof NoConnectionError); 50 | } 51 | /** 52 | * Determines whether the error is related to server 53 | * @param error 54 | * @return 55 | */ 56 | private static boolean isServerProblem(Object error) { 57 | return (error instanceof ServerError) || (error instanceof AuthFailureError); 58 | } 59 | /** 60 | * Handles the server error, tries to determine whether to show a stock message or to 61 | * show a message retrieved from the server. 62 | * 63 | * @param err 64 | * @param context 65 | * @return 66 | */ 67 | private static String handleServerError(Object err, Context context) { 68 | VolleyError error = (VolleyError) err; 69 | NetworkResponse response = error.networkResponse; 70 | if (response != null) { 71 | switch (response.statusCode) { 72 | case 404: 73 | case 422: 74 | case 401: 75 | try { 76 | // server might return error like this { "error": "Some error occured" } 77 | // Use "Gson" to parse the result 78 | HashMap result = new Gson().fromJson(new String(response.data), 79 | new TypeToken>() { 80 | }.getType()); 81 | if (result != null && result.containsKey("error")) { 82 | return result.get("error"); 83 | } 84 | } catch (Exception e) { 85 | e.printStackTrace(); 86 | } 87 | // invalid request 88 | return error.getMessage(); 89 | default: 90 | return context.getResources().getString(R.string.generic_server_down); 91 | } 92 | } 93 | return context.getResources().getString(R.string.generic_error); 94 | } 95 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/util/DeviceUtils.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.util; 2 | 3 | import android.content.Context; 4 | import android.net.wifi.WifiInfo; 5 | import android.net.wifi.WifiManager; 6 | import android.os.Build; 7 | import android.provider.Settings; 8 | 9 | import java.io.IOException; 10 | import java.io.InputStreamReader; 11 | import java.io.LineNumberReader; 12 | 13 | /** 14 | *
 15 |  *     author: Blankj
 16 |  *     blog  : http://blankj.com
 17 |  *     time  : 2016/8/1
 18 |  *     desc  : 设备相关工具类
 19 |  * 
20 | */ 21 | public class DeviceUtils { 22 | 23 | private DeviceUtils() { 24 | throw new UnsupportedOperationException("u can't instantiate me..."); 25 | } 26 | 27 | /** 28 | * 获取系统版本号 29 | */ 30 | public static int getSDK() { 31 | return Build.VERSION.SDK_INT; 32 | } 33 | 34 | 35 | /** 36 | * 获取AndroidID 37 | * 38 | * @param context 上下文 39 | * @return AndroidID 40 | */ 41 | public static String getAndroidID(Context context) { 42 | return Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID); 43 | } 44 | 45 | /** 46 | * 获取设备MAC地址 47 | *

需添加权限 {@code }

48 | * 49 | * @param context 上下文 50 | * @return MAC地址 51 | */ 52 | public static String getMacAddress(Context context) { 53 | WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); 54 | WifiInfo info = wifi.getConnectionInfo(); 55 | if (info != null) { 56 | String macAddress = info.getMacAddress(); 57 | if (macAddress != null) { 58 | return macAddress.replace(":", ""); 59 | } 60 | } 61 | return null; 62 | } 63 | 64 | /** 65 | * 获取设备MAC地址 66 | *

需添加权限 {@code }

67 | * 68 | * @return MAC地址 69 | */ 70 | 71 | public static String getMacAddress() { 72 | String macAddress = null; 73 | LineNumberReader lnr = null; 74 | InputStreamReader isr = null; 75 | try { 76 | Process pp = Runtime.getRuntime().exec("cat /sys/class/net/wlan0/address"); 77 | isr = new InputStreamReader(pp.getInputStream()); 78 | lnr = new LineNumberReader(isr); 79 | macAddress = lnr.readLine().replace(":", ""); 80 | } catch (IOException e) { 81 | e.printStackTrace(); 82 | } finally { 83 | FileUtils.closeIO(lnr, isr); 84 | } 85 | return macAddress == null ? "" : macAddress; 86 | } 87 | 88 | /** 89 | * 获取设备厂商,如Xiaomi 90 | * 91 | * @return 设备厂商 92 | */ 93 | public static String getManufacturer() { 94 | return Build.MANUFACTURER; 95 | } 96 | 97 | /** 98 | * 获取设备型号,如MI2SC 99 | * 100 | * @return 设备型号 101 | */ 102 | public static String getModel() { 103 | String model = Build.MODEL; 104 | if (model != null) { 105 | model = model.trim().replaceAll("\\s*", ""); 106 | } else { 107 | model = ""; 108 | } 109 | return model; 110 | } 111 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/sys/ObjectUtils.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.sys; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * 一些常用的对象判断方法集合 8 | * Created by slj on 2016/5/26. 9 | */ 10 | public class ObjectUtils { 11 | 12 | /** 13 | * ObjectUtils 14 | */ 15 | public ObjectUtils() { 16 | throw new AssertionError(); 17 | } 18 | 19 | /** 20 | * compare two object 21 | * 22 | * @param actual 23 | * @param expected 24 | * @return
    25 | *
  • if both are null, return true
  • 26 | *
  • return actual.{@link Object#equals(Object)}
  • 27 | *
28 | */ 29 | public static boolean isEquals(Object actual, Object expected) { 30 | return actual == expected || (actual == null ? expected == null : actual.equals(expected)); 31 | } 32 | 33 | /** 34 | * compare two object 35 | *
    36 | * About result 37 | *
  • if v1 > v2, return 1
  • 38 | *
  • if v1 = v2, return 0
  • 39 | *
  • if v1 < v2, return -1
  • 40 | *
41 | *
    42 | * About rule 43 | *
  • if v1 is null, v2 is null, then return 0
  • 44 | *
  • if v1 is null, v2 is not null, then return -1
  • 45 | *
  • if v1 is not null, v2 is null, then return 1
  • 46 | *
  • return v1.{@link Comparable#compareTo(Object)}
  • 47 | *
48 | * 49 | * @param v1 50 | * @param v2 51 | * @return 52 | */ 53 | @SuppressWarnings({"unchecked", "rawtypes"}) 54 | public static int compare(V v1, V v2) { 55 | return v1 == null ? (v2 == null ? 0 : -1) : (v2 == null ? 1 : ((Comparable)v1).compareTo(v2)); 56 | } 57 | 58 | /** 59 | * get size of list 60 | * 61 | *
 62 |      * getSize(null)   =   0;
 63 |      * getSize({})     =   0;
 64 |      * getSize({1})    =   1;
 65 |      * 
66 | * 67 | * @param 68 | * @param sourceList 69 | * @return if list is null or empty, return 0, else return {@link List#size()}. 70 | */ 71 | public static int getSize(List sourceList) { 72 | return sourceList == null ? 0 : sourceList.size(); 73 | } 74 | 75 | /** 76 | * is null or its size is 0 77 | * 78 | *
 79 |      * isEmpty(null)   =   true;
 80 |      * isEmpty({})     =   true;
 81 |      * isEmpty({1})    =   false;
 82 |      * 
83 | * 84 | * @param 85 | * @param sourceList 86 | * @return if list is null or its size is 0, return true, else return false. 87 | */ 88 | public static boolean isEmpty(List sourceList) { 89 | return (sourceList == null || sourceList.size() == 0); 90 | } 91 | 92 | /** 93 | * invert list 94 | * 95 | * @param 96 | * @param sourceList 97 | * @return 98 | */ 99 | public static List invertList(List sourceList) { 100 | if (isEmpty(sourceList)) { 101 | return sourceList; 102 | } 103 | 104 | List invertList = new ArrayList(sourceList.size()); 105 | for (int i = sourceList.size() - 1; i >= 0; i--) { 106 | invertList.add(sourceList.get(i)); 107 | } 108 | return invertList; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/util/CleanUtils.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.util; 2 | 3 | import android.content.Context; 4 | 5 | import java.io.File; 6 | 7 | /** 8 | *
  9 |  *     author: Blankj
 10 |  *     blog  : http://blankj.com
 11 |  *     time  : 2016/9/27
 12 |  *     desc  : 清除相关工具类
 13 |  * 
14 | */ 15 | public class CleanUtils { 16 | 17 | private CleanUtils() { 18 | throw new UnsupportedOperationException("u can't instantiate me..."); 19 | } 20 | 21 | /** 22 | * 清除内部缓存 23 | *

/data/data/com.xxx.xxx/cache

24 | * 25 | * @param context 上下文 26 | * @return {@code true}: 清除成功
{@code false}: 清除失败 27 | */ 28 | public static boolean cleanInternalCache(Context context) { 29 | return FileUtils.deleteFilesInDir(context.getCacheDir()); 30 | } 31 | 32 | /** 33 | * 清除内部文件 34 | *

/data/data/com.xxx.xxx/files

35 | * 36 | * @param context 上下文 37 | * @return {@code true}: 清除成功
{@code false}: 清除失败 38 | */ 39 | public static boolean cleanInternalFiles(Context context) { 40 | return FileUtils.deleteFilesInDir(context.getFilesDir()); 41 | } 42 | 43 | /** 44 | * 清除内部数据库 45 | *

/data/data/com.xxx.xxx/databases

46 | * 47 | * @param context 上下文 48 | * @return {@code true}: 清除成功
{@code false}: 清除失败 49 | */ 50 | public static boolean cleanInternalDbs(Context context) { 51 | return FileUtils.deleteFilesInDir(context.getFilesDir().getParent() + File.separator + "databases"); 52 | } 53 | 54 | /** 55 | * 根据名称清除数据库 56 | *

/data/data/com.xxx.xxx/databases/dbName

57 | * 58 | * @param context 上下文 59 | * @param dbName 数据库名称 60 | * @return {@code true}: 清除成功
{@code false}: 清除失败 61 | */ 62 | public static boolean cleanInternalDbByName(Context context, String dbName) { 63 | return context.deleteDatabase(dbName); 64 | } 65 | 66 | /** 67 | * 清除内部SP 68 | *

/data/data/com.xxx.xxx/shared_prefs

69 | * 70 | * @param context 上下文 71 | * @return {@code true}: 清除成功
{@code false}: 清除失败 72 | */ 73 | public static boolean cleanInternalSP(Context context) { 74 | return FileUtils.deleteFilesInDir(context.getFilesDir().getParent() + File.separator + "shared_prefs"); 75 | } 76 | 77 | /** 78 | * 清除外部缓存 79 | *

/storage/emulated/0/android/data/com.xxx.xxx/cache

80 | * 81 | * @param context 上下文 82 | * @return {@code true}: 清除成功
{@code false}: 清除失败 83 | */ 84 | public static boolean cleanExternalCache(Context context) { 85 | return SDCardUtils.isSDCardEnable() && FileUtils.deleteFilesInDir(context.getExternalCacheDir()); 86 | } 87 | 88 | /** 89 | * 清除自定义目录下的文件 90 | * 91 | * @param dirPath 目录路径 92 | * @return {@code true}: 清除成功
{@code false}: 清除失败 93 | */ 94 | public static boolean cleanCustomCache(String dirPath) { 95 | return FileUtils.deleteFilesInDir(dirPath); 96 | } 97 | 98 | /** 99 | * 清除自定义目录下的文件 100 | * 101 | * @param dir 目录 102 | * @return {@code true}: 清除成功
{@code false}: 清除失败 103 | */ 104 | public static boolean cleanCustomCache(File dir) { 105 | return FileUtils.deleteFilesInDir(dir); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/util/ClipboardUtils.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.util; 2 | 3 | import android.content.ClipData; 4 | import android.content.ClipboardManager; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.net.Uri; 8 | 9 | /** 10 | *

 11 |  *     author: Blankj
 12 |  *     blog  : http://blankj.com
 13 |  *     time  : 2016/9/25
 14 |  *     desc  : 剪贴板相关工具类
 15 |  * 
16 | */ 17 | public class ClipboardUtils { 18 | 19 | private ClipboardUtils() { 20 | throw new UnsupportedOperationException("u can't instantiate me..."); 21 | } 22 | 23 | /** 24 | * 复制文本到剪贴板 25 | * 26 | * @param context 上下文 27 | * @param text 文本 28 | */ 29 | public static void copyText(Context context, CharSequence text) { 30 | ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); 31 | clipboard.setPrimaryClip(ClipData.newPlainText("text", text)); 32 | } 33 | 34 | /** 35 | * 获取剪贴板的文本 36 | * 37 | * @param context 上下文 38 | * @return 剪贴板的文本 39 | */ 40 | public static CharSequence getText(Context context) { 41 | ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); 42 | ClipData clip = clipboard.getPrimaryClip(); 43 | if (clip != null && clip.getItemCount() > 0) { 44 | return clip.getItemAt(0).coerceToText(context); 45 | } 46 | return null; 47 | } 48 | 49 | /** 50 | * 复制uri到剪贴板 51 | * 52 | * @param context 上下文 53 | * @param uri uri 54 | */ 55 | public static void copyUri(Context context, Uri uri) { 56 | ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); 57 | clipboard.setPrimaryClip(ClipData.newUri(context.getContentResolver(), "uri", uri)); 58 | } 59 | 60 | /** 61 | * 获取剪贴板的uri 62 | * 63 | * @param context 上下文 64 | * @return 剪贴板的uri 65 | */ 66 | public static Uri getUri(Context context) { 67 | ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); 68 | ClipData clip = clipboard.getPrimaryClip(); 69 | if (clip != null && clip.getItemCount() > 0) { 70 | return clip.getItemAt(0).getUri(); 71 | } 72 | return null; 73 | } 74 | 75 | /** 76 | * 复制意图到剪贴板 77 | * 78 | * @param context 上下文 79 | * @param intent 意图 80 | */ 81 | public static void copyIntent(Context context, Intent intent) { 82 | ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); 83 | clipboard.setPrimaryClip(ClipData.newIntent("intent", intent)); 84 | } 85 | 86 | /** 87 | * 获取剪贴板的意图 88 | * 89 | * @param context 上下文 90 | * @return 剪贴板的意图 91 | */ 92 | public static Intent getIntent(Context context) { 93 | ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); 94 | ClipData clip = clipboard.getPrimaryClip(); 95 | if (clip != null && clip.getItemCount() > 0) { 96 | return clip.getItemAt(0).getIntent(); 97 | } 98 | return null; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/util/EmptyUtils.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.util; 2 | 3 | import android.os.Build; 4 | import android.util.SparseArray; 5 | import android.util.SparseBooleanArray; 6 | import android.util.SparseIntArray; 7 | import android.util.SparseLongArray; 8 | 9 | import java.lang.reflect.Array; 10 | import java.util.Collection; 11 | import java.util.Map; 12 | 13 | /** 14 | *
15 |  *     author: Blankj
16 |  *     blog  : http://blankj.com
17 |  *     time  : 2016/9/28
18 |  *     desc  : 判空相关工具类
19 |  * 
20 | */ 21 | public class EmptyUtils { 22 | 23 | private EmptyUtils() { 24 | throw new UnsupportedOperationException("u can't instantiate me..."); 25 | } 26 | 27 | /** 28 | * 判断对象是否为空 29 | * 30 | * @param obj 对象 31 | * @return {@code true}: 为空
{@code false}: 不为空 32 | */ 33 | public static boolean isEmpty(Object obj) { 34 | if (obj == null) { 35 | return true; 36 | } else if (obj instanceof String && obj.toString().length() == 0) { 37 | return true; 38 | } else if (obj.getClass().isArray() && Array.getLength(obj) == 0) { 39 | return true; 40 | } else if (obj instanceof Collection && ((Collection) obj).isEmpty()) { 41 | return true; 42 | } else if (obj instanceof Map && ((Map) obj).isEmpty()) { 43 | return true; 44 | } else if (obj instanceof SparseArray && ((SparseArray) obj).size() == 0) { 45 | return true; 46 | } else if (obj instanceof SparseBooleanArray && ((SparseBooleanArray) obj).size() == 0) { 47 | return true; 48 | } else if (obj instanceof SparseIntArray && ((SparseIntArray) obj).size() == 0) { 49 | return true; 50 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { 51 | if (obj instanceof SparseLongArray && ((SparseLongArray) obj).size() == 0) { 52 | return true; 53 | } 54 | } 55 | return false; 56 | } 57 | 58 | /** 59 | * 判断对象是否非空 60 | *

不要问我为什么不直接调用{@code !isEmpty(obj);}

61 | * 62 | * @param obj 对象 63 | * @return {@code true}: 非空
{@code false}: 空 64 | */ 65 | public static boolean isNotEmpty(Object obj) { 66 | if (obj == null) { 67 | return false; 68 | } else if (obj instanceof String && obj.toString().length() == 0) { 69 | return false; 70 | } else if (obj.getClass().isArray() && Array.getLength(obj) == 0) { 71 | return false; 72 | } else if (obj instanceof Collection && ((Collection) obj).isEmpty()) { 73 | return false; 74 | } else if (obj instanceof Map && ((Map) obj).isEmpty()) { 75 | return false; 76 | } else if (obj instanceof SparseArray && ((SparseArray) obj).size() == 0) { 77 | return false; 78 | } else if (obj instanceof SparseBooleanArray && ((SparseBooleanArray) obj).size() == 0) { 79 | return false; 80 | } else if (obj instanceof SparseIntArray && ((SparseIntArray) obj).size() == 0) { 81 | return false; 82 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { 83 | if (obj instanceof SparseLongArray && ((SparseLongArray) obj).size() == 0) { 84 | return false; 85 | } 86 | } 87 | return true; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/string/CyptoUtils.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.string; 2 | 3 | 4 | 5 | import java.security.InvalidAlgorithmParameterException; 6 | import java.security.Key; 7 | import java.security.spec.AlgorithmParameterSpec; 8 | 9 | import javax.crypto.Cipher; 10 | import javax.crypto.SecretKeyFactory; 11 | import javax.crypto.spec.DESKeySpec; 12 | import javax.crypto.spec.IvParameterSpec; 13 | 14 | /** 15 | * 加密解密工具包 16 | * @author Winter Lau 17 | * @date 2011-12-26 18 | */ 19 | public class CyptoUtils { 20 | 21 | public static final String ALGORITHM_DES = "DES/CBC/PKCS5Padding"; 22 | 23 | /** 24 | * DES算法,加密 25 | * 26 | * @param data 待加密字符串 27 | * @param key 加密私钥,长度不能够小于8位 28 | * @return 加密后的字节数组,一般结合Base64编码使用 29 | * @throws InvalidAlgorithmParameterException 30 | * @throws Exception 31 | */ 32 | public static String encode(String key,String data) { 33 | if(data == null) 34 | return null; 35 | try{ 36 | DESKeySpec dks = new DESKeySpec(key.getBytes()); 37 | SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); 38 | //key的长度不能够小于8位字节 39 | Key secretKey = keyFactory.generateSecret(dks); 40 | Cipher cipher = Cipher.getInstance(ALGORITHM_DES); 41 | IvParameterSpec iv = new IvParameterSpec("12345678".getBytes()); 42 | AlgorithmParameterSpec paramSpec = iv; 43 | cipher.init(Cipher.ENCRYPT_MODE, secretKey,paramSpec); 44 | byte[] bytes = cipher.doFinal(data.getBytes()); 45 | return byte2hex(bytes); 46 | }catch(Exception e){ 47 | e.printStackTrace(); 48 | return data; 49 | } 50 | } 51 | 52 | /** 53 | * DES算法,解密 54 | * 55 | * @param data 待解密字符串 56 | * @param key 解密私钥,长度不能够小于8位 57 | * @return 解密后的字节数组 58 | * @throws Exception 异常 59 | */ 60 | public static String decode(String key,String data) { 61 | if(data == null) 62 | return null; 63 | try { 64 | DESKeySpec dks = new DESKeySpec(key.getBytes()); 65 | SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); 66 | //key的长度不能够小于8位字节 67 | Key secretKey = keyFactory.generateSecret(dks); 68 | Cipher cipher = Cipher.getInstance(ALGORITHM_DES); 69 | IvParameterSpec iv = new IvParameterSpec("12345678".getBytes()); 70 | AlgorithmParameterSpec paramSpec = iv; 71 | cipher.init(Cipher.DECRYPT_MODE, secretKey, paramSpec); 72 | return new String(cipher.doFinal(hex2byte(data.getBytes()))); 73 | } catch (Exception e){ 74 | e.printStackTrace(); 75 | return data; 76 | } 77 | } 78 | 79 | /** 80 | * 二行制转字符串 81 | * @param b 82 | * @return 83 | */ 84 | private static String byte2hex(byte[] b) { 85 | StringBuilder hs = new StringBuilder(); 86 | String stmp; 87 | for (int n = 0; b!=null && n < b.length; n++) { 88 | stmp = Integer.toHexString(b[n] & 0XFF); 89 | if (stmp.length() == 1) 90 | hs.append('0'); 91 | hs.append(stmp); 92 | } 93 | return hs.toString().toUpperCase(); 94 | } 95 | 96 | private static byte[] hex2byte(byte[] b) { 97 | if((b.length%2)!=0) 98 | throw new IllegalArgumentException(); 99 | byte[] b2 = new byte[b.length/2]; 100 | for (int n = 0; n < b.length; n+=2) { 101 | String item = new String(b,n,2); 102 | b2[n/2] = (byte)Integer.parseInt(item,16); 103 | } 104 | return b2; 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/util/ConstUtils.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.util; 2 | 3 | /** 4 | *
  5 |  *     author: Blankj
  6 |  *     blog  : http://blankj.com
  7 |  *     time  : 2016/8/11
  8 |  *     desc  : 常量相关工具类
  9 |  * 
10 | */ 11 | public class ConstUtils { 12 | 13 | private ConstUtils() { 14 | throw new UnsupportedOperationException("u can't instantiate me..."); 15 | } 16 | 17 | /******************** 存储相关常量 ********************/ 18 | /** 19 | * Byte与Byte的倍数 20 | */ 21 | public static final int BYTE = 1; 22 | /** 23 | * KB与Byte的倍数 24 | */ 25 | public static final int KB = 1024; 26 | /** 27 | * MB与Byte的倍数 28 | */ 29 | public static final int MB = 1048576; 30 | /** 31 | * GB与Byte的倍数 32 | */ 33 | public static final int GB = 1073741824; 34 | 35 | public enum MemoryUnit { 36 | BYTE, 37 | KB, 38 | MB, 39 | GB 40 | } 41 | 42 | /******************** 时间相关常量 ********************/ 43 | /** 44 | * 毫秒与毫秒的倍数 45 | */ 46 | public static final int MSEC = 1; 47 | /** 48 | * 秒与毫秒的倍数 49 | */ 50 | public static final int SEC = 1000; 51 | /** 52 | * 分与毫秒的倍数 53 | */ 54 | public static final int MIN = 60000; 55 | /** 56 | * 时与毫秒的倍数 57 | */ 58 | public static final int HOUR = 3600000; 59 | /** 60 | * 天与毫秒的倍数 61 | */ 62 | public static final int DAY = 86400000; 63 | 64 | public enum TimeUnit { 65 | MSEC, 66 | SEC, 67 | MIN, 68 | HOUR, 69 | DAY 70 | } 71 | 72 | /******************** 正则相关常量 ********************/ 73 | /** 74 | * 正则:手机号(简单) 75 | */ 76 | public static final String REGEX_MOBILE_SIMPLE = "^[1]\\d{10}$"; 77 | /** 78 | * 正则:手机号(精确) 79 | *

移动:134(0-8)、135、136、137、138、139、147、150、151、152、157、158、159、178、182、183、184、187、188

80 | *

联通:130、131、132、145、155、156、175、176、185、186

81 | *

电信:133、153、173、177、180、181、189

82 | *

全球星:1349

83 | *

虚拟运营商:170

84 | */ 85 | public static final String REGEX_MOBILE_EXACT = "^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(17[0,3,5-8])|(18[0-9])|(147))\\d{8}$"; 86 | /** 87 | * 正则:电话号码 88 | */ 89 | public static final String REGEX_TEL = "^0\\d{2,3}[- ]?\\d{7,8}"; 90 | /** 91 | * 正则:身份证号码15位 92 | */ 93 | public static final String REGEX_IDCARD15 = "^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}$"; 94 | /** 95 | * 正则:身份证号码18位 96 | */ 97 | public static final String REGEX_IDCARD18 = "^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}([0-9Xx])$"; 98 | /** 99 | * 正则:邮箱 100 | */ 101 | public static final String REGEX_EMAIL = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$"; 102 | /** 103 | * 正则:URL 104 | */ 105 | public static final String REGEX_URL = "http(s)?://([\\w-]+\\.)+[\\w-]+(/[\\w-./?%&=]*)?"; 106 | /** 107 | * 正则:汉字 108 | */ 109 | public static final String REGEX_CHZ = "^[\\u4e00-\\u9fa5]+$"; 110 | /** 111 | * 正则:用户名,取值范围为a-z,A-Z,0-9,"_",汉字,不能以"_"结尾,用户名必须是6-20位 112 | */ 113 | public static final String REGEX_USERNAME = "^[\\w\\u4e00-\\u9fa5]{6,20}(? 7) { 112 | String picturePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath(); 113 | return picturePath + "/nim/"; 114 | } else { 115 | String picturePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getAbsolutePath(); 116 | return picturePath + "/nim/"; 117 | } 118 | } 119 | 120 | public static boolean isInvalidVideoFile(String filePath) { 121 | return filePath.toLowerCase().endsWith(".3gp") 122 | || filePath.toLowerCase().endsWith(".mp4"); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/loaddrawable/LoadingRenderer.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.loaddrawable; 2 | 3 | import android.animation.Animator; 4 | import android.animation.ValueAnimator; 5 | import android.content.Context; 6 | import android.graphics.Canvas; 7 | import android.graphics.ColorFilter; 8 | import android.graphics.Rect; 9 | import android.graphics.drawable.Drawable; 10 | import android.view.animation.Animation; 11 | import android.view.animation.LinearInterpolator; 12 | import com.example.user.utils.util.AppUtils; 13 | 14 | /** 15 | * 加载动画的基础类 16 | */ 17 | public abstract class LoadingRenderer { 18 | private static final long ANIMATION_DURATION = 1333; 19 | private static final float DEFAULT_SIZE = 56.0f; 20 | 21 | private final ValueAnimator.AnimatorUpdateListener mAnimatorUpdateListener 22 | = new ValueAnimator.AnimatorUpdateListener() { 23 | @Override 24 | public void onAnimationUpdate(ValueAnimator animation) { 25 | computeRender((float) animation.getAnimatedValue()); 26 | invalidateSelf(); 27 | } 28 | }; 29 | 30 | /** 31 | * Whenever {@link LoadingDrawable} boundary changes mBounds will be updated. 32 | * More details you can see {@link LoadingDrawable#onBoundsChange(Rect)} 33 | */ 34 | protected final Rect mBounds = new Rect(); 35 | 36 | private Drawable.Callback mCallback; 37 | private ValueAnimator mRenderAnimator; 38 | 39 | protected long mDuration; 40 | 41 | protected float mWidth; 42 | protected float mHeight; 43 | 44 | public LoadingRenderer(Context context) { 45 | initParams(context); 46 | setupAnimators(); 47 | } 48 | 49 | @Deprecated 50 | protected void draw(Canvas canvas, Rect bounds) { 51 | } 52 | 53 | protected void draw(Canvas canvas) { 54 | draw(canvas, mBounds); 55 | } 56 | 57 | protected abstract void computeRender(float renderProgress); 58 | 59 | protected abstract void setAlpha(int alpha); 60 | 61 | protected abstract void setColorFilter(ColorFilter cf); 62 | 63 | protected abstract void reset(); 64 | 65 | protected void addRenderListener(Animator.AnimatorListener animatorListener) { 66 | mRenderAnimator.addListener(animatorListener); 67 | } 68 | 69 | void start() { 70 | reset(); 71 | mRenderAnimator.addUpdateListener(mAnimatorUpdateListener); 72 | 73 | mRenderAnimator.setRepeatCount(ValueAnimator.INFINITE); 74 | mRenderAnimator.setDuration(mDuration); 75 | mRenderAnimator.start(); 76 | } 77 | 78 | void stop() { 79 | // if I just call mRenderAnimator.end(), 80 | // it will always call the method onAnimationUpdate(ValueAnimator animation) 81 | // why ? if you know why please send email to me (dinus_developer@163.com) 82 | mRenderAnimator.removeUpdateListener(mAnimatorUpdateListener); 83 | 84 | mRenderAnimator.setRepeatCount(0); 85 | mRenderAnimator.setDuration(0); 86 | mRenderAnimator.end(); 87 | } 88 | 89 | boolean isRunning() { 90 | return mRenderAnimator.isRunning(); 91 | } 92 | 93 | void setCallback(Drawable.Callback callback) { 94 | this.mCallback = callback; 95 | } 96 | 97 | void setBounds(Rect bounds) { 98 | mBounds.set(bounds); 99 | } 100 | 101 | private void initParams(Context context) { 102 | mWidth = AppUtils.dp2px(context, DEFAULT_SIZE); 103 | mHeight =AppUtils.dp2px(context, DEFAULT_SIZE); 104 | 105 | mDuration = ANIMATION_DURATION; 106 | } 107 | 108 | private void setupAnimators() { 109 | mRenderAnimator = ValueAnimator.ofFloat(0.0f, 1.0f); 110 | mRenderAnimator.setRepeatCount(Animation.INFINITE); 111 | mRenderAnimator.setRepeatMode(Animation.RESTART); 112 | mRenderAnimator.setDuration(mDuration); 113 | //fuck you! the default interpolator is AccelerateDecelerateInterpolator 114 | mRenderAnimator.setInterpolator(new LinearInterpolator()); 115 | mRenderAnimator.addUpdateListener(mAnimatorUpdateListener); 116 | } 117 | 118 | private void invalidateSelf() { 119 | mCallback.invalidateDrawable(null); 120 | } 121 | 122 | } 123 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/sys/ScreenUtil.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.sys; 2 | 3 | import android.content.Context; 4 | import android.content.res.Resources; 5 | import android.util.DisplayMetrics; 6 | import android.util.Log; 7 | 8 | import java.lang.reflect.Field; 9 | 10 | public class ScreenUtil { 11 | private static final String TAG = "ScreenUtil"; 12 | 13 | private static double RATIO = 0.85; 14 | 15 | public static int screenWidth; 16 | public static int screenHeight; 17 | public static int screenMin;// 宽高中,小的一边 18 | public static int screenMax;// 宽高中,较大的值 19 | 20 | public static float density; 21 | public static float scaleDensity; 22 | public static float xdpi; 23 | public static float ydpi; 24 | public static int densityDpi; 25 | 26 | public static int dialogWidth; 27 | public static int statusbarheight; 28 | public static int navbarheight; 29 | 30 | 31 | public static int dip2px(float dipValue) { 32 | return (int) (dipValue * density + 0.5f); 33 | } 34 | 35 | public static int px2dip(float pxValue) { 36 | return (int) (pxValue / density + 0.5f); 37 | } 38 | 39 | public static int sp2px(float spValue) { 40 | return (int) (spValue * scaleDensity + 0.5f); 41 | } 42 | 43 | public static int getDialogWidth() { 44 | dialogWidth = (int) (screenMin * RATIO); 45 | return dialogWidth; 46 | } 47 | 48 | public static void init(Context context) { 49 | if (null == context) { 50 | return; 51 | } 52 | DisplayMetrics dm = context.getApplicationContext().getResources().getDisplayMetrics(); 53 | screenWidth = dm.widthPixels; 54 | screenHeight = dm.heightPixels; 55 | screenMin = (screenWidth > screenHeight) ? screenHeight : screenWidth; 56 | density = dm.density; 57 | scaleDensity = dm.scaledDensity; 58 | xdpi = dm.xdpi; 59 | ydpi = dm.ydpi; 60 | densityDpi = dm.densityDpi; 61 | 62 | Log.d(TAG, "screenWidth=" + screenWidth + " screenHeight=" + screenHeight + " density=" + density); 63 | } 64 | 65 | public static int getDisplayWidth() { 66 | if (screenWidth == 0) { 67 | GetInfo(DemoCache.getContext()); 68 | } 69 | return screenWidth; 70 | } 71 | 72 | public static int getDisplayHeight() { 73 | if (screenHeight == 0) { 74 | GetInfo(DemoCache.getContext()); 75 | } 76 | return screenHeight; 77 | } 78 | 79 | public static void GetInfo(Context context) { 80 | if (null == context) { 81 | return; 82 | } 83 | DisplayMetrics dm = context.getApplicationContext().getResources().getDisplayMetrics(); 84 | screenWidth = dm.widthPixels; 85 | screenHeight = dm.heightPixels; 86 | screenMin = (screenWidth > screenHeight) ? screenHeight : screenWidth; 87 | screenMax = (screenWidth < screenHeight) ? screenHeight : screenWidth; 88 | density = dm.density; 89 | scaleDensity = dm.scaledDensity; 90 | xdpi = dm.xdpi; 91 | ydpi = dm.ydpi; 92 | densityDpi = dm.densityDpi; 93 | statusbarheight = getStatusBarHeight(context); 94 | navbarheight = getNavBarHeight(context); 95 | Log.d(TAG, "screenWidth=" + screenWidth + " screenHeight=" + screenHeight + " density=" + density); 96 | } 97 | 98 | public static int getStatusBarHeight(Context context) { 99 | if (statusbarheight == 0) { 100 | try { 101 | Class c = Class.forName("com.android.internal.R$dimen"); 102 | Object o = c.newInstance(); 103 | Field field = c.getField("status_bar_height"); 104 | int x = (Integer) field.get(o); 105 | statusbarheight = context.getResources().getDimensionPixelSize(x); 106 | } catch (Exception e) { 107 | e.printStackTrace(); 108 | } 109 | } 110 | if (statusbarheight == 0) { 111 | statusbarheight = ScreenUtil.dip2px(25); 112 | } 113 | return statusbarheight; 114 | } 115 | 116 | public static int getNavBarHeight(Context context) { 117 | Resources resources = context.getResources(); 118 | int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); 119 | if (resourceId > 0) { 120 | return resources.getDimensionPixelSize(resourceId); 121 | } 122 | return 0; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/media/SampleSizeUtil.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.media; 2 | 3 | import android.opengl.GLES10; 4 | 5 | public class SampleSizeUtil { 6 | 7 | public static int calculateSampleSize(String imagePath, int totalPixel) { 8 | int[] bound = BitmapDecoder.decodeBound(imagePath); 9 | return calculateSampleSize(bound[0], bound[1], totalPixel); 10 | } 11 | 12 | public static int calculateSampleSize(int width, int height, int totalPixel) { 13 | int ratio = 1; 14 | 15 | if (width > 0 && height > 0) { 16 | ratio = (int) Math.sqrt((float) (width * height) / totalPixel); 17 | if (ratio < 1) { 18 | ratio = 1; 19 | } 20 | } 21 | 22 | return ratio; 23 | } 24 | 25 | /** 26 | * Calculate an inSampleSize for use in a {@link android.graphics.BitmapFactory.Options} 27 | * object when decoding bitmaps using the decode* methods from 28 | * {@link android.graphics.BitmapFactory}. This implementation calculates the closest 29 | * inSampleSize that will result in the final decoded bitmap having a width 30 | * and height equal to or larger than the requested width and height. This 31 | * implementation does not ensure a power of 2 is returned for inSampleSize 32 | * which can be faster when decoding but results in a larger bitmap which 33 | * isn't as useful for caching purposes. 34 | * 35 | * @param width 36 | * @param height 37 | * @param reqWidth 38 | * @param reqHeight 39 | * @return 40 | */ 41 | public static int calculateSampleSize(int width, int height, int reqWidth, int reqHeight) { 42 | // can't proceed 43 | if (width <= 0 || height <= 0) { 44 | return 1; 45 | } 46 | // can't proceed 47 | if (reqWidth <= 0 && reqHeight <= 0) { 48 | return 1; 49 | } else if (reqWidth <= 0) { 50 | reqWidth = (int) (width * reqHeight / (float)height + 0.5f) ; 51 | } else if (reqHeight <= 0) { 52 | reqHeight = (int) (height * reqWidth / (float)width + 0.5f); 53 | } 54 | 55 | int inSampleSize = 1; 56 | 57 | if (height > reqHeight || width > reqWidth) { 58 | // Calculate ratios of height and width to requested height and width 59 | final int heightRatio = Math.round((float) height / (float) reqHeight); 60 | final int widthRatio = Math.round((float) width / (float) reqWidth); 61 | 62 | // Choose the smallest ratio as inSampleSize value, this will 63 | // guarantee a final image 64 | // with both dimensions larger than or equal to the requested height and width. 65 | inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; 66 | if (inSampleSize == 0) { 67 | inSampleSize = 1; 68 | } 69 | 70 | // This offers some additional logic in case the image has a strange 71 | // aspect ratio. For example, a panorama may have a much larger 72 | // width than height. In these cases the total pixels might still 73 | // end up being too large to fit comfortably in memory, so we should 74 | // be more aggressive with sample down the image (=larger 75 | // inSampleSize). 76 | 77 | final float totalPixels = width * height; 78 | 79 | // Anything more than 2x the requested pixels we'll sample down 80 | // further 81 | final float totalReqPixelsCap = reqWidth * reqHeight * 2; 82 | 83 | while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) { 84 | inSampleSize++; 85 | } 86 | } 87 | 88 | return inSampleSize; 89 | } 90 | 91 | public static final int adjustSampleSizeWithTexture(int sampleSize, int width, int height) { 92 | int textureSize = getTextureSize(); 93 | 94 | if ((textureSize > 0) && ((width > sampleSize) || (height > sampleSize))) { 95 | while ((width / (float)sampleSize) > textureSize || (height / (float)sampleSize) > textureSize) { 96 | sampleSize++; 97 | } 98 | 99 | // 2的指数对齐 100 | sampleSize = SampleSizeUtil.roundup2n(sampleSize); 101 | } 102 | 103 | return sampleSize; 104 | } 105 | 106 | private static int textureSize = 0; 107 | //存在第二次拿拿不到的情况,所以把拿到的数据用一个static变量保存下来 108 | public static final int getTextureSize() { 109 | if (textureSize > 0) { 110 | return textureSize; 111 | } 112 | 113 | int[] params = new int[1]; 114 | GLES10.glGetIntegerv(GLES10.GL_MAX_TEXTURE_SIZE, params, 0); 115 | textureSize = params[0]; 116 | 117 | return textureSize; 118 | } 119 | 120 | // 将x向上对齐到2的幂指数 121 | private static final int roundup2n(int x) { 122 | if ((x & (x - 1)) == 0) { 123 | return x; 124 | } 125 | int pos = 0; 126 | while (x > 0) { 127 | x >>= 1; 128 | ++pos; 129 | } 130 | return 1 << pos; 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/util/RegexUtils.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.util; 2 | 3 | import java.util.regex.Pattern; 4 | 5 | import static com.example.user.utils.util.ConstUtils.REGEX_CHZ; 6 | import static com.example.user.utils.util.ConstUtils.REGEX_DATE; 7 | import static com.example.user.utils.util.ConstUtils.REGEX_EMAIL; 8 | import static com.example.user.utils.util.ConstUtils.REGEX_IDCARD15; 9 | import static com.example.user.utils.util.ConstUtils.REGEX_IDCARD18; 10 | import static com.example.user.utils.util.ConstUtils.REGEX_IP; 11 | import static com.example.user.utils.util.ConstUtils.REGEX_MOBILE_EXACT; 12 | import static com.example.user.utils.util.ConstUtils.REGEX_MOBILE_SIMPLE; 13 | import static com.example.user.utils.util.ConstUtils.REGEX_TEL; 14 | import static com.example.user.utils.util.ConstUtils.REGEX_URL; 15 | import static com.example.user.utils.util.ConstUtils.REGEX_USERNAME; 16 | 17 | /** 18 | *
 19 |  *     author: Blankj
 20 |  *     blog  : http://blankj.com
 21 |  *     time  : 2016/8/2
 22 |  *     desc  : 正则相关工具类
 23 |  * 
24 | */ 25 | public class RegexUtils { 26 | 27 | private RegexUtils() { 28 | throw new UnsupportedOperationException("u can't instantiate me..."); 29 | } 30 | 31 | /** 32 | * If u want more please visit http://toutiao.com/i6231678548520731137/ 33 | */ 34 | 35 | /** 36 | * 验证手机号(简单) 37 | * 38 | * @param string 待验证文本 39 | * @return {@code true}: 匹配
{@code false}: 不匹配 40 | */ 41 | public static boolean isMobileSimple(String string) { 42 | return isMatch(REGEX_MOBILE_SIMPLE, string); 43 | } 44 | 45 | /** 46 | * 验证手机号(精确) 47 | * 48 | * @param string 待验证文本 49 | * @return {@code true}: 匹配
{@code false}: 不匹配 50 | */ 51 | public static boolean isMobileExact(String string) { 52 | return isMatch(REGEX_MOBILE_EXACT, string); 53 | } 54 | 55 | /** 56 | * 验证电话号码 57 | * 58 | * @param string 待验证文本 59 | * @return {@code true}: 匹配
{@code false}: 不匹配 60 | */ 61 | public static boolean isTel(String string) { 62 | return isMatch(REGEX_TEL, string); 63 | } 64 | 65 | /** 66 | * 验证身份证号码15位 67 | * 68 | * @param string 待验证文本 69 | * @return {@code true}: 匹配
{@code false}: 不匹配 70 | */ 71 | public static boolean isIDCard15(String string) { 72 | return isMatch(REGEX_IDCARD15, string); 73 | } 74 | 75 | /** 76 | * 验证身份证号码18位 77 | * 78 | * @param string 待验证文本 79 | * @return {@code true}: 匹配
{@code false}: 不匹配 80 | */ 81 | public static boolean isIDCard18(String string) { 82 | return isMatch(REGEX_IDCARD18, string); 83 | } 84 | 85 | /** 86 | * 验证邮箱 87 | * 88 | * @param string 待验证文本 89 | * @return {@code true}: 匹配
{@code false}: 不匹配 90 | */ 91 | public static boolean isEmail(String string) { 92 | return isMatch(REGEX_EMAIL, string); 93 | } 94 | 95 | /** 96 | * 验证URL 97 | * 98 | * @param string 待验证文本 99 | * @return {@code true}: 匹配
{@code false}: 不匹配 100 | */ 101 | public static boolean isURL(String string) { 102 | return isMatch(REGEX_URL, string); 103 | } 104 | 105 | /** 106 | * 验证汉字 107 | * 108 | * @param string 待验证文本 109 | * @return {@code true}: 匹配
{@code false}: 不匹配 110 | */ 111 | public static boolean isChz(String string) { 112 | return isMatch(REGEX_CHZ, string); 113 | } 114 | 115 | /** 116 | * 验证用户名 117 | *

取值范围为a-z,A-Z,0-9,"_",汉字,不能以"_"结尾,用户名必须是6-20位

118 | * 119 | * @param string 待验证文本 120 | * @return {@code true}: 匹配
{@code false}: 不匹配 121 | */ 122 | public static boolean isUsername(String string) { 123 | return isMatch(REGEX_USERNAME, string); 124 | } 125 | 126 | /** 127 | * 验证yyyy-MM-dd格式的日期校验,已考虑平闰年 128 | * 129 | * @param string 待验证文本 130 | * @return {@code true}: 匹配
{@code false}: 不匹配 131 | */ 132 | public static boolean isDate(String string) { 133 | return isMatch(REGEX_DATE, string); 134 | } 135 | 136 | /** 137 | * 验证IP地址 138 | * 139 | * @param string 待验证文本 140 | * @return {@code true}: 匹配
{@code false}: 不匹配 141 | */ 142 | public static boolean isIP(String string) { 143 | return isMatch(REGEX_IP, string); 144 | } 145 | 146 | /** 147 | * string是否匹配regex 148 | * 149 | * @param regex 正则表达式字符串 150 | * @param string 要匹配的字符串 151 | * @return {@code true}: 匹配
{@code false}: 不匹配 152 | */ 153 | public static boolean isMatch(String regex, String string) { 154 | return !StringUtils.isEmpty(string) && Pattern.matches(regex, string); 155 | } 156 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/request/xutils/HttpUtilsOfxUtils.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.request.xutils; 2 | 3 | import com.google.gson.Gson; 4 | 5 | import org.xutils.common.Callback; 6 | import org.xutils.common.util.LogUtil; 7 | import org.xutils.http.RequestParams; 8 | import org.xutils.http.app.ResponseParser; 9 | import org.xutils.http.request.UriRequest; 10 | import org.xutils.x; 11 | 12 | import java.lang.reflect.Type; 13 | import java.util.Map; 14 | 15 | /** 16 | * 项目名称:QianShanDoctor 17 | * 类描述:HttpUtilsOfxUtils 18 | * 创建人:slj 19 | * 创建时间:2016-5-23 17:23 20 | * 修改人:slj 21 | * 修改时间:2016-5-23 17:23 22 | * 修改备注: 23 | * 邮箱:slj@bjlingzhuo.com 24 | */ 25 | public class HttpUtilsOfxUtils { 26 | /** 27 | * 发送get请求 28 | * 29 | * @param 30 | */ 31 | public static Callback.Cancelable Get(String url, Map map, Callback.CommonCallback callback) { 32 | RequestParams params = new RequestParams(url); 33 | if (null != map) { 34 | for (Map.Entry entry : map.entrySet()) { 35 | params.addQueryStringParameter(entry.getKey(), entry.getValue()); 36 | 37 | } 38 | } 39 | Callback.Cancelable cancelable = x.http().get(params, callback); 40 | return cancelable; 41 | } 42 | 43 | /** 44 | * 发送post请求 map参数 45 | * 46 | * @param 47 | */ 48 | public static Callback.Cancelable Post(String url, Map map, Callback.CommonCallback callback) { 49 | RequestParams params = new RequestParams(url); 50 | if (null != map) { 51 | for (Map.Entry entry : map.entrySet()) { 52 | params.addParameter(entry.getKey(), entry.getValue()); 53 | } 54 | } 55 | Callback.Cancelable cancelable = x.http().post(params, callback); 56 | return cancelable; 57 | } 58 | 59 | /** 60 | * 发送post请求 61 | * 62 | * @param json参数 63 | */ 64 | public static Callback.Cancelable Post(String url, String json, Callback.CommonCallback callback) { 65 | RequestParams params = new RequestParams(url); 66 | if (null != json) { 67 | params.addParameter("json", json); 68 | } 69 | Callback.Cancelable cancelable = x.http().post(params, callback); 70 | LogUtil.e("params:" + params + cancelable.toString()); 71 | ; 72 | return cancelable; 73 | } 74 | 75 | 76 | /** 77 | * 上传文件 78 | * 79 | * @param 80 | */ 81 | public static Callback.Cancelable UpLoadFile(String url, Map map, Callback.CommonCallback callback) { 82 | RequestParams params = new RequestParams(url); 83 | if (null != map) { 84 | for (Map.Entry entry : map.entrySet()) { 85 | params.addParameter(entry.getKey(), entry.getValue()); 86 | } 87 | } 88 | params.setMultipart(true); 89 | Callback.Cancelable cancelable = x.http().get(params, callback); 90 | return cancelable; 91 | } 92 | 93 | /** 94 | * 下载文件 95 | * 96 | * @param 97 | */ 98 | public static Callback.Cancelable DownLoadFile(String url, String filepath, Callback.CommonCallback callback) { 99 | RequestParams params = new RequestParams(url); 100 | //设置断点续传 101 | params.setAutoResume(true); 102 | params.setSaveFilePath(filepath); 103 | Callback.Cancelable cancelable = x.http().get(params, callback); 104 | return cancelable; 105 | } 106 | } 107 | 108 | class JsonResponseParser implements ResponseParser { 109 | //检查服务器返回的响应头信息 110 | @Override 111 | public void checkResponse(UriRequest request) throws Throwable { 112 | } 113 | 114 | /** 115 | * 转换result为resultType类型的对象 116 | * 117 | * @param resultType 返回值类型(可能带有泛型信息) 118 | * @param resultClass 返回值类型 119 | * @param result 字符串数据 120 | * @return 121 | * @throws Throwable 122 | */ 123 | @Override 124 | public Object parse(Type resultType, Class resultClass, String result) throws Throwable { 125 | return new Gson().fromJson(result, resultClass); 126 | } 127 | } 128 | 129 | 130 | class MyCallBack implements Callback.CommonCallback { 131 | 132 | @Override 133 | public void onSuccess(ResultType result) { 134 | //可以根据公司的需求进行统一的请求成功的逻辑处理 135 | } 136 | 137 | @Override 138 | public void onError(Throwable ex, boolean isOnCallback) { 139 | //可以根据公司的需求进行统一的请求网络失败的逻辑处理 140 | } 141 | 142 | @Override 143 | public void onCancelled(CancelledException cex) { 144 | 145 | } 146 | 147 | @Override 148 | public void onFinished() { 149 | 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/media/GildeTools/GlideUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | _ooOoo_ 3 | o8888888o 4 | 88" . "88 5 | (| -_- |) 6 | O\ = /O 7 | ____/`---'\____ 8 | .' \\| |// `. 9 | / \\||| : |||// \ 10 | / _||||| -:- |||||- \ 11 | | | \\\ - /// | | 12 | | \_| ''\---/'' | | 13 | \ .-\__ `-` ___/-. / 14 | ___`. .' /--.--\ `. . __ 15 | ."" '< `.___\_<|>_/___.' >'"". 16 | | | : `- \`.;`\ _ /`;.`/ - ` : | | 17 | \ \ `-. \_ __\ /__ _/ .-` / / 18 | ======`-.____`-.___\_____/___.-`____.-'====== 19 | `=---=' 20 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 21 | 佛祖保佑 永无BUG 22 | */ 23 | // 佛曰: 24 | // 写字楼里写字间,写字间里程序员; 25 | // 程序人员写程序,又拿程序换酒钱。 26 | // 酒醒只在网上坐,酒醉还来网下眠; 27 | // 酒醉酒醒日复日,网上网下年复年。 28 | // 但愿老死电脑间,不愿鞠躬老板前; 29 | // 奔驰宝马贵者趣,公交自行程序员。 30 | // 别人笑我忒疯癫,我笑自己命太贱; 31 | 32 | package com.example.user.utils.media.GildeTools; 33 | 34 | import android.content.Context; 35 | import android.widget.ImageView; 36 | 37 | import com.bumptech.glide.Glide; 38 | 39 | /** 40 | * 项目名称:QianShan 41 | * 类描述:GlideUtils 通过Glide下载图片 42 | * 创建人:slj 43 | * 创建时间:2016-7-22 15:10 44 | * 修改人:slj 45 | * 修改时间:2016-7-22 15:10 46 | * 修改备注: 47 | * 邮箱:slj@bjlingzhuo.com 48 | */ 49 | public class GlideUtils { 50 | /** 51 | * Glide 获取图片 有默认图片及错误图片 52 | * @param context 上下文对象 53 | * @param url 图片地址 54 | * @param view 图片要显示的ImageView 55 | */ 56 | public static void downLoadImage(Context context, String url, ImageView view,int plcaeId,int errorId){ 57 | Glide.with(context) 58 | .load(url) 59 | .placeholder(plcaeId) 60 | .error(errorId) 61 | .into(view); 62 | } 63 | 64 | /** 65 | * Glide 下载图片 带默认图片 66 | * @param context 67 | * @param url 下载地址 68 | * @param view 显示的ImageView 69 | */ 70 | public static void downLoadImageNomal(Context context, String url, ImageView view,int plcaeId){ 71 | Glide.with(context) 72 | .load(url) 73 | .placeholder(plcaeId) 74 | .into(view); 75 | } 76 | /** 77 | * Glide 下载图片 带下载错误图片 78 | * @param context 79 | * @param url 下载地址 80 | * @param view 显示的ImageView 81 | */ 82 | public static void downLoadImageError(Context context, String url, ImageView view,int errorId){ 83 | Glide.with(context) 84 | .load(url) 85 | .error(errorId) 86 | .into(view); 87 | } 88 | 89 | /** 90 | * Gilde 下载图片转换成圆形图片的方法 91 | * @param context 92 | * @param url 下砸地址 93 | * @param view 显示的ImageView 94 | */ 95 | public static void downLoadCircleImage(Context context, String url, ImageView view,int plcaeId,int errorId){ 96 | Glide.with(context) 97 | .load(url) 98 | .placeholder(plcaeId) 99 | .error(errorId) 100 | .transform(new GlideCircleTransform(context)) 101 | .into(view); 102 | } 103 | /** 104 | * Gilde 下载图片转换成圆形图片的方法 105 | * @param context 106 | * @param srcId 图片ID 107 | * @param view 显示的ImageView 108 | */ 109 | public static void downLoadCircleImage(Context context, int srcId, ImageView view,int plcaeId,int errorId){ 110 | Glide.with(context) 111 | .load(srcId) 112 | .placeholder(plcaeId) 113 | .error(errorId) 114 | .transform(new GlideCircleTransform(context)) 115 | .into(view); 116 | } 117 | /** 118 | * Glide 下载图片并转换成默认圆角角度大小图片的方法 默认为4dp 119 | * @param context 120 | * @param url 下载地址 121 | * @param view 显示的ImageView 122 | */ 123 | public static void downLoadRoundTransform(Context context, String url, ImageView view,int plcaeId,int errorId){ 124 | Glide.with(context) 125 | .load(url) 126 | .placeholder(plcaeId) 127 | .error(errorId) 128 | .transform(new GlideRoundTransform(context)) 129 | .into(view); 130 | } 131 | /** 132 | * Glide 下载图片并转换成自定义圆角角度大小图片的方法 133 | * @param context 134 | * @param url 下载地址 135 | * @param view 显示的ImageView 136 | * @param dp 自定义圆角的角度大小 137 | */ 138 | public static void downLoadRoundTransform(Context context, String url, int dp,ImageView view,int plcaeId,int errorId){ 139 | Glide.with(context) 140 | .load(url) 141 | .placeholder(plcaeId) 142 | .error(errorId) 143 | .transform(new GlideRoundTransform(context,dp)) 144 | .into(view); 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/string/HexDump.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.string; 2 | 3 | import java.io.IOException; 4 | import java.io.StringReader; 5 | 6 | public class HexDump { 7 | class HexTablifier { 8 | private int m_row = 8; 9 | 10 | private String m_pre = ""; 11 | 12 | private String m_post = "\n"; 13 | 14 | public HexTablifier() { 15 | } 16 | 17 | public HexTablifier(int row) { 18 | this(row, "", "\n"); 19 | } 20 | 21 | public HexTablifier(int row, String pre) { 22 | this(row, pre, "\n"); 23 | } 24 | 25 | public HexTablifier(int row, String pre, String post) { 26 | m_row = row; 27 | m_pre = pre; 28 | m_post = post; 29 | } 30 | 31 | public String format(String hex) { 32 | StringReader reader = new StringReader(hex); 33 | StringBuilder builder = new StringBuilder(hex.length() * 2); 34 | 35 | try { 36 | while (getHexLine(builder, reader)) { 37 | } 38 | } catch (IOException e) { 39 | // 不应该有异常出现。 40 | } 41 | 42 | return builder.toString(); 43 | } 44 | 45 | private boolean getHexLine(StringBuilder builder, StringReader reader) 46 | throws IOException { 47 | StringBuilder lineBuilder = new StringBuilder(); 48 | boolean result = true; 49 | 50 | for (int i = 0; i < m_row; i++) { 51 | result = getHexByte(lineBuilder, reader); 52 | 53 | if (result == false) 54 | break; 55 | } 56 | 57 | if (lineBuilder.length() > 0) { 58 | builder.append(m_pre); 59 | builder.append(lineBuilder); 60 | builder.append(m_post); 61 | } 62 | 63 | return result; 64 | } 65 | 66 | private boolean getHexByte(StringBuilder builder, StringReader reader) 67 | throws IOException { 68 | char[] hexByte = new char[4]; 69 | int bytesRead = reader.read(hexByte); 70 | 71 | if (bytesRead == -1) 72 | return false; 73 | 74 | builder.append(hexByte, 0, bytesRead); 75 | builder.append(" "); 76 | 77 | return bytesRead == 4; 78 | } 79 | } 80 | 81 | private static final char m_hexCodes[] = { '0', '1', '2', '3', '4', '5', 82 | '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; 83 | 84 | private static final int m_shifts[] = { 60, 56, 52, 48, 44, 40, 36, 32, 28, 85 | 24, 20, 16, 12, 8, 4, 0 }; 86 | 87 | public static String tablify(byte[] bytes) { 88 | return (new HexDump()).new HexTablifier().format(HexDump.toHex(bytes)); 89 | } 90 | 91 | public static String tablify(byte[] bytes, int row) { 92 | return (new HexDump()).new HexTablifier(row).format(HexDump 93 | .toHex(bytes)); 94 | } 95 | 96 | public static String tablify(byte[] bytes, int row, String pre) { 97 | return (new HexDump()).new HexTablifier(row, pre).format(HexDump 98 | .toHex(bytes)); 99 | } 100 | 101 | public static String tablify(String hex, int row, String pre, String post) { 102 | return (new HexDump()).new HexTablifier(row, pre, post).format(hex); 103 | } 104 | 105 | private static String toHex(final long value, final int digitNum) { 106 | StringBuilder result = new StringBuilder(digitNum); 107 | 108 | for (int j = 0; j < digitNum; j++) { 109 | int index = (int) ((value >> m_shifts[j + (16 - digitNum)]) & 15); 110 | result.append(m_hexCodes[index]); 111 | } 112 | 113 | return result.toString(); 114 | } 115 | 116 | public static String toHex(final byte value) { 117 | return toHex(value, 2); 118 | } 119 | 120 | public static String toHex(final short value) { 121 | return toHex(value, 4); 122 | } 123 | 124 | public static String toHex(final int value) { 125 | return toHex(value, 8); 126 | } 127 | 128 | public static String toHex(final long value) { 129 | return toHex(value, 16); 130 | } 131 | 132 | public static String toHex(final byte[] value) { 133 | return toHex(value, 0, value.length); 134 | } 135 | 136 | public static String toHex(final byte[] value, final int offset, 137 | final int length) { 138 | StringBuilder retVal = new StringBuilder(); 139 | 140 | int end = offset + length; 141 | for (int x = offset; x < end; x++) 142 | retVal.append(toHex(value[x])); 143 | 144 | return retVal.toString(); 145 | } 146 | 147 | public static byte[] restoreBytes(String hex) { 148 | byte[] bytes = new byte[hex.length() / 2]; 149 | for (int i = 0; i < bytes.length; ++i) { 150 | int c1 = charToNumber(hex.charAt(2 * i)); 151 | int c2 = charToNumber(hex.charAt(2 * i + 1)); 152 | if (c1 == -1 || c2 == -1) { 153 | return null; 154 | } 155 | bytes[i] = (byte) ((c1 << 4) + c2); 156 | } 157 | 158 | return bytes; 159 | } 160 | 161 | private static int charToNumber(char c) { 162 | if (c >= '0' && c <= '9') { 163 | return c - '0'; 164 | } else if (c >= 'a' && c <= 'f') { 165 | return c - 'a' + 0xa; 166 | } else if (c >= 'A' && c <= 'F') { 167 | return c - 'A' + 0xA; 168 | } else { 169 | return -1; 170 | } 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/weight/swipyrefresh/CircleImageView.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.weight.swipyrefresh; 2 | 3 | import android.content.Context; 4 | import android.content.res.Resources; 5 | import android.graphics.Canvas; 6 | import android.graphics.Color; 7 | import android.graphics.Paint; 8 | import android.graphics.RadialGradient; 9 | import android.graphics.Shader; 10 | import android.graphics.drawable.ShapeDrawable; 11 | import android.graphics.drawable.shapes.OvalShape; 12 | import android.support.v4.view.ViewCompat; 13 | import android.view.animation.Animation; 14 | import android.widget.ImageView; 15 | 16 | /** 17 | * Private class created to work around issues with AnimationListeners being 18 | * called before the animation is actually complete and support shadows on older 19 | * platforms. 20 | * 21 | * @hide 22 | */ 23 | public class CircleImageView extends ImageView { 24 | 25 | private static final int KEY_SHADOW_COLOR = 0x1E000000; 26 | private static final int FILL_SHADOW_COLOR = 0x3D000000; 27 | // PX 28 | private static final float X_OFFSET = 0f; 29 | private static final float Y_OFFSET = 1.75f; 30 | private static final float SHADOW_RADIUS = 3.5f; 31 | private static final int SHADOW_ELEVATION = 4; 32 | 33 | private Animation.AnimationListener mListener; 34 | private int mShadowRadius; 35 | 36 | public CircleImageView(Context context, int color, final float radius) { 37 | super(context); 38 | final float density = getContext().getResources().getDisplayMetrics().density; 39 | final int diameter = (int) (radius * density * 2); 40 | final int shadowYOffset = (int) (density * Y_OFFSET); 41 | final int shadowXOffset = (int) (density * X_OFFSET); 42 | 43 | mShadowRadius = (int) (density * SHADOW_RADIUS); 44 | 45 | ShapeDrawable circle; 46 | if (elevationSupported()) { 47 | circle = new ShapeDrawable(new OvalShape()); 48 | ViewCompat.setElevation(this, SHADOW_ELEVATION * density); 49 | } else { 50 | OvalShape oval = new OvalShadow(mShadowRadius, diameter); 51 | circle = new ShapeDrawable(oval); 52 | ViewCompat.setLayerType(this, ViewCompat.LAYER_TYPE_SOFTWARE, 53 | circle.getPaint()); 54 | circle.getPaint().setShadowLayer(mShadowRadius, shadowXOffset, 55 | shadowYOffset, KEY_SHADOW_COLOR); 56 | final int padding = (int) mShadowRadius; 57 | // set padding so the inner image sits correctly within the shadow. 58 | setPadding(padding, padding, padding, padding); 59 | } 60 | circle.getPaint().setColor(color); 61 | setBackgroundDrawable(circle); 62 | } 63 | 64 | private boolean elevationSupported() { 65 | return android.os.Build.VERSION.SDK_INT >= 21; 66 | } 67 | 68 | @Override 69 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 70 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 71 | if (!elevationSupported()) { 72 | setMeasuredDimension(getMeasuredWidth() + mShadowRadius * 2, 73 | getMeasuredHeight() + mShadowRadius * 2); 74 | } 75 | } 76 | 77 | public void setAnimationListener(Animation.AnimationListener listener) { 78 | mListener = listener; 79 | } 80 | 81 | @Override 82 | public void onAnimationStart() { 83 | super.onAnimationStart(); 84 | if (mListener != null) { 85 | mListener.onAnimationStart(getAnimation()); 86 | } 87 | } 88 | 89 | @Override 90 | public void onAnimationEnd() { 91 | super.onAnimationEnd(); 92 | if (mListener != null) { 93 | mListener.onAnimationEnd(getAnimation()); 94 | } 95 | } 96 | 97 | /** 98 | * Update the background color of the circle image view. 99 | */ 100 | @SuppressWarnings("ResourceType") 101 | public void setBackgroundColor(int colorRes) { 102 | if (getBackground() instanceof ShapeDrawable) { 103 | final Resources res = getResources(); 104 | ((ShapeDrawable) getBackground()).getPaint().setColor( 105 | res.getColor(colorRes)); 106 | } 107 | } 108 | 109 | private class OvalShadow extends OvalShape { 110 | private RadialGradient mRadialGradient; 111 | private int mShadowRadius; 112 | private Paint mShadowPaint; 113 | private int mCircleDiameter; 114 | 115 | public OvalShadow(int shadowRadius, int circleDiameter) { 116 | super(); 117 | mShadowPaint = new Paint(); 118 | mShadowRadius = shadowRadius; 119 | mCircleDiameter = circleDiameter; 120 | mRadialGradient = new RadialGradient(mCircleDiameter / 2, 121 | mCircleDiameter / 2, mShadowRadius, new int[] { 122 | FILL_SHADOW_COLOR, Color.TRANSPARENT }, null, 123 | Shader.TileMode.CLAMP); 124 | mShadowPaint.setShader(mRadialGradient); 125 | } 126 | 127 | @Override 128 | public void draw(Canvas canvas, Paint paint) { 129 | final int viewWidth = CircleImageView.this.getWidth(); 130 | final int viewHeight = CircleImageView.this.getHeight(); 131 | canvas.drawCircle(viewWidth / 2, viewHeight / 2, 132 | (mCircleDiameter / 2 + mShadowRadius), mShadowPaint); 133 | canvas.drawCircle(viewWidth / 2, viewHeight / 2, 134 | (mCircleDiameter / 2), paint); 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/util/BarUtils.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.util; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.os.Build; 6 | import android.util.TypedValue; 7 | import android.view.Window; 8 | import android.view.WindowManager; 9 | 10 | import java.lang.reflect.Method; 11 | 12 | /** 13 | *
 14 |  *     author: Blankj
 15 |  *     blog  : http://blankj.com
 16 |  *     time  : 2016/9/23
 17 |  *     desc  : 栏相关工具类
 18 |  * 
19 | */ 20 | public class BarUtils { 21 | private BarUtils() { 22 | throw new UnsupportedOperationException("u can't instantiate me..."); 23 | } 24 | 25 | /** 26 | * 设置透明状态栏(api大于19方可使用) 27 | *

可在Activity的onCreat()中调用

28 | *

需在顶部控件布局中加入以下属性让内容出现在状态栏之下

29 | *

android:clipToPadding="true"

30 | *

android:fitsSystemWindows="true"

31 | * 32 | * @param activity activity 33 | */ 34 | public static void setTransparentStatusBar(Activity activity) { 35 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 36 | //透明状态栏 37 | activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 38 | //透明导航栏 39 | activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); 40 | } 41 | } 42 | 43 | /** 44 | * 隐藏状态栏 45 | *

也就是设置全屏,一定要在setContentView之前调用,否则报错

46 | *

此方法Activity可以继承AppCompatActivity

47 | *

启动的时候状态栏会显示一下再隐藏,比如QQ的欢迎界面

48 | *

在配置文件中Activity加属性android:theme="@android:style/Theme.NoTitleBar.Fullscreen"

49 | *

如加了以上配置Activity不能继承AppCompatActivity,会报错

50 | * 51 | * @param activity activity 52 | */ 53 | public static void hideStatusBar(Activity activity) { 54 | activity.requestWindowFeature(Window.FEATURE_NO_TITLE); 55 | activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 56 | WindowManager.LayoutParams.FLAG_FULLSCREEN); 57 | } 58 | 59 | /** 60 | * 获取状态栏高度 61 | * 62 | * @param context 上下文 63 | * @return 状态栏高度 64 | */ 65 | public static int getStatusBarHeight(Context context) { 66 | int result = 0; 67 | int resourceId = context.getResources() 68 | .getIdentifier("status_bar_height", "dimen", "android"); 69 | if (resourceId > 0) { 70 | result = context.getResources().getDimensionPixelSize(resourceId); 71 | } 72 | return result; 73 | } 74 | 75 | /** 76 | * 判断状态栏是否存在 77 | * 78 | * @param activity activity 79 | * @return {@code true}: 存在
{@code false}: 不存在 80 | */ 81 | public static boolean isStatusBarExists(Activity activity) { 82 | WindowManager.LayoutParams params = activity.getWindow().getAttributes(); 83 | return (params.flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) != WindowManager.LayoutParams.FLAG_FULLSCREEN; 84 | } 85 | 86 | /** 87 | * 获取ActionBar高度 88 | * 89 | * @param activity activity 90 | * @return ActionBar高度 91 | */ 92 | public static int getActionBarHeight(Activity activity) { 93 | TypedValue tv = new TypedValue(); 94 | if (activity.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) { 95 | return TypedValue.complexToDimensionPixelSize(tv.data, activity.getResources().getDisplayMetrics()); 96 | } 97 | return 0; 98 | } 99 | 100 | /** 101 | * 显示通知栏 102 | *

需添加权限 {@code }

103 | * 104 | * @param context 上下文 105 | * @param isSettingPanel {@code true}: 打开设置
{@code false}: 打开通知 106 | */ 107 | public static void showNotificationBar(Context context, boolean isSettingPanel) { 108 | String methodName = (Build.VERSION.SDK_INT <= 16) ? "expand" 109 | : (isSettingPanel ? "expandSettingsPanel" : "expandNotificationsPanel"); 110 | invokePanels(context, methodName); 111 | } 112 | 113 | /** 114 | * 隐藏通知栏 115 | *

需添加权限 {@code }

116 | * 117 | * @param context 上下文 118 | */ 119 | public static void hideNotificationBar(Context context) { 120 | String methodName = (Build.VERSION.SDK_INT <= 16) ? "collapse" : "collapsePanels"; 121 | invokePanels(context, methodName); 122 | } 123 | 124 | /** 125 | * 反射唤醒通知栏 126 | * 127 | * @param context 上下文 128 | * @param methodName 方法名 129 | */ 130 | private static void invokePanels(Context context, String methodName) { 131 | try { 132 | Object service = context.getSystemService("statusbar"); 133 | Class statusBarManager = Class.forName("android.app.StatusBarManager"); 134 | Method expand = statusBarManager.getMethod(methodName); 135 | expand.invoke(service); 136 | } catch (Exception e) { 137 | e.printStackTrace(); 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/permission/util/MPermissionUtil.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.permission.util; 2 | 3 | import android.annotation.TargetApi; 4 | import android.app.Activity; 5 | import android.content.pm.PackageManager; 6 | import android.os.Build; 7 | import android.support.v4.app.Fragment; 8 | 9 | import com.example.user.utils.permission.annotation.OnMPermissionDenied; 10 | import com.example.user.utils.permission.annotation.OnMPermissionGranted; 11 | import com.example.user.utils.permission.annotation.OnMPermissionNeverAskAgain; 12 | 13 | import java.lang.annotation.Annotation; 14 | import java.lang.reflect.Method; 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | 18 | final public class MPermissionUtil { 19 | 20 | public static boolean isOverMarshmallow() { 21 | return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M; 22 | } 23 | 24 | public static Activity getActivity(Object object) { 25 | if (object instanceof Fragment) { 26 | return ((Fragment) object).getActivity(); 27 | } else if (object instanceof Activity) { 28 | return (Activity) object; 29 | } 30 | return null; 31 | } 32 | 33 | @TargetApi(value = Build.VERSION_CODES.M) 34 | public static List findDeniedPermissions(Activity activity, String... permission) { 35 | List denyPermissions = new ArrayList<>(); 36 | for (String value : permission) { 37 | if (activity.checkSelfPermission(value) != PackageManager.PERMISSION_GRANTED) { 38 | denyPermissions.add(value); 39 | } 40 | } 41 | return denyPermissions; 42 | } 43 | 44 | @TargetApi(value = Build.VERSION_CODES.M) 45 | public static List findNeverAskAgainPermissions(Activity activity, String... permission) { 46 | List neverAskAgainPermission = new ArrayList<>(); 47 | for (String value : permission) { 48 | if (activity.checkSelfPermission(value) != PackageManager.PERMISSION_GRANTED && 49 | !activity.shouldShowRequestPermissionRationale(value)) { 50 | neverAskAgainPermission.add(value); 51 | } 52 | } 53 | 54 | return neverAskAgainPermission; 55 | } 56 | 57 | @TargetApi(value = Build.VERSION_CODES.M) 58 | public static List findDeniedPermissionWithoutNeverAskAgain(Activity activity, String... permission) { 59 | List denyPermissions = new ArrayList<>(); 60 | for (String value : permission) { 61 | if (activity.checkSelfPermission(value) != PackageManager.PERMISSION_GRANTED && 62 | activity.shouldShowRequestPermissionRationale(value)) { 63 | denyPermissions.add(value); 64 | } 65 | } 66 | 67 | return denyPermissions; 68 | } 69 | 70 | @TargetApi(value = Build.VERSION_CODES.M) 71 | public static boolean hasNeverAskAgainPermission(Activity activity, List permission) { 72 | for (String value : permission) { 73 | if (activity.checkSelfPermission(value) != PackageManager.PERMISSION_GRANTED && 74 | !activity.shouldShowRequestPermissionRationale(value)) { 75 | return true; 76 | } 77 | } 78 | 79 | return false; 80 | } 81 | 82 | public static Method findMethodWithRequestCode(Class clazz, Class annotation, int requestCode) { 83 | for (Method method : clazz.getDeclaredMethods()) { 84 | if (method.getAnnotation(annotation) != null && 85 | isEqualRequestCodeFromAnnotation(method, annotation, requestCode)) { 86 | return method; 87 | } 88 | } 89 | return null; 90 | } 91 | 92 | public static boolean isEqualRequestCodeFromAnnotation(Method m, Class clazz, int requestCode) { 93 | if (clazz.equals(OnMPermissionDenied.class)) { 94 | return requestCode == m.getAnnotation(OnMPermissionDenied.class).value(); 95 | } else if (clazz.equals(OnMPermissionGranted.class)) { 96 | return requestCode == m.getAnnotation(OnMPermissionGranted.class).value(); 97 | } else if (clazz.equals(OnMPermissionNeverAskAgain.class)) { 98 | return requestCode == m.getAnnotation(OnMPermissionNeverAskAgain.class).value(); 99 | } else { 100 | return false; 101 | } 102 | } 103 | 104 | public static String toString(List permission) { 105 | if (permission == null || permission.isEmpty()) { 106 | return ""; 107 | } 108 | 109 | return toString(permission.toArray(new String[permission.size()])); 110 | } 111 | 112 | public static String toString(String[] permission) { 113 | if (permission == null || permission.length <= 0) { 114 | return ""; 115 | } 116 | 117 | StringBuilder sb = new StringBuilder(); 118 | for (String p : permission) { 119 | sb.append(p.replaceFirst("android.permission.", "")); 120 | sb.append(","); 121 | } 122 | 123 | sb.deleteCharAt(sb.length() - 1); 124 | 125 | return sb.toString(); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/user/utils/util/SizeUtils.java: -------------------------------------------------------------------------------- 1 | package com.example.user.utils.util; 2 | 3 | import android.content.Context; 4 | import android.util.DisplayMetrics; 5 | import android.util.Log; 6 | import android.util.TypedValue; 7 | import android.view.View; 8 | 9 | /** 10 | *
 11 |  *     author: Blankj
 12 |  *     blog  : http://blankj.com
 13 |  *     time  : 2016/8/2
 14 |  *     desc  : 尺寸相关工具类
 15 |  * 
16 | */ 17 | public class SizeUtils { 18 | 19 | private SizeUtils() { 20 | throw new UnsupportedOperationException("u can't instantiate me..."); 21 | } 22 | 23 | /** 24 | * dp转px 25 | * 26 | * @param context 上下文 27 | * @param dpValue dp值 28 | * @return px值 29 | */ 30 | public static int dp2px(Context context, float dpValue) { 31 | final float scale = context.getResources().getDisplayMetrics().density; 32 | return (int) (dpValue * scale + 0.5f); 33 | } 34 | 35 | /** 36 | * px转dp 37 | * 38 | * @param context 上下文 39 | * @param pxValue px值 40 | * @return dp值 41 | */ 42 | public static int px2dp(Context context, float pxValue) { 43 | final float scale = context.getResources().getDisplayMetrics().density; 44 | return (int) (pxValue / scale + 0.5f); 45 | } 46 | 47 | /** 48 | * sp转px 49 | * 50 | * @param context 上下文 51 | * @param spValue sp值 52 | * @return px值 53 | */ 54 | public static int sp2px(Context context, float spValue) { 55 | final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; 56 | return (int) (spValue * fontScale + 0.5f); 57 | } 58 | 59 | /** 60 | * px转sp 61 | * 62 | * @param context 上下文 63 | * @param pxValue px值 64 | * @return sp值 65 | */ 66 | public static int px2sp(Context context, float pxValue) { 67 | final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; 68 | return (int) (pxValue / fontScale + 0.5f); 69 | } 70 | 71 | /** 72 | * 各种单位转换 73 | *

该方法存在于TypedValue

74 | * 75 | * @param unit 单位 76 | * @param value 值 77 | * @param metrics DisplayMetrics 78 | * @return 转换结果 79 | */ 80 | public static float applyDimension(int unit, float value, DisplayMetrics metrics) { 81 | switch (unit) { 82 | case TypedValue.COMPLEX_UNIT_PX: 83 | return value; 84 | case TypedValue.COMPLEX_UNIT_DIP: 85 | return value * metrics.density; 86 | case TypedValue.COMPLEX_UNIT_SP: 87 | return value * metrics.scaledDensity; 88 | case TypedValue.COMPLEX_UNIT_PT: 89 | return value * metrics.xdpi * (1.0f / 72); 90 | case TypedValue.COMPLEX_UNIT_IN: 91 | return value * metrics.xdpi; 92 | case TypedValue.COMPLEX_UNIT_MM: 93 | return value * metrics.xdpi * (1.0f / 25.4f); 94 | } 95 | return 0; 96 | } 97 | 98 | /** 99 | * 在onCreate()即可强行获取View的尺寸 100 | *

需回调onGetSizeListener接口,在onGetSize中获取view宽高

101 | *

用法示例如下所示

102 | *
{@code
103 |      * SizeUtils.forceGetViewSize(view, new SizeUtils.onGetSizeListener() {
104 |      *     @ Override
105 |      *     public void onGetSize(View view) {
106 |      *         view.getWidth();
107 |      *     }
108 |      * });
109 |      * }
110 |      * 
111 | * 112 | * @param view 视图 113 | */ 114 | public static void forceGetViewSize(final View view, final onGetSizeListener listener) { 115 | view.post(new Runnable() { 116 | @Override 117 | public void run() { 118 | if (listener != null) { 119 | listener.onGetSize(view); 120 | } 121 | } 122 | }); 123 | } 124 | 125 | /** 126 | * 获取到View尺寸的监听 127 | */ 128 | public interface onGetSizeListener { 129 | void onGetSize(View view); 130 | } 131 | 132 | public static void setListener(onGetSizeListener listener) { 133 | mListener = listener; 134 | } 135 | 136 | private static onGetSizeListener mListener; 137 | 138 | /** 139 | * ListView中提前测量View尺寸,如headerView 140 | *

用的时候去掉注释拷贝到ListView中即可

141 | *

参照以下注释代码

142 | * 143 | * @param view 视图 144 | */ 145 | public static void measureViewInLV(View view) { 146 | Log.i("tips", "U should copy the following code."); 147 | /* 148 | ViewGroup.LayoutParams p = view.getLayoutParams(); 149 | if (p == null) { 150 | p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 151 | ViewGroup.LayoutParams.WRAP_CONTENT); 152 | } 153 | int width = ViewGroup.getChildMeasureSpec(0, 0, p.width); 154 | int height; 155 | int tempHeight = p.height; 156 | if (tempHeight > 0) { 157 | height = MeasureSpec.makeMeasureSpec(tempHeight, 158 | MeasureSpec.EXACTLY); 159 | } else { 160 | height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 161 | } 162 | view.measure(width, height); 163 | */ 164 | } 165 | } 166 | --------------------------------------------------------------------------------