AvLoadingIndicatorView 的 封装

简介: AvLoadingIndicatorView 的 封装

AVLoadingIndicatorView 是非常炫酷的加载动画,使用起来也非常方法。今天对他进行一个封装。


1,添加依赖


//Loading 依赖
api 'com.wang.avi:library:2.1.3'


2, 设置一些加载的样式,这些在 github 上面都可以找到


public enum  LoaderStyle {
    /**
     *  加载样式
     */
    BallPulseIndicator,
    BallGridPulseIndicator,
    BallClipRotateIndicator,
    BallClipRotatePulseIndicator,
    SquareSpinIndicator,
    BallClipRotateMultipleIndicator,
    BallPulseRiseIndicator,
    BallRotateIndicator,
    CubeTransitionIndicator,
    BallZigZagIndicator,
    BallZigZagDeflectIndicator,
    BallTrianglePathIndicator,
    BallScaleIndicator,
    LineScaleIndicator,
    LineScalePartyIndicator,
    BallPulseSyncIndicator,
    BallBeatIndicator,
    LineScalePulseOutIndicator,
    LineScalePulseOutRapidIndicator,
    BallScaleRippleIndicator,
    BallScaleRippleMultipleIndicator,
    BallSpinFadeLoaderIndicator,
    LineSpinFadeLoaderIndicator,
    TriangleSkewSpinIndicator,
    PacmanIndicator,
    BallGridBeatIndicator,
    SemiCircleSpinIndicator
}


3, 通过反射获取到 需要使用 加载动画


