Android各种工具类封装

  • Utils大全集合
  • AppUtils 获取项目的Application context 方便每个Utils去init(); 一定要在Application中初始化
  • BitmapUtil ==》图片工具类
  • GlideRoundTransform ==》glide加载任意想加载的圆角
  • CrashHandler ==》异常捕获
  • ThreadManager ==》线程池管理线程
  • ButtonClickUtils ==》防止快速点击
  • DataUtils ==》填充数据工具类
  • GsonUtil
  • KeyBoardUtils ==》打开或关闭软键盘
  • LogUtils
  • MathUtils
  • MoreUtils ==》手机号判断等
  • PictureProgressUtil ==》用于框架,图片上传时显示图片上传进度
  • PinyinUtils
  • PreferenceUtil
  • SpannableStringBuilder
  • ClickableSpanListener
  • TextViewUtils
  • TimeUtils
  • ToastUtils
  • UIUtils ==》用单位换算,获取屏幕宽高,获取屏幕状态栏高度



最近项目整合也是遇到很多工具类混乱 多个模块、组件工具类重复问题,喜欢点赞收藏、欢迎大佬提拔指点!

Utils大全集合

AppUtils 获取项目的Application context 方便每个Utils去init(); 一定要在Application中初始化

public class AppUtils {
    private static Context mContext;

    private AppUtils () {
        throw new UnsupportedOperationException("u can't instantiate me...");
    }

    public static void initContext(Context context){
        mContext = context;
    }

    public static Context getApplication() {
        if (mContext!=null){
            return mContext;
        }else {
            throw new UnsupportedOperationException("context 未初始化");
        }
    }
}

BitmapUtil ==》图片工具类

public class BitmapUtil {
    /**
     * 按图片的质量压缩
     *
     * @param filePath 需要压缩的图片路径
     * @param quality  压缩的质量 0 - 100
     * @return
     */

    public static String compressBitmapByQuality(String filePath, int quality) {
        Bitmap bm = BitmapFactory.decodeFile(filePath);
        int degree = readPictureDegree(filePath);//获取相片拍摄角度
        if (degree != 0) {//旋转照片角度,防止头像横着显示
            bm = rotateBitmap(bm, degree);
        }
        File imageFile = new File(LeoUtils.getApplication().getFilesDir().getAbsolutePath().toString() + "/" + TimeUtils.getStrByLong(System.currentTimeMillis(), "yyyy.MM.dd_HH:mm:ss:SSS") + "_atmancarm.jpg");
        try {
            imageFile.createNewFile();
            FileOutputStream out = new FileOutputStream(imageFile);
            bm.compress(Bitmap.CompressFormat.JPEG, quality, out);
        } catch (Exception e) {

        }

        String imgpath = imageFile.getPath();

        return imgpath;
    }

    /**
     * 按图片长宽压缩
     * 按传入的长宽后,计算出合适的压缩比如,压缩图片,此处指的是图片长宽大小的压缩
     */
    public static Bitmap compressBitmapBySize(String filePath, int requireWidth, int requireHeight) {
        final BitmapFactory.Options options = new BitmapFactory.Options();
        //设置整个属性后,不会加载bitmap,只会获取图片属性,比如宽高
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(filePath, options);
        // 计算缩放比()
        options.inSampleSize = calculateInSampleSize(options, requireWidth, requireHeight);
        // 完整解析图片返回bitmap
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeFile(filePath, options);
    }

    //与原图片比,长宽压缩多少倍数。 multiple  几倍数
    public static Bitmap compressBitmapBySourceSize(String filePath, double multiple) {
        final BitmapFactory.Options options = new BitmapFactory.Options();
        //设置整个属性后,不会加载bitmap,只会获取图片属性,比如宽高
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(filePath, options);

        int sourceHeight = options.outHeight;
        int sourceWidth = options.outWidth;
        int requireWidth = (int) (sourceWidth / multiple);
        int requireHeight = (int) (sourceHeight / multiple);

        // 计算缩放比()
        options.inSampleSize = calculateInSampleSize(options, requireWidth, requireHeight);
        // 完整解析图片返回bitmap
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeFile(filePath, options);
    }


    /**
     * 获取照片角度
     * 一般是拍摄照片的时候才会用到
     *
     * @param path
     * @return
     */

    public static int readPictureDegree(String path) {
        int degree = 0;
        try {
            ExifInterface exifInterface = new ExifInterface(path);
            int orientation = exifInterface.getAttributeInt(
                    ExifInterface.TAG_ORIENTATION,
                    ExifInterface.ORIENTATION_NORMAL);
            switch (orientation) {
                case ExifInterface.ORIENTATION_ROTATE_90:
                    degree = 90;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    degree = 180;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    degree = 270;
                    break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return degree;
    }

    /**
     * 旋转照片
     * 一般是拍摄照片的时候才会用到
     *
     * @param bitmap
     * @param degress
     * @return
     */
    public static Bitmap rotateBitmap(Bitmap bitmap, int degress) {
        if (bitmap != null) {
            Matrix m = new Matrix();
            m.postRotate(degress);
            bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
                    bitmap.getHeight(), m, true);
            return bitmap;
        }
        return bitmap;
    }


    // 计算缩放比()
    public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;
        if (height > reqHeight || width > reqWidth) {
            final int heightRatio = Math.round((float) height / (float) reqHeight);
            final int widthRatio = Math.round((float) width / (float) reqWidth);
            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
        }
        return inSampleSize;
    }


    //压缩图片到 指定大小
    public static Bitmap compressTargetBitmap(Bitmap bitmap) {
        double maxSize = 500.00;//KB
        //将bitmap放至数组中,意在bitmap的大小(与实际读取的原文件要大)
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        byte[] b = baos.toByteArray();
        //将字节换成KB
        double mid = b.length / 1024;
        //判断bitmap占用空间是否大于允许最大空间  如果大于则压缩 小于则不压缩
        if (mid > maxSize) {
            //获取bitmap大小 是允许最大大小的多少倍
            double i = mid / maxSize;
            //开始压缩  此处用到平方根 将宽带和高度压缩掉对应的平方根倍 (1.保持刻度和高度和原bitmap比率一致,压缩后也达到了最大大小占用空间的大小)
            bitmap = zoomBitmap(bitmap, bitmap.getWidth() / Math.sqrt(i),
                    bitmap.getHeight() / Math.sqrt(i));
        }
        return bitmap;
    }


    public static Bitmap zoomBitmap(Bitmap bgimage, double newWidth,
                                    double newHeight) {
        // 获取这个图片的宽和高
        float width = bgimage.getWidth();
        float height = bgimage.getHeight();
        // 创建操作图片用的matrix对象
        Matrix matrix = new Matrix();
        // 计算宽高缩放率
        float scaleWidth = ((float) newWidth) / width;
        float scaleHeight = ((float) newHeight) / height;
        // 缩放图片动作
        matrix.postScale(scaleWidth, scaleHeight);
        Bitmap bitmap = Bitmap.createBitmap(bgimage, 0, 0, (int) width,
                (int) height, matrix, true);
        return bitmap;
    }


}

GlideRoundTransform ==》glide加载任意想加载的圆角

public class GlideRoundTransform implements Transformation<Bitmap> {
    private BitmapPool mBitmapPool;

    private float radius;

    private boolean isLeftTop, isRightTop, isLeftBottom, isRightBotoom;

    /**
     * 需要设置圆角的部分
     *
     * @param leftTop     左上角
     * @param rightTop    右上角
     * @param leftBottom  左下角
     * @param rightBottom 右下角
     */
    public void setNeedCorner(boolean leftTop, boolean rightTop, boolean leftBottom, boolean rightBottom) {
        isLeftTop = leftTop;
        isRightTop = rightTop;
        isLeftBottom = leftBottom;
        isRightBotoom = rightBottom;
    }

    /**
     * @param context 上下文
     * @param radius  圆角幅度
     */
    public GlideRoundTransform(Context context, float radius) {
        this.mBitmapPool = Glide.get(context).getBitmapPool();
        this.radius = radius;
    }

