Android 自定义一款炫酷的加载控件

概述:

在设计应用的时候,我们应该热爱极简主义,简单就是好的,对于很多用户来说,复杂的东西并不受欢迎。
我要实现的是根据不同的情况去显示不同的加载效果,随用随调,效果是借鉴于某一项目的效果,我认为有必要提取出来改善封装一下,供以后使用。情况大致分为:加载中、无网络、无数据、加载失败等;

预览下效果图

这里写图片描述

我们怎么实现这种效果呢

view_loading.xml的布局如下:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:id="@+id/lin_loading"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:visibility="gone"
        android:orientation="vertical">

        <ImageView
            android:id="@+id/img_loading"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:src="@drawable/loading_animation" />

        <TextView
            android:id="@+id/tv_loading"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:layout_gravity="center_horizontal"
            android:textSize="14sp" />

    </LinearLayout>


    <LinearLayout
        android:id="@+id/lin_load"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:gravity="center"
        android:orientation="vertical"
        android:visibility="visible"

        >

        <ImageView
            android:id="@+id/iv_load"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:src="@mipmap/ic_launcher" />

        <TextView
            android:id="@+id/tv_load"
            android:layout_width="wrap_content"
            android:layout_gravity="center_horizontal"
            android:layout_height="wrap_content" />


        <Button
            android:id="@+id/btn_load"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="8dp"
            android:layout_gravity="center_horizontal"
            android:textSize="14sp" />

    </LinearLayout>

</FrameLayout>

从布局来看,我分了两个部分,一个是加载中,另外一个是带有ImagView、文字和按钮的布局,有人看到这,就会说,哇靠,这不是很简单吗?根据不同的情况去设置Visibility的值就好了啊,没错,原理就是这样。

XHLoadingView.java的代码如下:

package com.woyou.loadingdemo.widget;

import android.content.Context;
import android.graphics.drawable.AnimationDrawable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.woyou.loadingdemo.LoadingState;
import com.woyou.loadingdemo.R;


/**
 * Created by Xiho on 11:21.
 */
public class XHLoadingView extends FrameLayout {

    private Context mContext;
    // 加载中的布局
    private LinearLayout mLinearLoad;
    //其他加载的布局
    private LinearLayout mLinearLoading;

    private TextView mTvLoading;

    private TextView mTvLoad;

    private ImageView mIvLoading;

    private ImageView mIvLoad;

    private Button mBtnLoad;

    private LoadingState mState;

    private AnimationDrawable animation;


    public XHLoadingView(Context context) {
        super(context);
        mContext = context;
    }