public class LoaderCreator {
    //进行缓存
    private static final WeakHashMap<String,Indicator> LOADING_MAP = new WeakHashMap<>();
    static AVLoadingIndicatorView creawte(String type, Context context){
        final AVLoadingIndicatorView avLoadingIndicatorView = new AVLoadingIndicatorView(context);
        if (LOADING_MAP.get(type) == null){
            //根据传入的 type 进行反射 获取动画 
            final Indicator indicator = getIndicator(type);
            LOADING_MAP.put(type,indicator);
        }
        //设置 这个动画
        avLoadingIndicatorView.setIndicator(LOADING_MAP.get(type));
        return avLoadingIndicatorView;
    }
    private static Indicator getIndicator(String name){
        if (name == null || name.isEmpty()){
            return null;
        }
        final StringBuilder drawbleClassName = new StringBuilder();
        //如果类名不包含 . 就说明传入的是一个 整个的类名,否则就是包名
        if (!name.contains(".")){
            // 拼装一个完整的路径,这个路径就是 动画类所在的位置。
            final String defultPackageName = AVLoadingIndicatorView.class.getPackage().getName();
            drawbleClassName.append(defultPackageName)
                    .append(".indicators")
                    .append(".");
        }
        drawbleClassName.append(name);
        try {
            //通过反射 拿到给定的类
            final Class<?> drawableClass = Class.forName(drawbleClassName.toString());
            //创建 该对象并返回
            return (Indicator) drawableClass.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}


4,设置样式。我们要将loading 显示在 dialog 上面,在style.xml 中添加如下代码:


<resources>
    <style name="dialog" parent="@android:style/Theme.Dialog">
        <!--去掉边框-->
        <item name="android:windowFrame">@null</item>
        <!--悬浮-->
        <item name="android:windowIsFloating">true</item>
        <!--半透明-->
        <item name="android:windowIsTranslucent">false</item>
        <!--不需要标题-->
        <item name="android:windowNoTitle">true</item>
        <!--背景透明-->
        <item name="android:windowBackground">@android:color/transparent</item>
        <!--允许模糊-->
        <item name="android:backgroundDimEnabled">true</item>
        <!--全屏幕-->
        <item name="android:windowFullscreen">true</item>
    </style>
</resources>


5,创建 一个测量的类。用于适应屏幕


public class DimenUtil {
    /**
     * @return 可用显示大小的绝对宽度(以像素为单位)
     */
    public static int getScreenWidth(){
        //这里的 getAppContext 是获取Context
        final Resources resources = Coke.getAppContext().getResources();
        final DisplayMetrics dm = resources.getDisplayMetrics();
        return dm.widthPixels;
    }
    /**
     * @return 可用显示大小的绝对高度(以像素为单位)
     */
    public static int getScreenHeight(){
        final Resources resources = Coke.getAppContext().getResources();
        final DisplayMetrics dm = resources.getDisplayMetrics();
        return dm.heightPixels;
    }
}


5, 最后一步,设置 AVLoading


public class CokeLoading {
    //缩放比,让load根据屏幕的大小 来调整大小。
    private static final int LOADER_SIZE_SCALE = 8;
    //屏幕的偏移量
    private static final int LOADER_OFFSET_SCALT = 10;
    private static final ArrayList<AppCompatDialog> LOADERS = new ArrayList<>();
    private static final String DEFULT_LOADER = LoaderStyle.BallClipRotatePulseIndicator.name();
    public static void showLoading(Context context, Enum<LoaderStyle> type) {
        showLoading(context, type.name());
    }
    public static void showLoading(Context context, String type) {
        // 使用 dialog 来承载 Loading .
        // 尽量 使用 v7包下的东西,这样兼容性比较好
        final AppCompatDialog dialog = new AppCompatDialog(context, R.style.dialog);
        //通过creawte方法 设置 样式 并返回对象
        final AVLoadingIndicatorView avLoadingIndicatorView = LoaderCreator.creawte(type, context);
        dialog.setContentView(avLoadingIndicatorView);
        int deviceWidth = DimenUtil.getScreenWidth();
        int deviceHeight = DimenUtil.getScreenHeight();
        final Window dialogWindow = dialog.getWindow();
        if (dialogWindow != null) {
            //设置 dialog 的属性
            final WindowManager.LayoutParams lp = dialogWindow.getAttributes();
            lp.alpha = 0.4f;
            lp.width = deviceWidth / LOADER_SIZE_SCALE;
            lp.height = deviceHeight / LOADER_SIZE_SCALE;
            //偏移量,会将上面的 height 个给覆盖掉
            lp.height = lp.height + deviceHeight / LOADER_OFFSET_SCALT;
            lp.gravity = Gravity.CENTER;
        }
        LOADERS.add(dialog);
        dialog.show();
    }
    public static void showLoading(Context context) {
         //自定义 一个默认的 加载动画
        showLoading(context, DEFULT_LOADER);
    }
    public static void stopLoading() {
        for (AppCompatDialog dialog : LOADERS) {
            if (dialog != null) {
                if (dialog.isShowing()) {
                    //  dismiss() 只是单纯的消失掉 dialog 而 cancel 会有一些回调,所以使用cancel
                    dialog.cancel();
                }
            }
        }
    }
}


7,使用如下:


//使用 指定的动画
CokeLoading.showLoading(getContext(),LoaderStyle.SemiCircleSpinIndicator);
//使用默认的
CokeLoading.showLoading(getContext());
//关闭如下
 CokeLoading.stopLoading();


效果如下:


0a2653c851af460fa595bd959398a8f1.png

2d65d23f6d4748949b924e4057485923.png


到这里就已经封装完成了。是不是使用起来非常 方便呢。赶紧试一试吧


相关文章
|
6月前
|
JavaScript API
接口的封装
接口的封装
|
存储 Cloud Native 安全
C++ 封装成库
C++ 封装成库
|
Java 数据挖掘 数据库
封装的理解
封装的理解
100 0
|
2月前
|
数据安全/隐私保护 C语言 C++
C++(七)封装
本文档详细介绍了C++封装的概念及其应用。封装通过权限控制对外提供接口并隐藏内部数据,增强代码的安全性和可维护性。文档首先解释了`class`中的权限修饰符(`public`、`private`、`protected`)的作用,并通过示例展示了如何使用封装实现栈结构。接着介绍了构造器和析构器的使用方法,包括初始化列表的引入以及它们在内存管理和对象生命周期中的重要性。最后,通过分文件编程的方式展示了如何将类定义和实现分离,提高代码的模块化和复用性。
|
5月前
什么是封装?为什么是要封装?
什么是封装?为什么是要封装?
117 0
|
6月前
|
安全 C#
C#封装详解
C#封装详解
62 0
|
6月前
|
安全 数据安全/隐私保护
什么是封装?
什么是封装?
33 0
|
6月前
|
测试技术 API
(接口封装)
(接口封装)
87 0
|
程序员
封装(了解一下)
封装(了解一下)
91 0