    @NonNull
    @Override
    public Resource<Bitmap> transform(@NonNull Context context, @NonNull Resource<Bitmap> resource, int outWidth, int outHeight) {

        Bitmap source = resource.get();
        int finalWidth, finalHeight;
        //输出目标的宽高或高宽比例
        float scale;
        if (outWidth > outHeight) {
            //如果 输出宽度 > 输出高度 求高宽比

            scale = (float) outHeight / (float) outWidth;
            finalWidth = source.getWidth();
            //固定原图宽度,求最终高度
            finalHeight = (int) ((float) source.getWidth() * scale);
            if (finalHeight > source.getHeight()) {
                //如果 求出的最终高度 > 原图高度 求宽高比

                scale = (float) outWidth / (float) outHeight;
                finalHeight = source.getHeight();
                //固定原图高度,求最终宽度
                finalWidth = (int) ((float) source.getHeight() * scale);
            }
        } else if (outWidth < outHeight) {
            //如果 输出宽度 < 输出高度 求宽高比

            scale = (float) outWidth / (float) outHeight;
            finalHeight = source.getHeight();
            //固定原图高度,求最终宽度
            finalWidth = (int) ((float) source.getHeight() * scale);
            if (finalWidth > source.getWidth()) {
                //如果 求出的最终宽度 > 原图宽度 求高宽比

                scale = (float) outHeight / (float) outWidth;
                finalWidth = source.getWidth();
                finalHeight = (int) ((float) source.getWidth() * scale);
            }
        } else {
            //如果 输出宽度=输出高度
            finalHeight = source.getHeight();
            finalWidth = finalHeight;
        }

        //修正圆角
        this.radius *= (float) finalHeight / (float) outHeight;
        Bitmap outBitmap = this.mBitmapPool.get(finalWidth, finalHeight, Bitmap.Config.ARGB_8888);
        if (outBitmap == null) {
            outBitmap = Bitmap.createBitmap(finalWidth, finalHeight, Bitmap.Config.ARGB_8888);
        }

        Canvas canvas = new Canvas(outBitmap);
        Paint paint = new Paint();
        //关联画笔绘制的原图bitmap
        BitmapShader shader = new BitmapShader(source, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        //计算中心位置,进行偏移
        int width = (source.getWidth() - finalWidth) / 2;
        int height = (source.getHeight() - finalHeight) / 2;
        if (width != 0 || height != 0) {
            Matrix matrix = new Matrix();
            matrix.setTranslate((float) (-width), (float) (-height));
            shader.setLocalMatrix(matrix);
        }

        paint.setShader(shader);
        paint.setAntiAlias(true);
        RectF rectF = new RectF(0.0F, 0.0F, (float) canvas.getWidth(), (float) canvas.getHeight());
        //先绘制圆角矩形
        canvas.drawRoundRect(rectF, this.radius, this.radius, paint);

        //左上角圆角
        if (!isLeftTop) {
            canvas.drawRect(0, 0, radius, radius, paint);
        }
        //右上角圆角
        if (!isRightTop) {
            canvas.drawRect(canvas.getWidth() - radius, 0, canvas.getWidth(), radius, paint);
        }
        //左下角圆角
        if (!isLeftBottom) {
            canvas.drawRect(0, canvas.getHeight() - radius, radius, canvas.getHeight(), paint);
        }
        //右下角圆角
        if (!isRightBotoom) {
            canvas.drawRect(canvas.getWidth() - radius, canvas.getHeight() - radius, canvas.getWidth(), canvas.getHeight(), paint);
        }

        return BitmapResource.obtain(outBitmap, this.mBitmapPool);
    }


    @Override
    public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {

    }
}

CrashHandler ==》异常捕获

要打开存储权限.(加入后,一旦程序崩溃,崩溃日志会自动保存在手机内部存储里)
	CrashHandler crashHandler = CrashHandler.getInstance();
	crashHandler.init(getApplicationContext());
public class CrashHandler implements Thread.UncaughtExceptionHandler {
    public static final String TAG = "CrashHandler";

    //系统默认的UncaughtException处理类
    private Thread.UncaughtExceptionHandler mDefaultHandler;
    //CrashHandler实例
    private static CrashHandler INSTANCE = new CrashHandler();
    //程序的Context对象
    private Context mContext;
    Class<?> mCls;
    //用来存储设备信息和异常信息
    private Map<String, String> infos = new HashMap<String, String>();

    //用于格式化日期,作为日志文件名的一部分
    private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");

    /**
     * 保证只有一个CrashHandler实例
     */
    private CrashHandler() {
    }

    /**
     * 获取CrashHandler实例 ,单例模式
     */
    public static CrashHandler getInstance() {
        return INSTANCE;
    }

    /**
     * 初始化
     *
     * @param context
     */


    public void init(Context context) {
        init(context, null);
    }

    public void init(Context context, Class<?> cls) {
        mCls = cls;
        mContext = context;
        //获取系统默认的UncaughtException处理器
        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
        //设置该CrashHandler为程序的默认处理器
        Thread.setDefaultUncaughtExceptionHandler(this);
    }

    /**
     * 当UncaughtException发生时会转入该函数来处理
     */

    @Override
    public void uncaughtException(Thread thread, Throwable ex) {

        if (!handleException(ex) && mDefaultHandler != null) {
            //如果用户没有处理则让系统默认的异常处理器来处理
            mDefaultHandler.uncaughtException(thread, ex);
        } else {
            if (mCls == null) {
                android.os.Process.killProcess(android.os.Process.myPid());
                System.exit(0);
            } else {
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {

                        Intent intent = new Intent(mContext, mCls);
//                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
                        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
                        mContext.startActivity(intent);

                    }
                }, 1000);
            }
        }
    }


    /**
     * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
     *
     * @param ex
     * @return true:如果处理了该异常信息;否则返回false.
     */
    private boolean handleException(Throwable ex) {
        if (ex == null) {
            return false;
        }
        //使用Toast来显示异常信息
        new Thread() {
            @Override
            public void run() {
                Looper.prepare();
                Toast.makeText(mContext, "很抱歉,程序出现异常,即将重启.", Toast.LENGTH_SHORT).show();
                Looper.loop();
            }
        }.start();
        //收集设备参数信息
        collectDeviceInfo(mContext);
        //保存日志文件
        saveCrashInfo2File(ex);
        return true;
    }

    /**
     * 收集设备参数信息
     *
     * @param ctx
     */
    public void collectDeviceInfo(Context ctx) {
        try {
            PackageManager pm = ctx.getPackageManager();
            PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(), PackageManager.GET_ACTIVITIES);
            if (pi != null) {
                String versionName = pi.versionName == null ? "null" : pi.versionName;
                String versionCode = pi.versionCode + "";
                infos.put("versionName", versionName);
                infos.put("versionCode", versionCode);
            }
        } catch (PackageManager.NameNotFoundException e) {
            Log.e(TAG, "an error occured when collect package info", e);
        }
        Field[] fields = Build.class.getDeclaredFields();
        for (Field field : fields) {
            try {
                field.setAccessible(true);
                infos.put(field.getName(), field.get(null).toString());
                Log.d(TAG, field.getName() + " : " + field.get(null));
            } catch (Exception e) {
                Log.e(TAG, "an error occured when collect crash info", e);
            }
        }
    }

    /**
     * 保存错误信息到文件中
     *
     * @param ex
     * @return 返回文件名称, 便于将文件传送到服务器
     */
    private String saveCrashInfo2File(Throwable ex) {

        StringBuffer sb = new StringBuffer();
        for (Map.Entry<String, String> entry : infos.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            sb.append(key + "=" + value + "\n");
        }

        Writer writer = new StringWriter();
        PrintWriter printWriter = new PrintWriter(writer);
        ex.printStackTrace(printWriter);
        Throwable cause = ex.getCause();
        while (cause != null) {
            cause.printStackTrace(printWriter);
            cause = cause.getCause();
        }
        printWriter.close();
        String result = writer.toString();
        sb.append(result);
        try {
            long timestamp = System.currentTimeMillis();
            String time = formatter.format(new Date());
            String fileName = "crash-" + time + "-" + timestamp + ".log";
            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                String path = "/sdcard/App_Crash/";
                File dir = new File(path);
                if (!dir.exists()) {
                    dir.mkdirs();
                }
                FileOutputStream fos = new FileOutputStream(path + fileName);
                fos.write(sb.toString().getBytes());

                fos.close();
            }
            return fileName;
        } catch (Exception e) {
            Log.e(TAG, "an error occured while writing file...", e);
        }
        return null;
    }
}

ThreadManager ==》线程池管理线程

public class ThreadManager {
    private static ThreadManager threadManager;
    /**
     * 懒汉多线程单例
     *
     * @return
     */
    public static ThreadManager getInstance() {
        if (threadManager == null) {
            synchronized (ThreadManager.class) {
                if (threadManager == null) {
                    threadManager = new ThreadManager();
                }
            }
        }
        return threadManager;
    }

    /**
     * 核心线程池的数量,同时能够执行的线程数量
     */
    private int corePoolSize;
    /**
     * 最大线程池数量,表示当缓冲队列满的时候能继续容纳的等待任务的数量
     */
    private int maximumPoolSize;
    /**
     * 存活时间
     */
    private long keepAliveTime = 1;
    private TimeUnit unit = TimeUnit.HOURS;
    private ThreadPoolExecutor executor;

