一.无图无真相
二.主要代码
1.简单布局
a.主布局 activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#ff0000"
android:gravity="center"
android:text="加载效果演示"
android:textColor="#ffffff"
android:textSize="18sp" />
<ListView
android:id="@+id/listView1"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" >
</ListView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="showLoadSuccess"
android:text="加载成功" />
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="showLoadError"
android:text="加载失败" />
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="showLoadEmpty"
android:text="没有数据" />
</LinearLayout>
</LinearLayout>
b.加载中布局 load_loading.xml
<?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:gravity="center"
android:background="#5555"
android:orientation="vertical" >
<ProgressBar
android:id="@+id/progressBar1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="正在加载中..." />
</LinearLayout>
c.加载失败和没有数据简单布局 load_empty.xml
<?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="#eee"
android:gravity="center"
android:orientation="vertical" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="暂无数据" />
<Button
android:id="@+id/button1"
android:layout_width="80dp"
android:layout_height="40dp"
android:layout_marginTop="12dp"
android:text="点击重试" />
</LinearLayout>
2.主要代码
a.定义接口 ViewCallBack
package com.gulang.commonloadview;
import android.content.Context;
import android.view.View;
/**
* 定义实现接口
*
* @author 孤狼
* @since 2015-8-4
*/
public interface ViewCallBack {
// 获取当前布局
public abstract View getCurrentLayout();
// 重置布局
public abstract void resetView();
// 显示布局
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();
}
b(1).添加要加载的布局 ViewGroupLayout
package com.gulang.commonloadview;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* 添加布局
* 实现思想:获取要显示区域的父布局,添加要显示的布局,只需要在代码中控制显示即可
* @author 孤狼
* @since 2015-8-4
*/
public class ViewGroupLayout implements ViewCallBack {
private View view;
private ViewGroup parentView;
private int viewIndex;
private ViewGroup.LayoutParams params;
private View currentView;
public ViewGroupLayout(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 resetView() {
showLayout(view);
}
@Override
public void showLayout(View view) {
if (parentView == null) {
init();
}
this.currentView = 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;
}
}
b(2).第二种方式,添加布局
package com.gulang.commonloadview;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.FrameLayout;
/**
* 添加布局界面
*
* @author 孤狼
* @since 2015-8-4
*/
public class ViewFrameLayout implements ViewCallBack {
private ViewCallBack helper;
private View view;
public ViewFrameLayout(View view) {
super();
this.view = view;
ViewGroup group = (ViewGroup) view.getParent();
LayoutParams layoutParams = view.getLayoutParams();
FrameLayout frameLayout = new FrameLayout(view.getContext());
group.removeView(view);
group.addView(frameLayout, layoutParams);
LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
View floatView = new View(view.getContext());
frameLayout.addView(view, params);
frameLayout.addView(floatView, params);
helper = new ViewGroupLayout(floatView);
}
@Override
public View getCurrentLayout() {
return helper.getCurrentLayout();
}
@Override
public void resetView() {
helper.resetView();
}
@Override
public void showLayout(View view) {
helper.showLayout(view);
}
@Override
public void showLayout(int layoutId) {
showLayout(inflate(layoutId));
}
@Override
public View inflate(int layoutId) {
return helper.inflate(layoutId);
}
@Override
public Context getContext() {
return helper.getContext();
}
@Override
public View getView() {
return view;
}
}
c.自定义显示工具类(可根据具体要求自己实现,此处简单实现)
package com.gulang.commonloadview;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import com.gulang.app.R;
/**
* 自定义布局,随意替换
*
* @author 孤狼
* @since 2015-8-4
*/
public class LoadViewHelper {
private ViewCallBack helper;
// 构造函数
public LoadViewHelper(View view) {
this(new ViewGroupLayout(view));
}
// 构造函数
public LoadViewHelper(ViewCallBack helper) {
super();
this.helper = helper;
}
// 加载错误
public void showError(String errorText, String buttonText,
OnClickListener onClickListener) {
View layout = helper.inflate(R.layout.load_error);
TextView textView = (TextView) layout.findViewById(R.id.textView1);
textView.setText(errorText);
Button button = (Button) layout.findViewById(R.id.button1);
button.setText(buttonText);
button.setOnClickListener(onClickListener);
helper.showLayout(layout);
}
// 数据为空
public void showEmpty(String errorText, String buttonText,
OnClickListener onClickListener) {
View layout = helper.inflate(R.layout.load_empty);
TextView textView = (TextView) layout.findViewById(R.id.textView1);
textView.setText(errorText);
Button button = (Button) layout.findViewById(R.id.button1);
button.setText(buttonText);
button.setOnClickListener(onClickListener);
helper.showLayout(layout);
}
// 正在加载中
public void showLoading(String loadText) {
View layout = helper.inflate(R.layout.load_loading);
TextView textView = (TextView) layout.findViewById(R.id.textView1);
textView.setText(loadText);
helper.showLayout(layout);
}
public void restore() {
helper.resetView();
}
}
d.代码中调用MainActivity.java
package com.gulang.app;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import com.gulang.commonloadview.LoadViewHelper;
/**
* 简单演示,具体逻辑请根据开发需求
*
* @author 孤狼
* @since 2015-8-4
*/
public class MainActivity extends Activity {
private ListView listView;
private LoadDataTask task;
private LoadViewHelper helper;
private ArrayAdapter<String> adapter;
private List<String> data = new ArrayList<String>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.listView1);
//创建要加载的效果,关联要显示的父布局
helper = new LoadViewHelper(listView);
listView.setAdapter(adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, data));
task = new LoadDataTask(3);
task.execute();
}
@Override
protected void onDestroy() {
super.onDestroy();
if (task != null) {
task.cancel(true);
}
}
// 加载失败
public void showLoadError(View view) {
if (task != null) {
task.cancel(true);
}
task = new LoadDataTask(1);
task.execute();
}
// 数据为空
public void showLoadEmpty(View view) {
if (task != null) {
task.cancel(true);
}
task = new LoadDataTask(2);
task.execute();
}
// 加载成功
public void showLoadSuccess(View view) {
if (task != null) {
task.cancel(true);
}
task = new LoadDataTask(3);
task.execute();
}
private class LoadDataTask extends AsyncTask<Void, Void, List<String>> {
private int type;
public LoadDataTask(int type) {
super();
this.type = type;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
helper.showLoading("加载中...");
}
@Override
protected List<String> doInBackground(Void... params) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (type == 1) {
return null;
} else if (type == 2) {
return new ArrayList<String>(0);
}
List<String> strings = new ArrayList<String>();
for (int i = 0; i < 50; i++) {
strings.add("通用加载效果测试" + i);
}
return strings;
}
@Override
protected void onPostExecute(List<String> result) {
super.onPostExecute(result);
if (result == null) {
helper.showError("加载失败", "重试", new OnClickListener() {
@Override
public void onClick(View v) {
task = new LoadDataTask(1);
task.execute();
}
});
} else if (result.isEmpty()) {
helper.showEmpty("暂无数据", "重试", new OnClickListener() {
@Override
public void onClick(View v) {
task = new LoadDataTask(2);
task.execute();
}
});
} else {
data.clear();
data.addAll(result);
helper.restore();
adapter.notifyDataSetChanged();
}
}
}
}
三.说明
废话不多说,代码比较简单,完全实现具体的自定义布局只需要修改LoadViewHelper 中加载显示的view即可
四.源码下载
加载效果Demo