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

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

首先,感谢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的类加载器。

下载链接
本篇完。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,830评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,992评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,875评论 0 331
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,837评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,734评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,091评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,550评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,217评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,368评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,298评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,350评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,027评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,623评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,706评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,940评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,349评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,936评论 2 341

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,273评论 25 707
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,982评论 4 60
  • 不要把别人的善言善行当心灵鸡汤喝掉,或者端了去又灌给其他人喝,而是要切己体察,马上落实到自己身上。不要廉价的感动和...
    华杉2009阅读 660评论 0 0
  • “我死了之后,想必就会有答案了吧?可惜,这个答案我却看不到。” 阿炳将子弹按进了弹夹。接下来的程序,应该是把枪口对...
    说啥看心情阅读 492评论 0 2