    private ThreadManager() {
        /**
         * 给corePoolSize赋值:当前设备可用处理器核心数*2 + 1,能够让cpu的效率得到最大程度执行(有研究论证的)
         */
        corePoolSize = Runtime.getRuntime().availableProcessors() * 2 + 1;
        //虽然maximumPoolSize用不到,但是需要赋值,否则报错
        maximumPoolSize = corePoolSize;
        executor = new ThreadPoolExecutor(
                //当某个核心任务执行完毕,会依次从缓冲队列中取出等待任务
                corePoolSize,
                //5,先corePoolSize,然后new LinkedBlockingQueue<Runnable>(),然后maximumPoolSize,但是它的数量是包含了corePoolSize的
                maximumPoolSize,
                //表示的是maximumPoolSize当中等待任务的存活时间
                keepAliveTime,
                unit,
                //缓冲队列,用于存放等待任务,Linked的先进先出
                new LinkedBlockingQueue<Runnable>(),
                //创建线程的工厂
                //  Executors.defaultThreadFactory(),
                new DefaultThreadFactory(Thread.NORM_PRIORITY, "tiaoba-pool-"),
                //用来对超出maximumPoolSize的任务的处理策略
                new ThreadPoolExecutor.AbortPolicy()
        );
    }

    /**
     * 执行任务
     *
     * @param runnable
     */
    public void execute(Runnable runnable) {
        if (executor == null) {
            //线程池执行者。
            //参1:核心线程数;参2:最大线程数;参3:线程休眠时间;参4:时间单位;参5:线程队列;参6:生产线程的工厂;参7:线程异常处理策略
            executor = new ThreadPoolExecutor(
                    corePoolSize,
                    maximumPoolSize,
                    keepAliveTime,
                    TimeUnit.SECONDS,
                    new LinkedBlockingQueue<Runnable>(),
                    //   Executors.defaultThreadFactory(),
                    new DefaultThreadFactory(Thread.NORM_PRIORITY, "tiaoba-pool-"),
                    new ThreadPoolExecutor.AbortPolicy());
        }
        if (runnable != null) {
            executor.execute(runnable);
        }
    }

    /**
     * 移除任务
     */
    public void remove(Runnable runnable) {
        if (runnable != null) {
            executor.remove(runnable);
        }
    }

    /**
     * 创建线程的工厂,设置线程的优先级,group,以及命名
     */
    private static class DefaultThreadFactory implements ThreadFactory {
        /**
         * 线程池的计数
         */
        private static final AtomicInteger poolNumber = new AtomicInteger(1);

        /**
         * 线程的计数
         */
        private final AtomicInteger threadNumber = new AtomicInteger(1);

        private final ThreadGroup group;
        private final String namePrefix;
        private final int threadPriority;

        DefaultThreadFactory(int threadPriority, String threadNamePrefix) {
            this.threadPriority = threadPriority;
            this.group = Thread.currentThread().getThreadGroup();
            namePrefix = threadNamePrefix + poolNumber.getAndIncrement() + "-thread-";
        }

        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
            if (t.isDaemon()) {
                t.setDaemon(false);
            }
            t.setPriority(threadPriority);
            return t;
        }
    }
}

ButtonClickUtils ==》防止快速点击

public class ButtonClickUtils {

    private ButtonClickUtils() {
        throw new UnsupportedOperationException("u can't instantiate me...");
    }

    // 两次点击按钮之间的点击间隔不能少于1000毫秒
    private static final int MIN_CLICK_DELAY_TIME = 500;
    private static long lastClickTime;

    public static boolean isFastClick() {
        boolean flag = false;
        long curClickTime = System.currentTimeMillis();

        if ((curClickTime - lastClickTime) < MIN_CLICK_DELAY_TIME) {
            flag = true;
        } else {
            lastClickTime = curClickTime;
        }
        return flag;
    }

}

DataUtils ==》填充数据工具类

public class DataUtils {
    private DataUtils() {
        throw new UnsupportedOperationException("u can't instantiate me...");
    }


    //不带翻页的设置数据
    public static <T extends Object> void initDataNoPager(List<?> arrayList, List<T> dataList, BaseAdapter adapter) {
        if (dataList != null && dataList.size() > 0) {
            ((List<T>) arrayList).addAll(dataList);
        }
        adapter.notifyDataSetChanged();
    }


    public static <T extends Object> void initDataNoPager(List<?> arrayList, List<T> dataList, BaseAdapter adapter, View emptyView) {
        initDataNoPager(arrayList, dataList, adapter);
        if (emptyView != null) {
            isShowEmpty((ArrayList<?>) arrayList, emptyView);
        }
    }


    public static <T extends Object> void initData(int pageNumber, List<?> arrayList, List<T> dataList, BaseAdapter adapter, SmartRefreshLayout smartRefreshLayout, View emptyView) {
        initData(pageNumber, arrayList, dataList, adapter, smartRefreshLayout);
        if (emptyView != null) {
            isShowEmpty((ArrayList<?>) arrayList, emptyView);
        }
    }

    //带翻页的设置数据
    public static <T extends Object> void initData(int pageNumber, List<?> arrayList, List<T> dataList, BaseAdapter adapter, SmartRefreshLayout smartRefreshLayout) {
        if (pageNumber == 0) {
            arrayList.clear();
        }

        if (dataList != null && dataList.size() > 0) {
            ((List<T>) arrayList).addAll(dataList);
        } else {
            if (smartRefreshLayout != null) {
                smartRefreshLayout.finishLoadMoreWithNoMoreData();
            }
        }

        if (pageNumber == 0) {
            adapter.notifyDataSetChanged();
        } else {
            if (arrayList.size() == 0) {
                adapter.notifyDataSetChanged();
            } else {
                if (dataList != null && dataList.size() > 0) {
                    adapter.notifyItemRangeChanged(arrayList.size() - dataList.size(), dataList.size());
                }
            }
        }
        if (smartRefreshLayout != null) {
            smartRefreshLayout.finishRefresh();
            smartRefreshLayout.finishLoadMore();
        }
    }


    public static void notifyItemRemoved(int removePosition, BaseAdapter adapter, ArrayList<?> arrayList, View emptyView) {
        notifyItemRemoved(removePosition, adapter, arrayList);
        if (emptyView != null) {
            isShowEmpty(arrayList, emptyView);
        }
    }


    public static void notifyItemRemoved(int removePosition, BaseAdapter adapter, ArrayList<?> arrayList) {
        adapter.notifyItemRemoved(removePosition);
        adapter.notifyItemRangeChanged(removePosition, adapter.getItemCount());
        arrayList.remove(removePosition);
    }


    public static void isShowEmpty(ArrayList<?> arrayList, View view) {
        if (arrayList != null && arrayList.size() > 0) {
            view.setVisibility(View.GONE);
        } else {
            view.setVisibility(View.VISIBLE);
        }
    }
}

GsonUtil

public class GsonUtil {
    private GsonUtil() {
        throw new UnsupportedOperationException("u can't instantiate me...");
    }

    private static Gson getGsonObject() {
        Gson gson = new GsonBuilder().serializeNulls().create();
        return gson;
    }

    /**
     * 对象转Gson字符串
     *
     * @param object
     * @return
     */
    public static <T extends Object> String ser(T object) {
        Gson gson = getGsonObject();
        return gson.toJson(object);
    }

    /**
     * Gson字符串转可序列化对象
     *
     * @param object
     * @param clazz
     * @return
     */
    public static <T extends Object> T deser(String object, Class<T> clazz) {
        Gson gson = getGsonObject();

        T result = null;
        try {
            result = gson.fromJson(object, clazz);
        } catch (Exception e) {
            result = null;
            e.printStackTrace();
        }

        return result;
    }

    /**
     * Gson字符串转可序列化对象
     *
     * @param object
     * @return
     */
    public static <T extends Object> T deser(String object, Type type) {
        Gson gson = getGsonObject();

        T result = null;
        try {
            result = gson.fromJson(object, type);
        } catch (Exception e) {
            result = null;
            e.printStackTrace();
        }

        return result;
    }