    public XHLoadingView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
    }

    public XHLoadingView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
    }

    public XHLoadingView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        mContext = context;

    }
    public void build(){
        LayoutInflater.from(mContext).inflate(R.layout.view_loading, this, true);

        mLinearLoading = (LinearLayout) findViewById(R.id.lin_loading);

        mLinearLoad = (LinearLayout) findViewById(R.id.lin_load);

        mIvLoading = (ImageView) findViewById(R.id.img_loading);

        mIvLoad = (ImageView) findViewById(R.id.iv_load);

        mTvLoading = (TextView) findViewById(R.id.tv_loading);

        mTvLoad = (TextView) findViewById(R.id.tv_load);

        mBtnLoad = (Button) findViewById(R.id.btn_load);

        mBtnLoad.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                setState(LoadingState.STATE_LOADING);
                mOnRetryListener.onRetry();
            }
        });

    }


    @Override
    public void setVisibility(int visibility) {
        super.setVisibility(visibility);
        if(View.GONE==visibility && mState==LoadingState.STATE_LOADING && animation!=null&&animation.isRunning()){
            animation.stop();
        }
    }

    /**
     * 加载中提示文字
     */
    private String mLoadingText;
    private int mLoadingIcon;
    public XHLoadingView withLoadingIcon(int resId){
        mLoadingIcon = resId;
        return this;
    }

    /**
     * 加载数据为空提示文字
     */
    private String mLoadEmptyText;
    private int mLoadEmptyIcon;
    public XHLoadingView withEmptyIcon(int resId){
        mLoadEmptyIcon = resId;
        return this;
    }

    /**
     * 无网络提示
     */
    private String mLoadNoNetworkText;
    private int mNoNetworkIcon;
    public XHLoadingView withNoNetIcon(int resId){
        mNoNetworkIcon = resId;
        return this;
    }

    private OnRetryListener mOnRetryListener;

    /**
     * 定义重试的的接口
     */
    public interface OnRetryListener {
        void onRetry();
    }

    public XHLoadingView withOnRetryListener(OnRetryListener mOnRetryListener){
        this.mOnRetryListener = mOnRetryListener;
        return this;
    }

    /**
     *  设置加载的状态
     * @param state
     */
    public void setState(LoadingState state){
        if(mState==state){
            return;
        }else if(state==LoadingState.STATE_LOADING){
            mLinearLoading.setVisibility(VISIBLE);
            mLinearLoad.setVisibility(GONE);
        }else if(state!=LoadingState.STATE_LOADING){
            mLinearLoading.setVisibility(GONE);
            mLinearLoad.setVisibility(VISIBLE);
            if(animation!=null && mState==LoadingState.STATE_LOADING)
                animation.stop();
        }
        changeState(state);
    }


    public boolean btnEmptyEnable = true;
    public boolean btnErrorEnable = true;
    public boolean btnNoNetworkEnable = true;

    public XHLoadingView withBtnNoNetEnnable(boolean ennable) {
        btnNoNetworkEnable = ennable;
        return this;
    }

    public XHLoadingView withBtnErrorEnnable(boolean ennable) {
        btnErrorEnable = ennable;
        return this;
    }


    public XHLoadingView withBtnEmptyEnnable(boolean ennable) {
        btnEmptyEnable = ennable;
        return this;
    }

    /**
     * 改变状态
     * @param state
     */
    private void changeState(LoadingState state) {
        switch (state) {
            //加载中
            case STATE_LOADING:
                mState = LoadingState.STATE_LOADING;
                mIvLoading.setImageResource(mLoadingIcon);
                mTvLoading.setText(mLoadingText);
                if (animation == null) {
                    animation = (AnimationDrawable) mIvLoading.getDrawable();
                }
                if (animation != null)
                    animation.start();
                break;
            //数据为空
            case STATE_EMPTY:
                mState = LoadingState.STATE_EMPTY;
                mIvLoad.setImageResource(mLoadEmptyIcon);
                mTvLoad.setText(mLoadEmptyText);
                if (btnEmptyEnable) {
                    mBtnLoad.setVisibility(VISIBLE);
                    mBtnLoad.setText(btn_empty_text);
                } else {
                    mBtnLoad.setVisibility(GONE);
                }
                break;
            //加载失败
            case STATE_ERROR:
                mState = LoadingState.STATE_ERROR;
                mIvLoad.setImageResource(mErrorIco);
                mTvLoad.setText(mLoadErrorText);
                if (btnErrorEnable) {
                    mBtnLoad.setVisibility(VISIBLE);
                    mBtnLoad.setText(btn_error_text);
                } else {
                    mBtnLoad.setVisibility(GONE);
                }
                break;
            //无网络
            case STATE_NO_NET:
                mState = LoadingState.STATE_NO_NET;
                mIvLoad.setImageResource(mNoNetworkIcon);
                mTvLoad.setText(mLoadNoNetworkText);
                if (btnNoNetworkEnable) {
                    mBtnLoad.setVisibility(VISIBLE);
                    mBtnLoad.setText(btn_nonet_text);
                } else {
                    mBtnLoad.setVisibility(GONE);
                }
                break;
        }

    }


    /**
     * 后台或者本地出现错误提示
     */
    private String mLoadErrorText;
    private int mErrorIco;

    public XHLoadingView withErrorIco(int resId) {
        mErrorIco = resId;
        return this;
    }

    /**
     * 加载空数据
     * @param resId
     * @return
     */
    public XHLoadingView withLoadEmptyText(int resId) {
        mLoadEmptyText = getResources().getString(resId);
        return this;
    }

    public XHLoadingView withLoadEmptyText(String mLoadEmptyText) {
        this.mLoadEmptyText = mLoadEmptyText;
        return this;
    }

    /**
     *  无网络时候加载文字
     * @param resId
     * @return
     */
    public XHLoadingView withLoadNoNetworkText(int resId) {
        mLoadNoNetworkText = getResources().getString(resId);
        return this;
    }

    public String btn_empty_text = "重试";
    public String btn_error_text = "重试";
    public String btn_nonet_text = "重试";

    /**
     * 数据为空的Button的文字提示
     * @param text
     * @return
     */
    public XHLoadingView withBtnEmptyText(String text) {
        this.btn_empty_text = text;
        return this;
    }

    /**
     * 加载错误的Button的文字提示
     * @param text
     * @return
     */
    public XHLoadingView withBtnErrorText(String text) {
        this.btn_error_text = text;
        return this;
    }

    /**
     * 加载错误的文字提示
     * @param resId
     * @return
     */
    public XHLoadingView withLoadErrorText(int resId) {
        this.mLoadErrorText = getResources().getString(resId);
        return this;
    }
    public XHLoadingView withLoadErrorText(String mLoadedErrorText) {
        this.mLoadErrorText = mLoadedErrorText;
        return this;
    }

    /**
     * 加载无网络的Button的文字提示
     * @param text
     * @return
     */
    public XHLoadingView withBtnNoNetText(String text) {
        this.btn_nonet_text = text;
        return this;
    }

    /**
     * 加载没有网路的文字提示
     * @param mLoadedNoNetText
     * @return
     */
    public XHLoadingView withLoadNoNetworkText(String mLoadedNoNetText) {
        this.mLoadNoNetworkText = mLoadedNoNetText;
        return this;
    }

    public XHLoadingView withLoadingText(int resId) {
        this.mLoadingText = getResources().getString(resId);
        return this;
    }

    public XHLoadingView withLoadingText(String mLoadingText) {
        this.mLoadingText = mLoadingText;
        return this;
    }

}

