最简单通用加载效果---完全实现自定义

一.无图无真相
通用加载中效果
简单加载成功效果
简单通用加载失败效果
简单通用没有数据效果
二.主要代码
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

猜你喜欢

转载自blog.csdn.net/jackiandroid/article/details/47282131