    /**
     * 快速读取本地json文件
     * * */
    public String getJson(Context context, String fileName) {
        StringBuilder stringBuilder = new StringBuilder();
        try {
            AssetManager assetManager = context.getAssets();
            BufferedReader bf = new BufferedReader(new InputStreamReader(
                    assetManager.open(fileName)));
            String line;
            while ((line = bf.readLine()) != null) {
                stringBuilder.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return stringBuilder.toString();
    }


}

KeyBoardUtils ==》打开或关闭软键盘

public class KeyBoardUtils {

    private KeyBoardUtils() {
        throw new UnsupportedOperationException("u can't instantiate me...");
    }
    /**
     * 打开软键盘
     */
    public static void openKeybord() {
        InputMethodManager imm = (InputMethodManager) LeoUtils.getApplication().getSystemService(Context.INPUT_METHOD_SERVICE);
        if (imm == null) {
            return;
        }
        imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
    }

    //带EditText参数时,获取焦点
    public static void openKeybord(EditText mEditText) {
        //设置可获得焦点
        mEditText.setFocusable(true);
        mEditText.setFocusableInTouchMode(true);
        //请求获得焦点
        mEditText.requestFocus();
        InputMethodManager imm = (InputMethodManager) LeoUtils.getApplication().getSystemService(Context.INPUT_METHOD_SERVICE);
        if (imm == null) {
            return;
        }
        imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
    }


    /**
     * 关闭软键盘
     */

    //如果是EditText的话,同时取消焦点
    public static void closeKeybord(View view) {
        if (view instanceof EditText){
            ((EditText)view).clearFocus();
        }
        InputMethodManager imm =
                (InputMethodManager) LeoUtils.getApplication().getSystemService(Context.INPUT_METHOD_SERVICE);
        if (imm == null) return;
        imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
    }


    //只是单纯的关闭软键盘
    public static void closeKeybord(Activity activity) {
        Window window = activity.getWindow();
        View view = window.getCurrentFocus();
        if (view == null) {
            View decorView = window.getDecorView();
            View focusView = decorView.findViewWithTag("keyboardTagView");
            if (focusView == null) {
                view = new EditText(window.getContext());
                view.setTag("keyboardTagView");
                ((ViewGroup) decorView).addView(view, 0, 0);
            } else {
                view = focusView;
            }
            view.requestFocus();
        }
        closeKeybord(view);
    }



    /**
     * 判断当前点击屏幕的地方是否是软键盘:
     *
     * @param v
     * @param event
     * @return
     */
    public static boolean isShouldHideInput(View v, MotionEvent event) {
        if (v != null && (v instanceof EditText)) {
            int[] leftTop = {0, 0};
            v.getLocationInWindow(leftTop);
            int left = leftTop[0], top = leftTop[1], bottom = top + v.getHeight(), right = left
                    + v.getWidth();
            if (event.getX() > left && event.getX() < right
                    && event.getY() > top && event.getY() < bottom) {
                // 保留点击EditText的事件
                return false;
            } else {
                return true;
            }
        }
        return false;
    }

    //点击屏幕空白处,隐藏软键盘
//    @Override
//    public boolean dispatchTouchEvent(MotionEvent ev) {
//        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
//            View v = getCurrentFocus();
//            if (isShouldHideInput(v, ev)) {
//                KeyBoardUtils.closeKeybord(binding.editPhone, LoginActivity.this);
//            }
//        }
//        return super.dispatchTouchEvent(ev);
//    }

}

LogUtils

public class LogUtils {

    //可以全局控制是否打印log日志
    private static boolean isEnableLog = true;
    private static int LOG_MAXLENGTH = 3000;
    public static final String TAG = LogUtils.class.getSimpleName();


    public static void v(String msg) {
        v(TAG, msg);
    }

    public static void v(String tagName, String msg) {
        if (isEnableLog) {
            //如果是null
            if (msg == null) {
                Log.v(tagName, "null");
                return;
            }

            //如果是空的话
            if (TextUtils.isEmpty(msg)) {
                Log.v(tagName, "\"\"");
                return;
            }


            int strLength = msg.length();
            if (strLength > LOG_MAXLENGTH) {
                //如果打印长度大于,限制的最大长度后,我们就需要分段打印
                //已经打印的长度
                int printLenght = 0;
                //初始化一个开始打印的index
                int printStart = 0;
                //总长度大于已打印的长度,那么就一直打印
                while (strLength > printLenght) {

                    if ((printStart + LOG_MAXLENGTH) <= strLength) {
                        Log.v(tagName, msg.substring(printStart, printStart + LOG_MAXLENGTH));
                        printLenght = printStart + LOG_MAXLENGTH;
                        printStart = printStart + LOG_MAXLENGTH;
                    } else {
                        Log.v(tagName, msg.substring(printStart, strLength));
                        printLenght = strLength;
                    }
                }

            } else {
                Log.v(tagName, msg);
            }
        }
    }

    public static void d(String msg) {
        d(TAG, msg);
    }

    public static void d(String tagName, String msg) {
        if (isEnableLog) {
            //如果是null
            if (msg == null) {
                Log.d(tagName, "null");
                return;
            }

            //如果是空的话
            if (TextUtils.isEmpty(msg)) {
                Log.d(tagName, "\"\"");
                return;
            }


            int strLength = msg.length();
            if (strLength > LOG_MAXLENGTH) {
                //如果打印长度大于,限制的最大长度后,我们就需要分段打印
                //已经打印的长度
                int printLenght = 0;
                //初始化一个开始打印的index
                int printStart = 0;
                //总长度大于已打印的长度,那么就一直打印
                while (strLength > printLenght) {

                    if ((printStart + LOG_MAXLENGTH) <= strLength) {
                        Log.d(tagName, msg.substring(printStart, printStart + LOG_MAXLENGTH));
                        printLenght = printStart + LOG_MAXLENGTH;
                        printStart = printStart + LOG_MAXLENGTH;
                    } else {
                        Log.d(tagName, msg.substring(printStart, strLength));
                        printLenght = strLength;
                    }
                }

            } else {
                Log.d(tagName, msg);
            }
        }
    }

    public static void i(String msg) {
        i(TAG, msg);
    }


    public static void i(String tagName, String msg) {
        if (isEnableLog) {
            //如果是null
            if (msg == null) {
                Log.i(tagName, "null");
                return;
            }

            //如果是空的话
            if (TextUtils.isEmpty(msg)) {
                Log.i(tagName, "\"\"");
                return;
            }


            int strLength = msg.length();
            if (strLength > LOG_MAXLENGTH) {
                //如果打印长度大于,限制的最大长度后,我们就需要分段打印
                //已经打印的长度
                int printLenght = 0;
                //初始化一个开始打印的index
                int printStart = 0;
                //总长度大于已打印的长度,那么就一直打印
                while (strLength > printLenght) {

                    if ((printStart + LOG_MAXLENGTH) <= strLength) {
                        Log.i(tagName, msg.substring(printStart, printStart + LOG_MAXLENGTH));
                        printLenght = printStart + LOG_MAXLENGTH;
                        printStart = printStart + LOG_MAXLENGTH;
                    } else {
                        Log.i(tagName, msg.substring(printStart, strLength));
                        printLenght = strLength;
                    }
                }

            } else {
                Log.i(tagName, msg);
            }
        }
    }

    public static void w(String msg) {
        w(TAG, msg);
    }

    public static void w(String tagName, String msg) {
        if (isEnableLog) {
            //如果是null
            if (msg == null) {
                Log.w(tagName, "null");
                return;
            }

            //如果是空的话
            if (TextUtils.isEmpty(msg)) {
                Log.w(tagName, "\"\"");
                return;
            }


            int strLength = msg.length();
            if (strLength > LOG_MAXLENGTH) {
                //如果打印长度大于,限制的最大长度后,我们就需要分段打印
                //已经打印的长度
                int printLenght = 0;
                //初始化一个开始打印的index
                int printStart = 0;
                //总长度大于已打印的长度,那么就一直打印
                while (strLength > printLenght) {

                    if ((printStart + LOG_MAXLENGTH) <= strLength) {
                        Log.w(tagName, msg.substring(printStart, printStart + LOG_MAXLENGTH));
                        printLenght = printStart + LOG_MAXLENGTH;
                        printStart = printStart + LOG_MAXLENGTH;
                    } else {
                        Log.w(tagName, msg.substring(printStart, strLength));
                        printLenght = strLength;
                    }
                }

            } else {
                Log.w(tagName, msg);
            }
        }
    }

    public static void e(String msg) {
        e(TAG, msg);
    }

    public static void e(String tagName, String msg) {
        if (isEnableLog) {
            //如果是null
            if (msg == null) {
                Log.e(tagName, "null");
                return;
            }

            //如果是空的话
            if (TextUtils.isEmpty(msg)) {
                Log.e(tagName, "\"\"");
                return;
            }


            int strLength = msg.length();
            if (strLength > LOG_MAXLENGTH) {
                //如果打印长度大于,限制的最大长度后,我们就需要分段打印
                //已经打印的长度
                int printLenght = 0;
                //初始化一个开始打印的index
                int printStart = 0;
                //总长度大于已打印的长度,那么就一直打印
                while (strLength > printLenght) {

                    if ((printStart + LOG_MAXLENGTH) <= strLength) {
                        Log.e(tagName, msg.substring(printStart, printStart + LOG_MAXLENGTH));
                        printLenght = printStart + LOG_MAXLENGTH;
                        printStart = printStart + LOG_MAXLENGTH;
                    } else {
                        Log.e(tagName, msg.substring(printStart, strLength));
                        printLenght = strLength;
                    }
                }

            } else {
                Log.e(tagName, msg);
            }
        }
    }
}

MathUtils

public class MathUtils {
    private MathUtils() {
        throw new UnsupportedOperationException("u can't instantiate me...");
    }

    //保留几位小数
    public static double round(Double v, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        BigDecimal b = null == v ? new BigDecimal("0.0") : new BigDecimal(Double.toString(v));
        BigDecimal one = new BigDecimal("1");
        return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).doubleValue();

    }
}

MoreUtils ==》手机号判断等

public class MoreUtils {
    private MoreUtils() {
        throw new UnsupportedOperationException("u can't instantiate me...");
    }


