加载动画及占位图 EmptyLayout

前言

在android开发中,对于网络加载、本地数据加载等耗时任务时,为了更好的用户体验,会先给用户展示一些等待图或者动画一类的占位图。对于列表更是需要处理空数据等其他异常情况。本篇的主角 EmptyLayout 就是由此而生。 借鉴:oschina

先上效果

EmptyLayout演示

直接上代码

代码位置

emptylayout代码位置

EmptyLayout.java

该控件主要是setErrorType方法,控制显示类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
public class EmptyLayout extends LinearLayout implements
View.OnClickListener {

public static final int NETWORK_ERROR = 1; // 网络异常
public static final int NETWORK_LOADING = 2;//加载中
public static final int NODATA = 3;//暂无数据
public static final int HIDE_LAYOUT = 4;//隐藏该控件
public static final int NO_LOGIN = 5;//未登录

private Loading mLoading;
private boolean clickEnable = true;
private final Context context;
public ImageView img;
private int mErrorState;
private String strNoDataContent = "";
private TextView tv;
private boolean mLoadingLocalFriend;

private OnViewClick listener;

public EmptyLayout(Context context) {
super(context);
this.context = context;
init();
}

public EmptyLayout(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
init();
}

private void init() {
View view = LayoutInflater.from(getContext()).inflate(R.layout.widget_empty_layout, this, false);
img = (ImageView) view.findViewById(R.id.img_error_layout);
tv = (TextView) view.findViewById(R.id.tv_error_layout);
mLoading = (Loading) view.findViewById(R.id.animProgress);
setBackgroundColor(-1);
setOnClickListener(this);
img.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
if (clickEnable && mErrorState != NETWORK_LOADING) {
if (listener != null)
listener.onViewClick(v);
}
}
});
addView(view);
}

public void dismiss() {
mErrorState = HIDE_LAYOUT;
setVisibility(View.GONE);
}

public int getErrorState() {
return mErrorState;
}

public boolean isLoadError() {
return mErrorState == NETWORK_ERROR;
}

public boolean isLoading() {
return mErrorState == NETWORK_LOADING;
}

@Override
public void onClick(View v) {
if (clickEnable && mErrorState != NETWORK_LOADING) {
if (listener != null)
listener.onViewClick(v);
}
}

/**
* 修改提示文本
*
* @param msg
*/
public void setErrorMessage(String msg) {
tv.setText(msg);
}

/**
* 修改提示文本
*
* @param loadingLocalFriend
*/
public void setLoadingLocalFriend(boolean loadingLocalFriend) {
this.mLoadingLocalFriend = loadingLocalFriend;
tv.setText(R.string.error_view_loading_local_friend);
}

/**
* 修改显示图片
*
* @param imgResource
*/
public void setErrorImg(int imgResource) {
try {
img.setImageResource(imgResource);
} catch (Exception e) {
}
}

/**
* 修改显示类型
*
* @param i
*/
public void setErrorType(int i) {
if (HIDE_LAYOUT == i && HIDE_LAYOUT == mErrorState) {
return;
}

setVisibility(View.VISIBLE);
switch (i) {
case NETWORK_ERROR:
mErrorState = NETWORK_ERROR;
if (TDevice.hasInternet(context)) {
tv.setText(R.string.error_view_load_error_click_to_refresh);
img.setBackgroundResource(R.drawable.page_tip_fail);
} else {
tv.setText(R.string.tip_network_error);
img.setBackgroundResource(R.drawable.page_tip_network);
}
img.setVisibility(View.VISIBLE);
mLoading.stop();
mLoading.setVisibility(View.GONE);
clickEnable = true;
break;
case NETWORK_LOADING:
mErrorState = NETWORK_LOADING;
mLoading.setVisibility(View.VISIBLE);
mLoading.start();
img.setVisibility(View.GONE);
if (mLoadingLocalFriend) {
tv.setText(R.string.error_view_loading_local_friend);
} else {
tv.setText(R.string.error_view_loading);
}
clickEnable = false;
break;
case NODATA:
mErrorState = NODATA;
img.setBackgroundResource(R.drawable.page_icon_empty);
img.setVisibility(View.VISIBLE);
mLoading.stop();
mLoading.setVisibility(View.GONE);
setTvNoDataContent();
clickEnable = true;
break;
case HIDE_LAYOUT:
mLoading.stop();
setVisibility(View.GONE);
break;
default:
break;
}
}

public void setNoDataContent(String noDataContent) {
strNoDataContent = noDataContent;
}

public void setOnLayoutClickListener(OnViewClick listener) {
this.listener = listener;
}

public void setTvNoDataContent() {
if (!strNoDataContent.equals(""))
tv.setText(strNoDataContent);
else
tv.setText(R.string.error_view_no_data);
}

@Override
public void setVisibility(int visibility) {
if (visibility == View.GONE)
mErrorState = HIDE_LAYOUT;
super.setVisibility(visibility);
}

public static interface OnViewClick {
void onViewClick(View v);
}
}

layout widget_empty_layout.xml

其中Loading为加载动画,也可用ProgressBar替换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layout_error"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFF"
android:gravity="center"
android:orientation="vertical">

<ImageView
android:id="@+id/img_error_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/page_tip_network"
android:visibility="gone"
tools:visibility="visible" />

<com.nhtzj.learnapplication.widget.loading.Loading
android:id="@+id/animProgress"
android:layout_width="26dip"
android:layout_height="26dip" />

<TextView
android:id="@+id/tv_error_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10.0dip"
android:gravity="center"
android:lines="2"
android:text="@string/error_view_loading"
android:textColor="@color/txt_color_gray"
android:textSize="@dimen/sp_14" />

</LinearLayout>

values

1
2
3
4
5
6
7
8
9
10
11
12
<string name="error_view_no_data">暂无内容</string>
<string name="error_view_loading">加载中…</string>
<string name="error_view_loading_local_friend">获取附近的程序员中…</string>
<string name="error_view_load_error_click_to_refresh">内容加载失败\r\n点击重新加载</string>
<string name="tip_network_error">没有可用的网络</string>
<string name="loading">加载中…</string>


<dimen name="g_loading_lineSize">2dp</dimen>
<dimen name="g_loading_minSize">28dp</dimen>
<dimen name="g_loading_maxSize">40dp</dimen>
<dimen name="sp_14">14sp</dimen>

源码下载

海的那边 / learn

坚持原创技术分享,您的支持是对我最大的鼓励!