美文网首页ViewandroidAndroid
一个通用的加载帮助类,Loading如此舒服

一个通用的加载帮助类,Loading如此舒服

作者: 阿敏其人 | 来源:发表于2016-06-18 22:39 被阅读2382次

    本文出自 “阿敏其人” 简书博客,转载或引用请注明出处。

    首先,感谢github两位同学的分享精神
    XHLoadingView
    LoadViewHelper
    借这两位的代码,做了一个稍微提取成为了一个mudule,可直接引入代码使用。大家学习可以连接加星,为开源点赞。

    一、你好,Loading

    我们加载Listview等,往往需要耗时几秒,这和等待过程加上一些交互效果自然会让人感觉输入一些,常见的转圈圈自不必说,但是按照通常的想法,我们往往是加xml里面的view通过隐藏和现实来实现,这种方式实在不太方便,现在实现了一个ViewLoadHelp,直接通过构造构造方法传入待loading的View,方便快捷。

    先上gif图:


    通用loading展示图.gif Paste_Image.png

    在loading的时候,大概可以分为几种情况
    1、正在loading
    2、load的时候发现异常
    这个异常不论是服务器的,还是网络,还是其他,在这里我们都归为load异常,后面我们可以根据不同的异常显示不同的提示图片和提示语
    3、load后无数据
    4、load完成,成功得到数据并且展示数据

    根据这几种情况,我们的LoadViewHelp就可以写上对应的方法。

    二、使用方式

    第一步:

    private LoadHelpView mLoadHelpView;
    

    第二步,指定LoadHelpView要load替换的View

    mLoadHelpView = new LoadHelpView(mTvShow);
    

    第三步:
    该怎么load,该空数据,该网络异常,你看着办

    怎么显示loading

    mLoadHelpView.showLoading("正在为您拼命加载");
    

    怎么显示异常:

    mLoadHelpView.showError("您的网络怎么了?", "再试一下", R.drawable.load_error,new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            testNetError();
                        }
                    });
    

    嫌传入的东西太长?那么我们就传一个短一点的:

    mLoadHelpView.showError(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            testNetError();
                        }
                    });
    

    去掉load页面

    mLoadHelpView.dismiss();
    

    三、代码简介

    下图是我们抽取出来的依赖module

    Paste_Image.png

    可以看到,代码非常简单,一个主要的LoadHelpView,另外一个IReplaceViewHelper接口,然后我们根据这个接口产生了一个实现类,大家可以自己写上自己合适的实现类。

    接下看一下代码:

    LoadHelpView

    /**
     * 自定义要切换的布局,通过IVaryViewHelper实现真正的切换<br>
     * 使用者可以根据自己的需求,使用自己定义的布局样式
     */
    public class LoadHelpView {
    
        private IReplaceViewHelper helper;
        private AnimationDrawable animationDrawable;
    
        public LoadHelpView(View view) {
            this(new ReplaceViewHelper(view));
        }
    
        public LoadHelpView(IReplaceViewHelper helper) {
            super();
            this.helper = helper;
        }
    
        // 数据异常
        public void showError(String errorText, String buttonText, int picResId,OnClickListener onClickListener) {
            View layout = helper.inflate(R.layout.load_error);
            // 设置图片
            ImageView mIvShowPic = (ImageView) layout.findViewById(R.id.mIvShowPic);
            mIvShowPic.setBackgroundResource(picResId);
            // 设置提示文字
            TextView mTvTip = (TextView) layout.findViewById(R.id.mTvTip);
            mTvTip.setText(errorText);
    
            // 设置按钮
            TextView mTvBtn = (TextView) layout.findViewById(R.id.mTvBtn);
            mTvBtn.setText(buttonText);
            mTvBtn.setOnClickListener(onClickListener);
    
            helper.showLayout(layout);
        }
    
        // 数据异常简易版
        public void showError(OnClickListener onClickListener) {
            View layout = helper.inflate(R.layout.load_error);
            TextView mTvBtn = (TextView) layout.findViewById(R.id.mTvBtn);
            mTvBtn.setOnClickListener(onClickListener);
            helper.showLayout(layout);
        }
    
    
        // 空数据
        public void showEmpty(String errorText, String buttonText, int picResId,OnClickListener onClickListener) {
            View layout = helper.inflate(R.layout.load_empty);
    
            ImageView mIvShowPic = (ImageView) layout.findViewById(R.id.mIvShowPic);
            mIvShowPic.setBackgroundResource(picResId);
    
            TextView mTvTip = (TextView) layout.findViewById(R.id.mTvTip);
            mTvTip.setText(errorText);
    
            TextView mTvBtn = (TextView) layout.findViewById(R.id.mTvBtn);
            mTvBtn.setText(buttonText);
            mTvBtn.setOnClickListener(onClickListener);
    
            helper.showLayout(layout);
        }
    
        // 空数据简易版
        public void showEmpty(OnClickListener onClickListener) {
            View layout = helper.inflate(R.layout.load_empty);
            TextView mTvBtn = (TextView) layout.findViewById(R.id.mTvBtn);
            mTvBtn.setOnClickListener(onClickListener);
            helper.showLayout(layout);
        }
    
        // 正在加载
        public void showLoading(String loadText) {
            View layout = helper.inflate(R.layout.load_ing);
            TextView mTvTip = (TextView) layout.findViewById(R.id.mTvTip);
            ImageView mIvAnim = (ImageView) layout.findViewById(R.id.mIvAnim);
            mIvAnim.setImageResource(R.drawable.loading_animation);
            animationDrawable = (AnimationDrawable) mIvAnim.getDrawable();
            animationDrawable.start(); // 开启帧动画
            mTvTip.setText(loadText);
            helper.showLayout(layout);
        }
    
        public void dismiss() {
            helper.dismissView();
        }
    }
    
    

    .
    .

    关键接口 IReplaceViewHelper

    public interface IReplaceViewHelper {
    
        public abstract View getCurrentLayout();
    
        public abstract void dismissView();
    
        public abstract void showLayout(View view);
    
        public abstract void showLayout(int layoutId);
    
        public abstract View inflate(int layoutId);
    
        public abstract Context getContext();
    
        public abstract View getView();
    
    }
    

    .
    .
    参考实现类 ReplaceViewHelper

    /**
     * 用于切换布局,用一个新的布局替换掉原先的布局
     * 
     *
     *
     */
    public class ReplaceViewHelper implements IReplaceViewHelper {
        private View view;
        private ViewGroup parentView;
        private int viewIndex;
        private ViewGroup.LayoutParams params;
        private View currentView;
    
        public ReplaceViewHelper(View view) {
            super();
            this.view = view;
        }
    
        private void init() {
            params = view.getLayoutParams();
            if (view.getParent() != null) {
                parentView = (ViewGroup) view.getParent();
            } else {
                parentView = (ViewGroup) view.getRootView().findViewById(android.R.id.content);
            }
            int count = parentView.getChildCount();
            for (int index = 0; index < count; index++) {
                if (view == parentView.getChildAt(index)) {
                    viewIndex = index;
                    break;
                }
            }
            currentView = view;
        }
    
        @Override
        public View getCurrentLayout() {
            return currentView;
        }
    
        @Override
        public void dismissView() {
            showLayout(view);
        }
    
        @Override
        public void showLayout(View view) {
            if (parentView == null) {
                init();
            }
            this.currentView = view;
            // 如果已经是那个view,那就不需要再进行替换操作了
            if (parentView.getChildAt(viewIndex) != view) {
                ViewGroup parent = (ViewGroup) view.getParent();
                if (parent != null) {
                    parent.removeView(view);
                }
                parentView.removeViewAt(viewIndex);
                parentView.addView(view, viewIndex, params);
            }
        }
    
        @Override
        public void showLayout(int layoutId) {
            showLayout(inflate(layoutId));
        }
    
        @Override
        public View inflate(int layoutId) {
            return LayoutInflater.from(view.getContext()).inflate(layoutId, null);
        }
    
        @Override
        public Context getContext() {
            return view.getContext();
        }
    
        @Override
        public View getView() {
            return view;
        }
    }
    
    

    通过来加载器LayoutInflater和LayoutParams,我们就可以进行View的替换展示。

    以上是mudule库的主要代码
    下面是主工程的引用后的实例代码

    MainActivity

    public class MainActivity extends Activity implements View.OnClickListener {
    
        private TextView mTvLoad;
        private TextView mTvNetError;
        private TextView mTvNoData;
        private TextView mTvLoadSuccess;
        private Intent intent;
    
        public static int LOAD = 1;
        public static int NET_ERROR = 2;
        public static int NO_DATA = 3;
        public static int SUCEESS = 4;
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            intent = new Intent(MainActivity.this, TestActivity.class);
            mTvLoad = (TextView) findViewById(R.id.mTvLoad);
            mTvNetError = (TextView) findViewById(R.id.mTvNetError);
            mTvNoData = (TextView) findViewById(R.id.mTvNoData);
            mTvLoadSuccess = (TextView) findViewById(R.id.mTvLoadSuccess);
    
            mTvLoad.setOnClickListener(this);
            mTvNetError.setOnClickListener(this);
            mTvNoData.setOnClickListener(this);
            mTvLoadSuccess.setOnClickListener(this);
    
    
        }
    
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.mTvLoad:
                    intent.putExtra("TYPE", LOAD);
                    startActivity(intent);
                    break;
    
                case R.id.mTvNetError:
                    intent.putExtra("TYPE", NET_ERROR);
                    startActivity(intent);
                    break;
    
                case R.id.mTvNoData:
                    intent.putExtra("TYPE", NO_DATA);
                    startActivity(intent);
                    break;
    
                case R.id.mTvLoadSuccess:
                    intent.putExtra("TYPE", SUCEESS);
                    startActivity(intent);
                    break;
            }
        }
    }
    
    

    .
    .
    TestActivity

    public class TestActivity extends Activity{
    
    
        private TextView mTv;
        private TextView mTvShow;
        private LoadHelpView mLoadHelpView;
        private Intent mIntent;
        private int mType;
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_test);
    
            mTv = (TextView) findViewById(R.id.mTv);
            mTvShow = (TextView) findViewById(R.id.mTvShow);
            mLoadHelpView = new LoadHelpView(mTvShow);
    
            mIntent = getIntent();
            mType = mIntent.getIntExtra("TYPE", -1);
    
            mTv.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if(mType == MainActivity.LOAD){
                        mLoadHelpView.showLoading("正在为您拼命加载");
                    }else if(mType == MainActivity.NET_ERROR){
                        testNetError();
                    }else if(mType == MainActivity.NO_DATA){
                        testNoData();
                    }else if(mType == MainActivity.SUCEESS){
                        testSuccess();
                    }
                }
            });
    
        }
    
        private void testNetError(){
            mLoadHelpView.showLoading("正在为您拼命加载");
            new Handler().postDelayed(new Runnable(){
                public void run() {
                    /*mLoadHelpView.showError("您的网络怎么了?", "再试一下", R.drawable.load_error,new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            testNetError();
                        }
                    });*/
    
    
                    mLoadHelpView.showError(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            testNetError();
                        }
                    });
                }
            }, 1200);
        }
    
        private void testNoData(){
            mLoadHelpView.showLoading("正在为您拼命加载");
            new Handler().postDelayed(new Runnable(){
                public void run() {
                    /*mLoadHelpView.showEmpty("暂无数据,快去录入新数据吧", "再试一下", R.drawable.load_no_data,new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            testNetError();
                        }
                    });*/
    
    
                    mLoadHelpView.showEmpty(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            testNetError();
                        }
                    });
                }
            }, 1200);
        }
    
        private void testSuccess(){
            mLoadHelpView.showLoading("正在为您拼命加载");
            new Handler().postDelayed(new Runnable(){
                public void run() {
                    mLoadHelpView.dismiss();
                    mTvShow.setText("成功加载数据,展示数据");
                }
            }, 1200);
        }
    }
    
    

    再来看一下TestActivity的xml,我们看到我们无需在xml里面做替换View的隐藏和显示。

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent"
                  android:background="#66000000"
                  android:orientation="vertical"
        >
    
        <TextView
            android:id="@+id/mTv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:layout_marginTop="30dp"
            android:background="#66ff0000"
            android:padding="10dp"
            android:text="加载数据"
            android:textSize="20dp"
            />
    
        <TextView
            android:id="@+id/mTvShow"
            android:layout_width="300dp"
            android:layout_height="300dp"
            android:layout_gravity="center_horizontal"
            android:layout_marginTop="20dp"
            android:background="#660000ff"
            android:gravity="center"
            />
    </LinearLayout>
    

    该有的应该都有了,其实借此代码,还可以好好感受一下的android的类加载器。

    下载链接
    本篇完。

    相关文章

      网友评论

      • android_cyw:在实际的使用过程中,各种提示view的切换(如无网络切换到无数据)瞬间会触发下层内容view的点击事件
        阿敏其人:@ce5236592dc0 没有啊,自己处理下里
        android_cyw:@阿敏其人 有好的推荐吗?
        阿敏其人:@ce5236592dc0 我现在没用这个也,不好意思噢
      • sspuerh:findViewById如果在showLoading()之后就会报空指针了?这要怎么解决?
        阿敏其人:不行,你是隐藏显示的有一一定的调整是吧。你的view不方便调整,help可以调整啊。
        sspuerh:@阿敏其人 可以在代码兼容?现在是如果正确视图里面有个控件在加载完后findViewById会null
        阿敏其人:@38cb2c0f3f84 调整位置
      • 捡淑:马克
      • 绿衣拂袖:看不懂

      • 3ff012179d09:我想学这些东西,可是什么都不懂怎么开始学?
      • 牛晓伟:还可以写的扩展性更好些,比如使用者可以替换加载失败的样式,或者加载中的样式。
        李简书:@牛晓伟 如果里面没有按钮还好添加,自己改一下就好,如果有按钮,还是自己改一下loadview比较简单

      本文标题:一个通用的加载帮助类,Loading如此舒服

      本文链接:https://www.haomeiwen.com/subject/vkkbdttx.html