    /**
     * 判断号码是否是手机号
     *
     * @param mobiles
     * @return
     */
    public static boolean isPhoneNumber(String mobiles) {
        if (TextUtils.isEmpty(mobiles)) {
            return false;
        }

        if (mobiles.length() != 11) {
            return false;
        }
        Pattern p = Pattern
                .compile("^((13[0-9])|(14[0-9])|(15[0-9])|(16[0-9])|(17[0-9])|(18[0-9])|(19[0-9]))\\d{8}$");
        Matcher m = p.matcher(mobiles);
        return m.matches();
    }


    /**
     * 判断身份证号是否正确(其中包括了月份和日期进行了判断)
     *
     * @param text
     * @return
     */
    public static boolean isIDcards(String text) {
        Pattern p = Pattern
                .compile("^\\d{6}(18|19|20)\\d{2}(0[1-9]|1[012])(0[1-9]|[12]\\d|3[01])\\d{3}(\\d|[xX])$");
        Matcher m = p.matcher(text);
        return m.matches();
    }


    //1:是男  2:是女
    public static int isSex(String idCard) {
        if (!TextUtils.isEmpty(idCard) && idCard.length() == 18) {
            if (Integer.parseInt(idCard.substring(16, 17)) % 2 == 0) {
                return 2;
            } else {
                return 1;
            }
        }
        return 0;
    }


    /**
     * 根据身份证号码计算年龄
     *
     * @param psptNo
     * @return
     */
    public static int getAge(String psptNo) {
        if (TextUtils.isEmpty(psptNo)) {
            return 0;
        }
        String birthDay = psptNo.substring(6, 14);
        String time = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        String yearStr = time.split("-")[0];
        String monthStr = time.split("-")[1];
        String dayStr = time.split("-")[2];
        String yearBirthStr = birthDay.substring(0, 4);
        String monthBirthStr = birthDay.substring(4, 6);
        String dayBirthStr = birthDay.substring(6);
        int year = Integer.valueOf(yearStr);
        int yearBirth = Integer.valueOf(yearBirthStr);
        if (year - yearBirth <= 0) {
            return 0;
        }
        int age = year - yearBirth;
        int month = Integer.valueOf(monthStr);
        int monthBirth = Integer.valueOf(monthBirthStr);
        if (month - monthBirth > 0) {
            return age;
        }
        if (month - monthBirth < 0) {
            return --age;
        }
        int day = Integer.valueOf(dayStr);
        int dayBirth = Integer.valueOf(dayBirthStr);
        if (day - dayBirth >= 0) {
            return age;
        }
        return --age;
    }



    //获取是否有通知权限
    public static boolean isNotificationEnabled(Context context) {
        boolean isOpened = false;
        try {
            isOpened = NotificationManagerCompat.from(context).areNotificationsEnabled();
        } catch (Exception e) {
            e.printStackTrace();
            isOpened = false;
        }
        return isOpened;
    }

    /**
     * 跳到通知栏设置界面
     *
     * @param context
     */
    public static void goNotificationSetting(Context context) {
        Intent intent = new Intent();
        if (Build.VERSION.SDK_INT >= 26) {
            intent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
            intent.putExtra(Settings.EXTRA_APP_PACKAGE, context.getPackageName());
        } else if (Build.VERSION.SDK_INT >= 21) {
            intent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
            intent.putExtra("app_package", context.getPackageName());
            intent.putExtra("app_uid", context.getApplicationInfo().uid);
        } else {
            // 其他
            intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
            intent.setData(Uri.fromParts("package", context.getPackageName(), null));
        }
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);
    }


    
    