针对不同的情况作了不同的处理,然后我们在需要的Activity调用。

    private XHLoadingView mLoadingView;
     
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_display);
        mLoadingView = (XHLoadingView) findViewById(R.id.lv_loading);
        mLoadingView.withLoadEmptyText("≥﹏≤ , 啥也木有 !").withEmptyIcon(R.drawable.disk_file_no_data).withBtnEmptyEnnable(false)
                    .withErrorIco(R.drawable.ic_chat_empty).withLoadErrorText("(῀( ˙᷄ỏ˙᷅ )῀)ᵒᵐᵍᵎᵎᵎ,我家程序猿跑路了 !").withBtnErrorText("臭狗屎!!!")
                    .withLoadNoNetworkText("你挡着信号啦o( ̄ヘ ̄o)☞ᗒᗒ 你走").withNoNetIcon(R.drawable.ic_chat_empty).withBtnNoNetText("网弄好了,重试")
                    .withLoadingIcon(R.drawable.loading_animation).withLoadingText("加载中...").withOnRetryListener(new XHLoadingView.OnRetryListener() {
                @Override
                public void onRetry() {
                    SnackbarUtil.show(mLoadingView,"已经在努力重试了",0);
                }
            }).build();
     }

........

  //加载中
      mLoadingView.setVisibility(View.VISIBLE);
      mLoadingView.setState(LoadingState.STATE_LOADING);

 //空数据
      mLoadingView.setVisibility(View.VISIBLE);
      mLoadingView.setState(LoadingState.STATE_EMPTY)
 //无网络
      mLoadingView.setVisibility(View.VISIBLE);
      mLoadingView.setState(LoadingState.STATE_NO_NET);

 //加载错误
      mLoadingView.setVisibility(View.VISIBLE);
      mLoadingView.setState(LoadingState.STATE_ERROR);

.......


   }

源码中注释详细,就不用再做过多的解释了吧!

完整代码XHLoadingView

作者:xuhao
QQ:504105930
转载请注明出处:http://blog.csdn.net/u011974987/article/details/51455333
希望您能指出宝贵意见,谢谢。

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

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,544评论 25 707
  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 13,628评论 1 92
  • 内容抽屉菜单ListViewWebViewSwitchButton按钮点赞按钮进度条TabLayout图标下拉刷新...
    皇小弟阅读 46,391评论 22 663
  • 【作者】乔冠清 【导师】刘艳 袁浩 郑鹏 【导图解说】这幅导图主要说明了藏羚羊跪拜这篇课文的主要内容是一开始老猎人...
    乔丹2005阅读 607评论 4 3
  • 面授,顾名思义,就是面对面的授课,主要就是集中在课堂里直接授课学习。相信大家对此并不陌生,九年义务教务就是这个模式...
    小范妈阅读 1,907评论 0 1