        //获得独一无二的Psuedo ID  这里有个兼容
    public static String getDeviceId(Context context) {
        if (context.getApplicationInfo().targetSdkVersion >= 29 && Build.VERSION.SDK_INT >= 29) {
            //大于等于29使用特殊方法
            String id = null;
            String androidId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
            if (!TextUtils.isEmpty(androidId) && "9774d56d682e549c" != androidId) {
                try {
                    UUID uuid = UUID.nameUUIDFromBytes(androidId.getBytes("utf-8"));
                    id = uuid.toString();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            if (TextUtils.isEmpty(id)) {
                return UUID.randomUUID().toString();
            } else {
                return id;
            }
        } else {
            return getDeviceId();
        }

    }
    
    
    
    
    
    
    //获得独一无二的Psuedo ID
    public static String getDeviceId() {
        String serial = null;
        String m_szDevIDShort = "35" +
                Build.BOARD.length() % 10 + Build.BRAND.length() % 10 +

                Build.CPU_ABI.length() % 10 + Build.DEVICE.length() % 10 +

                Build.DISPLAY.length() % 10 + Build.HOST.length() % 10 +

                Build.ID.length() % 10 + Build.MANUFACTURER.length() % 10 +

                Build.MODEL.length() % 10 + Build.PRODUCT.length() % 10 +

                Build.TAGS.length() % 10 + Build.TYPE.length() % 10 +

                Build.USER.length() % 10; //13 位

        try {
            serial = android.os.Build.class.getField("SERIAL").get(null).toString();
            //API>=9 使用serial号
            return new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString();
        } catch (Exception exception) {
            //serial需要一个初始化
            serial = "serial"; // 随便一个初始化
        }
        //使用硬件信息拼凑出来的15位号码
        return new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString();
    }




    /**
     * 获取当前手机系统语言。
     *
     * @return 返回当前系统语言。例如:当前设置的是“中文-中国”,则返回“zh-CN”
     */
    public static String getSystemLanguage() {
        return Locale.getDefault().getLanguage();
    }

    /**
     * 获取当前系统上的语言列表(Locale列表)
     *
     * @return 语言列表
     */
    public static Locale[] getSystemLanguageList() {
        return Locale.getAvailableLocales();
    }

    /**
     * 获取当前手机系统版本号
     *
     * @return 系统版本号
     */
    public static String getSystemVersion() {
        return Build.VERSION.RELEASE;
    }

    /**
     * 获取手机型号
     *
     * @return 手机型号
     */
    public static String getSystemModel() {
        return Build.MODEL;
    }

    /**
     * 获取手机厂商
     *
     * @return 手机厂商
     */
    public static String getDeviceBrand() {
        return Build.BRAND;
    }


    /**
     * get App versionCode
     *
     * @param context
     * @return
     */
    public static int getVersionCode(Context context) {
        PackageManager packageManager = context.getPackageManager();
        PackageInfo packageInfo;
        int versionCode = 1;
        try {
            packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
            versionCode = packageInfo.versionCode ;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        return versionCode;
    }

    /**
     * get App versionName
     *
     * @param context
     * @return
     */
    public static String getVersionName(Context context) {
        PackageManager packageManager = context.getPackageManager();
        PackageInfo packageInfo;
        String versionName = "";
        try {
            packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
            versionName = packageInfo.versionName;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        return versionName;
    }


    public static String md5(String content) {//MD5加密
        byte[] hash;
        try {
            hash = MessageDigest.getInstance("MD5").digest(content.getBytes("UTF-8"));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("NoSuchAlgorithmException",e);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("UnsupportedEncodingException", e);
        }

        StringBuilder hex = new StringBuilder(hash.length * 2);
        for (byte b : hash) {
            if ((b & 0xFF) < 0x10){
                hex.append("0");
            }
            hex.append(Integer.toHexString(b & 0xFF));
        }
        return hex.toString();
    }


    @RequiresApi(api = Build.VERSION_CODES.O)
    public static String base64(String content){
        String encodeResult = java.util.Base64.getEncoder().encodeToString(content.getBytes());
        return encodeResult;
    }
}

PictureProgressUtil ==》用于框架,图片上传时显示图片上传进度

public class PictureProgressUtil {
    public static int currentProgress = 0;
    public static int totalProgress = 0;
    public static int oldProgress = 0;

    public static void initData(int pictureSize) {
        currentProgress = 0;
        oldProgress = 0;
        totalProgress = 100 * pictureSize;
    }

    public static int setCurrentProgress(int progress) {
        if (progress <= oldProgress) {
            progress += 100;
            int trueCount = progress - oldProgress;
            currentProgress += trueCount;
            oldProgress = progress - 100;
        } else {
            int trueCount = progress - oldProgress;
            currentProgress += trueCount;
            oldProgress = progress;
        }
        if (currentProgress >= totalProgress) {
            currentProgress = totalProgress;
        }
        return currentProgress * 100 / totalProgress;
    }
}

PinyinUtils

public class PinyinUtils {
    /**
     * 获得汉语拼音首字母
     *
     * @param chines 汉字
     * @return
     */
    public static String getChineaseABC(String chines) {
        String pinyinName = "";
        char[] nameChar = chines.toCharArray();
        HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
        defaultFormat.setCaseType(HanyuPinyinCaseType.UPPERCASE);
        defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        for (int i = 0; i < nameChar.length; i++) {
            if (nameChar[i] > 128) {
                try {
                    pinyinName += PinyinHelper.toHanyuPinyinStringArray(
                            nameChar[i], defaultFormat)[0].charAt(0);
                } catch (BadHanyuPinyinOutputFormatCombination e) {
                    e.printStackTrace();
                }
            } else {
                pinyinName += nameChar[i];
            }
        }
        return pinyinName;
    }

    /**
     * 中文转拼音全拼,英文字符不变
     *
     * @param inputString 汉字
     * @return
     */
    public static String getPingYin(String inputString) {
        HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
        format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
        format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        format.setVCharType(HanyuPinyinVCharType.WITH_V);
        String output = "";
        if (inputString != null && inputString.length() > 0
                && !"null".equals(inputString)) {
            char[] input = inputString.trim().toCharArray();
            try {
                for (int i = 0; i < input.length; i++) {
                    if (Character.toString(input[i]).matches(
                            "[\\u4E00-\\u9FA5]+")) {
                        String[] temp = PinyinHelper.toHanyuPinyinStringArray(
                                input[i], format);
                        output += temp[0];
                    } else
                        output += Character.toString(input[i]);
                }
            } catch (BadHanyuPinyinOutputFormatCombination e) {
                e.printStackTrace();
            }
        } else {
            return "*";
        }
        return output;
    }

    /**
     * 中文转汉语拼音首字母,英文字符不变
     *
     * @param chines 汉字
     * @return 拼音
     */
    public static String converterToFirstSpell(String chines) {
        String pinyinName = "";
        char[] nameChar = chines.toCharArray();
        HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
        defaultFormat.setCaseType(HanyuPinyinCaseType.UPPERCASE);
        defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        for (int i = 0; i < nameChar.length; i++) {
            if (nameChar[i] > 128) {
                try {
                    pinyinName += PinyinHelper.toHanyuPinyinStringArray(
                            nameChar[i], defaultFormat)[0].charAt(0);
                } catch (BadHanyuPinyinOutputFormatCombination e) {
                    e.printStackTrace();
                }
            } else {
                pinyinName += nameChar[i];
            }
        }
        return pinyinName;
    }


    /**
     * 将小写字母转成大写字母
     */

    //将小写字母 转换成大写字母
    public static String switchSmallToBig(String str) {
        char[] c = str.toCharArray();
        for (int i = 0; i < str.length(); i++) {
//                if (c[i] >= 'A' && c[i] <= 'Z')
//                    c[i] += 32;
//                else
            if (c[i] >= 'a' && c[i] <= 'z')
                c[i] -= 32;
        }

        return new String(c);
    }

    //将小写字母 转换成大写字母
    public static String switchBigToSmall(String str) {
        char[] c = str.toCharArray();
        for (int i = 0; i < str.length(); i++) {
            if (c[i] >= 'A' && c[i] <= 'Z')
                c[i] += 32;
//                else
//            if (c[i] >= 'a' && c[i] <= 'z')
//                c[i] -= 32;
        }

        return new String(c);
    }


    //将大小写互相转换
    public static String switchLetter(String str) {
        char[] c = str.toCharArray();
        for (int i = 0; i < str.length(); i++) {
            if (c[i] >= 'A' && c[i] <= 'Z')
                c[i] += 32;
            else if (c[i] >= 'a' && c[i] <= 'z')
                c[i] -= 32;
        }

        return new String(c);
    }


}

PreferenceUtil

public class PreferenceUtil {
    public static final String FILE_NAME = "sp_name";

    private PreferenceUtil() {
        throw new UnsupportedOperationException("u can't instantiate me...");
    }

    /**
     * 这里是对基本数据类型进行的操作
     */
    /*
     * 这里是保存基本数据类型 -- 表名是上面设置的FILE_NAME
     * */
    public static void put(String key, Object object) {

        SharedPreferences sp = LeoUtils.getApplication().getSharedPreferences(FILE_NAME,
                LeoUtils.getApplication().MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();

        if (object instanceof String) {
            editor.putString(key, (String) object);
        } else if (object instanceof Integer) {
            editor.putInt(key, (Integer) object);
        } else if (object instanceof Boolean) {
            editor.putBoolean(key, (Boolean) object);
        } else if (object instanceof Float) {
            editor.putFloat(key, (Float) object);
        } else if (object instanceof Long) {
            editor.putLong(key, (Long) object);
        } else {
            editor.putString(key, object.toString());
        }
        editor.commit();
    }

    /*
     * 这里是根据key,获取数据。表名是 -- FILE_NAME
     * 第二个参数是  默认值
     * */
    public static Object get(String key, Object defaultObject) {
        SharedPreferences sp = LeoUtils.getApplication().getSharedPreferences(FILE_NAME,
                LeoUtils.getApplication().MODE_PRIVATE);

        if (defaultObject instanceof String) {
            return sp.getString(key, (String) defaultObject);
        } else if (defaultObject instanceof Integer) {
            return sp.getInt(key, (Integer) defaultObject);
        } else if (defaultObject instanceof Boolean) {
            return sp.getBoolean(key, (Boolean) defaultObject);
        } else if (defaultObject instanceof Float) {
            return sp.getFloat(key, (Float) defaultObject);
        } else if (defaultObject instanceof Long) {
            return sp.getLong(key, (Long) defaultObject);
        }

        return null;
    }


    /*
     * 根据某个key值获取数据  表名 -- FILE_NAME
     * */
    public static void remove(String key) {
        SharedPreferences sp = LeoUtils.getApplication().getSharedPreferences(FILE_NAME,
                LeoUtils.getApplication().MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        editor.remove(key);
        editor.commit();
    }

    /*
     * 清楚 表名 -- FILE_NAME 里所有的数据
     * */
    public static void clear() {
        SharedPreferences sp = LeoUtils.getApplication().getSharedPreferences(FILE_NAME,
                LeoUtils.getApplication().MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        editor.clear();
        editor.commit();
    }

    /*
     * 判断当前key值 是否存在于  表名--FILE_NAME 表里
     * */
    public static boolean contains(String key) {
        SharedPreferences sp = LeoUtils.getApplication().getSharedPreferences(FILE_NAME,
                LeoUtils.getApplication().MODE_PRIVATE);
        return sp.contains(key);
    }


    /*
     * 返回表名 -- FILE_NAME里所有的数据,以Map键值对的方式
     * */
    public static Map<String, ?> getAll() {
        SharedPreferences sp = LeoUtils.getApplication().getSharedPreferences(FILE_NAME,
                LeoUtils.getApplication().MODE_PRIVATE);
        return sp.getAll();
    }


    /**
     * 以下是保存类的方式,跟上面的FILE_NAME表不在一个表里
     */
    /*
     * 保存类,当前SharedPreferences以 class类名被表名
     * */
    public static <T extends Serializable> boolean putByClass(String key, T entity) {
        if (entity == null) {
            return false;
        }
        String prefFileName = entity.getClass().getName();
        SharedPreferences sp = LeoUtils.getApplication().getSharedPreferences(prefFileName, 0);
        SharedPreferences.Editor et = sp.edit();
        String json = GsonUtil.ser(entity);
        et.putString(key, json);
        return et.commit();
    }


    /*
     * 获取某个以class 为表名的。所有class 对象
     * */
    public static <T extends Serializable> List<T> getAllByClass(Class<T> clazz) {
        String prefFileName = clazz.getName();
        SharedPreferences sp = LeoUtils.getApplication().getSharedPreferences(prefFileName, 0);
        Map<String, String> values = (Map<String, String>) sp.getAll();
        List<T> results = new ArrayList<T>();
        if (values == null || values.isEmpty())
            return results;
        Collection<String> colles = values.values();
        for (String json : colles) {
            results.add(GsonUtil.deser(json, clazz));
        }
        return results;
    }

    /*
     * 获取以类名为表名的,某个key值上的value
     * 第二个参数是,类名class,也就是当前的表名
     * */
    public static <T extends Serializable> T getByClass(String key, Class<T> clazz) {
        String prefFileName = clazz.getName();
        SharedPreferences sp = LeoUtils.getApplication().getSharedPreferences(prefFileName, 0);

        String json = sp.getString(key, null);
        if (json == null) {
            return null;
        }
        return GsonUtil.deser(json, clazz);
    }

    /*
     * 在以类名为表名的表上,移除key值
     * 第二个参数是,类名class,也就是当前的表名
     * */
    public static <T extends Serializable> void removeByClass(String key, Class<T> clazz) {
        String prefFileName = clazz.getName();
        SharedPreferences sp = LeoUtils.getApplication().getSharedPreferences(prefFileName, 0);
        if (sp.contains(key)) {
            sp.edit().remove(key).commit();
        }
    }

    /*
     * 移除 某个以类名为表名上的所有的值
     * */
    public static <T extends Serializable> void clearByClass(Class<T> clazz) {
        String prefFileName = clazz.getName();
        SharedPreferences sp = LeoUtils.getApplication().getSharedPreferences(prefFileName, 0);
        sp.edit().clear().commit();
    }
}

SpannableStringBuilder

public class SpannableStringBuilder {
    private String sourceStr;
    SpannableString spannableString;

    public SpannableStringBuilder(String sourceStr) {
        this.sourceStr = sourceStr;
        spannableString = new SpannableString(sourceStr);

    }

    public static SpannableStringBuilder build(String sourceStr) {
        return new SpannableStringBuilder(sourceStr);
    }


    // 设置字体颜色值
    public SpannableStringBuilder color(int color, int start, int end) {
        ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(color);
        spannableString.setSpan(foregroundColorSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        return this;
    }

    // 设置字体颜色值
    public SpannableStringBuilder color(int color, String target) {
        if (sourceStr.contains(target)) {
            int start = sourceStr.indexOf(target);
            int end = start + target.length();
            ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(color);
            spannableString.setSpan(foregroundColorSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
        return this;
    }


    //设置字体背景颜色值
    public SpannableStringBuilder backgroundColor(int color, int start, int end) {
        BackgroundColorSpan backgroundColorSpan = new BackgroundColorSpan(color);
        spannableString.setSpan(backgroundColorSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        return this;
    }

    //设置字体背景颜色值
    public SpannableStringBuilder backgroundColor(int color, String target) {
        if (sourceStr.contains(target)) {
            int start = sourceStr.indexOf(target);
            int end = start + target.length();
            BackgroundColorSpan backgroundColorSpan = new BackgroundColorSpan(color);
            spannableString.setSpan(backgroundColorSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
        return this;
    }


    // 设置字体下划线
    public SpannableStringBuilder underline(int start, int end) {
        UnderlineSpan underlineSpan = new UnderlineSpan();
        spannableString.setSpan(underlineSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        return this;
    }


    // 设置字体下划线
    public SpannableStringBuilder underline(String target) {
        if (sourceStr.contains(target)) {
            int start = sourceStr.indexOf(target);
            int end = start + target.length();
            UnderlineSpan underlineSpan = new UnderlineSpan();
            spannableString.setSpan(underlineSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
        return this;
    }


    // 设置字体删除线
    public SpannableStringBuilder deleteline(int start, int end) {
        StrikethroughSpan strikethroughSpan = new StrikethroughSpan();
        spannableString.setSpan(strikethroughSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        return this;
    }


    // 设置字体删除线
    public SpannableStringBuilder deleteline(String target) {
        if (sourceStr.contains(target)) {
            int start = sourceStr.indexOf(target);
            int end = start + target.length();
            StrikethroughSpan strikethroughSpan = new StrikethroughSpan();
            spannableString.setSpan(strikethroughSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
        return this;
    }


    // 设置字体大小,textSize
    public SpannableStringBuilder textSize(int dimens, int start, int end) {
        int size = (int) LeoUtils.getApplication().getResources().getDimension(dimens);
        AbsoluteSizeSpan absoluteSizeSpan = new AbsoluteSizeSpan(size);
        spannableString.setSpan(absoluteSizeSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        return this;
    }

    // 设置字体大小,textSize
    public SpannableStringBuilder textSize(int dimens, String target) {
        if (sourceStr.contains(target)) {
            int size = (int) LeoUtils.getApplication().getResources().getDimension(dimens);
            int start = sourceStr.indexOf(target);
            int end = start + target.length();
            AbsoluteSizeSpan absoluteSizeSpan = new AbsoluteSizeSpan(size);
            spannableString.setSpan(absoluteSizeSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
        return this;
    }


    // 设置字体大小,RelativeSizeSpan 在原有基础上去修改
    public SpannableStringBuilder textSize(float scale, int start, int end) {
        RelativeSizeSpan relativeSizeSpan = new RelativeSizeSpan(scale);
        spannableString.setSpan(relativeSizeSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        return this;
    }


    // 设置字体大小,RelativeSizeSpan 在原有基础上去修改
    public SpannableStringBuilder textSize(float scale, String target) {
        if (sourceStr.contains(target)) {
            int start = sourceStr.indexOf(target);
            int end = start + target.length();
            RelativeSizeSpan relativeSizeSpan = new RelativeSizeSpan(scale);
            spannableString.setSpan(relativeSizeSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
        return this;
    }


    // 设置字体加粗
    public SpannableStringBuilder bold(int start, int end) {
        StyleSpan styleSpan = new StyleSpan(Typeface.BOLD);
        spannableString.setSpan(styleSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        return this;
    }


    // 设置字体加粗
    public SpannableStringBuilder bold(String target) {
        if (sourceStr.contains(target)) {
            int start = sourceStr.indexOf(target);
            int end = start + target.length();
            StyleSpan styleSpan = new StyleSpan(Typeface.BOLD);
            spannableString.setSpan(styleSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
        return this;
    }


    // 添加图片  注意插入图片,会覆盖文案。所以在插入图片前得有个占位
    public SpannableStringBuilder image(int start, int end, int drawableId, int dimensWith, int dimensHeight) {
        Drawable drawable = LeoUtils.getApplication().getResources().getDrawable(drawableId);
        drawable.setBounds(0, 0, (int) LeoUtils.getApplication().getResources().getDimension(dimensWith), (int) LeoUtils.getApplication().getResources().getDimension(dimensHeight));
        ImageSpan imageSpan = new ImageSpan(drawable);
        spannableString.setSpan(imageSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        return this;
    }


    //添加点击事件
    public SpannableStringBuilder clickSpan(int start, int end, int color, boolean isUnderline, ClickableSpanListener clickableSpanListener) {
        this.clickableSpanListener = clickableSpanListener;
        spannableString.setSpan(new ClickableSpan() {
            @Override
            public void updateDrawState(TextPaint ds) {
                super.updateDrawState(ds);
                ds.setColor(LeoUtils.getApplication().getResources().getColor(color));       //设置文件颜色
                ds.setUnderlineText(isUnderline);      //设置下划线
            }

            @Override
            public void onClick(View view) {
                if (clickableSpanListener != null) {
                    clickableSpanListener.onClick(view);
                }
            }
        }, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

        return this;
    }


    //添加点击事件
    public SpannableStringBuilder clickSpan(String target, int color, boolean isUnderline, ClickableSpanListener clickableSpanListener) {
        if (sourceStr.contains(target)) {
            int start = sourceStr.indexOf(target);
            int end = start + target.length();

            this.clickableSpanListener = clickableSpanListener;
            spannableString.setSpan(new ClickableSpan() {
                @Override
                public void updateDrawState(TextPaint ds) {
                    super.updateDrawState(ds);
                    ds.setColor(color);       //设置文件颜色
                    ds.setUnderlineText(isUnderline);      //设置下划线
                }

                @Override
                public void onClick(View view) {
                    if (clickableSpanListener != null) {
                        clickableSpanListener.onClick(view);
                    }
                }
            }, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

        }
        return this;
    }


    private ClickableSpanListener clickableSpanListener;

    public void into(TextView textView) {
        textView.setText(spannableString);
        if (clickableSpanListener != null) {
            textView.setHighlightColor(Color.TRANSPARENT); //设置点击后的颜色为透明,否则会一直出现高亮
            textView.setMovementMethod(LinkMovementMethod.getInstance());//开始响应点击事件
        }
    }

}

ClickableSpanListener

public interface ClickableSpanListener {
    void onClick(View view);
}

TextViewUtils

public class TextViewUtils {
    private TextViewUtils() {
        throw new UnsupportedOperationException("u can't instantiate me...");
    }

    /**
     * 固定宽度情况下,自适应文本字体大小
     *
     * @param tv
     * @param maxWidth
     * @param text
     * @return
     */
    public static float adjustTvTextSize(TextView tv, int maxWidth, String text) {
        int avaiWidth = maxWidth - tv.getPaddingLeft() - tv.getPaddingRight() - 10;

        if (avaiWidth <= 0 || TextUtils.isEmpty(text)) {
            return tv.getPaint().getTextSize();
        }

        TextPaint textPaintClone = new TextPaint(tv.getPaint());
        // note that Paint text size works in px not sp
        float trySize = textPaintClone.getTextSize();

        while (textPaintClone.measureText(text) > avaiWidth) {
            trySize--;
            textPaintClone.setTextSize(trySize);
        }

        tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, trySize);
        tv.setText(text);
        return trySize;
    }




    /**
     * 设置textView结尾...后面显示的文字和颜色
     * 例:xxxxxxxx...阅读原文
     *
     * @param context    上下文
     * @param textView   textview
     * @param minLines   最少的行数
     * @param originText 原文本
     * @param endText    结尾文字
     * @param endColorID 结尾文字颜色id
     * @param isExpand   当前是否是展开状态
     */
    public static void toggleEllipsize(final Context context,
                                       final TextView textView,
                                       final int minLines,
                                       final String originText,
                                       final String endText,
                                       final int endColorID,
                                       final boolean isExpand) {
        if (TextUtils.isEmpty(originText)) {
            return;
        }

        if (isExpand) {
            textView.setText(originText);
        } else {
            int paddingLeft = textView.getPaddingLeft();
            int paddingRight = textView.getPaddingRight();
            TextPaint paint = textView.getPaint();
            float moreText = textView.getTextSize() * endText.length();
            float availableTextWidth = (UIUtils.getScreenWidth() - paddingLeft - paddingRight) *
                    minLines - moreText;
            CharSequence ellipsizeStr = TextUtils.ellipsize(originText, paint,
                    availableTextWidth, TextUtils.TruncateAt.END);
            if (ellipsizeStr.length() < originText.length()) {
                CharSequence temp = ellipsizeStr + endText;
                SpannableStringBuilder ssb = new SpannableStringBuilder(temp);
                ssb.setSpan(new ForegroundColorSpan(context.getResources().getColor
                                (endColorID)),
                        temp.length() - endText.length(), temp.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
                textView.setText(ssb);
            } else {
                textView.setText(originText);
            }
        }
    }



    //字体带下阴影的办法
//    android:shadowColor="#ff009473"
//    android:shadowDx="0"
//    android:shadowDy="8"
//    android:shadowRadius="3.0"

}

TimeUtils

public class TimeUtils {

    /**
     * 时间戳 转时间。
     * @param timeMillis 时间戳
     * @param formatStr 要转换的时间格式;如:"yyyy.MM.dd  HH:mm"    "yyyy-MM-dd"
     * @return
     */
    public static String getStrByLong(long timeMillis, String formatStr) {
        Date date = new Date(timeMillis);
        SimpleDateFormat format = new SimpleDateFormat(formatStr);
        return format.format(date);
    }


    /**
     * 时间  转换为  时间戳
     *
     * @param timeStr 时间字符串 例如: 2016-03-09
     * @param formatStr  时间对应格式  例如: yyyy-MM-dd
     * @return
     */
    public static long getLongByStr(String timeStr, String formatStr) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(formatStr);
        Date date = null;
        try {
            date = simpleDateFormat.parse(timeStr);
            long timeStamp = date.getTime();
            return timeStamp;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return 0;
    }


    /**
     * 发布时间距离现在多久。要展示的文案
     */
    public static String getTimeFromNow(long milSecond) {

        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String nowStr = format.format(new Date());
        //当前时间
        try {
            long now = format.parse(nowStr).getTime();
            long tag = milSecond;
            int days = (int) ((now - tag) / (1000 * 60 * 60 * 24));
            if (days == 0) {
                //一天以内,以分钟, 小时, 刚刚显示
                int hours = (int) ((now - tag) / (1000 * 60 * 60));
                if (hours == 0) {
                    int minutes = (int) ((now - tag) / (1000 * 60));
                    if (minutes <= 0) {
                        return "刚刚";
                    } else {
                        return minutes + "分钟前";
                    }
                } else {
                    return hours + "小时前";
                }
            } else if (days >= 1 && days <= 7) {
                return days + "天前";
            } else if (days >= 365) {
                Date date = new Date(tag);
                SimpleDateFormat format_zuo = new SimpleDateFormat("yyyy-MM-dd");
                return format_zuo.format(date);
            } else {
                Date date = new Date(tag);
                SimpleDateFormat format_zuo = new SimpleDateFormat("MM-dd");
                return format_zuo.format(date);
            }


        } catch (ParseException e) {
            return "";
        }
    }


}

ToastUtils

public class ToastUtils {
    private static Context context = LeoUtils.getApplication();
    /**
     * Toast对象
     */
    private static Toast toast = null;

    /**
     * 显示Toast
     *
     * @param message
     */
    public static void showToast(String message) {
        if (toast == null) {
            toast = Toast.makeText(context, message, Toast.LENGTH_SHORT);
            toast.show();
        } else {
            toast.cancel();
            toast = Toast.makeText(context, message, Toast.LENGTH_SHORT);
            toast.show();
        }
    }
}

UIUtils ==》用单位换算,获取屏幕宽高,获取屏幕状态栏高度

public class UIUtils {

    private UIUtils() {
        throw new UnsupportedOperationException("u can't instantiate me...");
    }

    /*
     * dp 转 px
     * */
    public static int dp2px(float dpVal) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                dpVal, LeoUtils.getApplication().getResources().getDisplayMetrics());
    }

    /*
     * px 转 dp
     * */
    public static float px2dp(float pxVal) {
        final float scale = LeoUtils.getApplication().getResources().getDisplayMetrics().density;
        return (pxVal / scale);
    }

    /*
     * sp 转 px
     * */
    public static int sp2px(float spVal) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
                spVal, LeoUtils.getApplication().getResources().getDisplayMetrics());
    }

    /*
     * px 转 sp
     * */
    public static float px2sp(float pxVal) {
        return (pxVal / LeoUtils.getApplication().getResources().getDisplayMetrics().scaledDensity);
    }

    /*
     * 获取屏幕宽度
     * */
    public static int getScreenWidth() {
        WindowManager wm = (WindowManager) LeoUtils.getApplication().getSystemService(Context.WINDOW_SERVICE);
        if (wm == null) return -1;
        Point point = new Point();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            wm.getDefaultDisplay().getRealSize(point);
        } else {
            wm.getDefaultDisplay().getSize(point);
        }
        return point.x;
    }


    /*
     * 获取屏幕高度
     * */
    public static int getScreenHeight() {
        WindowManager wm = (WindowManager) LeoUtils.getApplication().getSystemService(Context.WINDOW_SERVICE);
        if (wm == null) return -1;
        Point point = new Point();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            wm.getDefaultDisplay().getRealSize(point);
        } else {
            wm.getDefaultDisplay().getSize(point);
        }
        return point.y;
    }


    /*
     * 获取屏幕状态栏高度
     * */
    public static int getStatusBarHeight() {
        Resources resources = LeoUtils.getApplication().getResources();
        int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
        return resources.getDimensionPixelSize(resourceId);
    }


    /*
    * 通过反射,获取包含虚拟键的整体屏幕高度
    * 有些android手机可以设置全屏或者是虚拟键,如果用getStatusBarHeight获取,往往不是全屏
    * */
    private int getHasVirtualKey(Activity activity) {
        int dpi = 0;
        Display display = activity.getWindowManager().getDefaultDisplay();
        DisplayMetrics dm = new DisplayMetrics();
        @SuppressWarnings("rawtypes")
        Class c;
        try {
            c = Class.forName("android.view.Display");
            @SuppressWarnings("unchecked")
            Method method = c.getMethod("getRealMetrics", DisplayMetrics.class);
            method.invoke(display, dm);
            dpi = dm.heightPixels;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return dpi;
    }

}