還不知道當listview數據爲空時如何處理嗎---------爲項目建立一個統一的EmptyView

10月底的時候去網易面試,感覺其他發揮都不錯,就listview這塊被虐了。回家痛定思痛,開始研究listview的源碼,從adapterView開始看起,想到了一個比較有趣的技巧,可以方便的管理我們項目中listview數據爲空時EmptyView。廢話不多說,先來看看EmptyView


關於Empty的機制,就是當listview的getCount爲0的時候,就顯示EmptyView。


具體的效果圖是這這樣的




點擊empty的時候清空數據,顯示emptyView,點擊show data的時候,再把數據加載進來

emptyView本身的用法並不複雜,但是我發現很多項目裏每用到一個listview都會去寫一個新的emptyview,這不光違反重用的原則,而且有可能因爲不同人去維護項目而導致每個emptyview的樣式不同,破壞了一個app的統一性,會讓用戶看起來很凌亂。

因此,我在這提出一個概念,每個項目主要實現一個emptyview,爲不同的listview甚至webview服務。然後留出一個接口,用於實現具體的emptyview點擊實現的業務


讓我們先來看看emptyview的實現

package com.example.emptyviewdemo;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.TextView;

public class EmptyView extends RelativeLayout{
	private OnEmptyViewListener mOnEmptyViewListener;
	private TextView         mEmptyTv;
	
	public EmptyView(Context context) {
		super(context);
	}
	
	public EmptyView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	@Override
	protected void onFinishInflate() {
		super.onFinishInflate();
		mEmptyTv = (TextView) findViewById(R.id.empty_textview);
		mEmptyTv.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				if (mOnEmptyViewListener != null) {
					mOnEmptyViewListener.onEmptyViewClick();
				}
			}
		});
	}
	
	public void setOnEmptyViewListener(OnEmptyViewListener listener){
		this.mOnEmptyViewListener = listener;
	}
}
其實很簡單,只是留出了一個接口實現點擊效果


接下來是佈局文件,你可以把這個佈局改成任何你想要的樣子,下面的xml只是舉了一個例子

<?xml version="1.0" encoding="utf-8"?>
<com.example.emptyviewdemo.EmptyView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white" >

    <TextView
        android:id="@+id/empty_textview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:drawablePadding="15dp"
        android:drawableTop="@drawable/friends_sends_pictures_no"
        android:gravity="center"
        android:text="there is no data" />

</com.example.emptyviewdemo.EmptyView>


然後爲了幫助大家更好的理解,我幫上面圖片的實現邏輯貼出來給大家看下

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {
	private EmptyView      mEmptyView;
	private ListView       mListView;
	private Activity       activity;
	private List<String>   data;
	private MyAdapter      mAdapter;
	private Button         mEmptyBtn;
	private Button         mShowDataBtn;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		mEmptyView = (EmptyView) findViewById(R.id.empty_view);
		mListView = (ListView) findViewById(R.id.my_listview);
		mShowDataBtn = (Button) findViewById(R.id.show_data_button);
		mEmptyBtn = (Button) findViewById(R.id.empty_button);
		activity = this;
		initData();
		mAdapter = new MyAdapter(activity);
		mListView.setAdapter(mAdapter);
		mAdapter.setData(data);
		mListView.setEmptyView(mEmptyView);
		
		mEmptyView.setOnEmptyViewListener(new OnEmptyViewListener() {
			
			@Override
			public void onEmptyViewClick() {
				Toast.makeText(activity, "EmptyView被點擊啦!", Toast.LENGTH_LONG).show();
			}
		});
		
		mShowDataBtn.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				mAdapter.setData(data);
			}
		});
		mEmptyBtn.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				mAdapter.emptyData();
			}
		});
		
	}
	
	private void initData(){
		data = new ArrayList<String>();
		data.add("星期一");
		data.add("星期二");
		data.add("星期三");
		data.add("星期四");
		data.add("星期五");
		data.add("星期六");
		data.add("星期七");
	}
	
	private class MyAdapter extends BaseAdapter{
		private List<String> data; 
		private Context context;
		
		public MyAdapter(Context context){
			this.context = context;
		}
		
		public void emptyData() {
			if (this.data == null) {
				this.data = new ArrayList<String>();
			}
			this.data.clear();
			notifyDataSetChanged();
		}
		
		public void setData(List<String> data) {
			if (this.data == null) {
				this.data = new ArrayList<String>();
			}
			this.data.clear();
			this.data.addAll(data);
			notifyDataSetChanged();
		}
		
		@Override
		public int getCount() {
			if(data != null){
				return data.size();
			}
			return 0;
		}
		
		@Override
		public Object getItem(int position) {
			if(data != null){
				return data.get(position);
			}
			return null;
		}

		@Override
		public long getItemId(int position) {
			if(data != null){
				return data.get(position).hashCode();
			}
			return 0;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			ViewHolder holder;
			if(convertView == null){
				holder = new ViewHolder();
				convertView = LayoutInflater.from(context).inflate(R.layout.item_view, null);
				holder.mItemTv = (TextView) convertView.findViewById(R.id.item_textview);
				convertView.setTag(holder);
			}else{
				holder = (ViewHolder) convertView.getTag();
			}
			
			holder.mItemTv.setText(data.get(position));
			
			return convertView;
			
		}
		
	}
	
	private class ViewHolder{
		TextView mItemTv;
	}
	
}

我們要對不同listview的emptyview點擊實現不同業務時,只要實現OnEmptyViewListener就行了



下面是佈局文件

<RelativeLayout 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:background="@android:color/white" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/button_container"
        android:orientation="vertical" >

        <ListView
            android:id="@+id/my_listview"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

        <include
            android:id="@+id/empty_view"
            layout="@layout/empty_view" />
    </LinearLayout>

    <LinearLayout
        android:id="@+id/button_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:orientation="horizontal" >

        <Button
            android:id="@+id/empty_button"
            android:layout_width="0dip"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_weight="1"
            android:background="@android:color/holo_orange_dark"
            android:gravity="center"
            android:padding="15dp"
            android:text="empty" />

        <Button
            android:id="@+id/show_data_button"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_weight="1"
            android:background="@android:color/holo_orange_dark"
            android:gravity="center"
            android:padding="15dp"
            android:text="show data" />
    </LinearLayout>

</RelativeLayout>

值得注意的是當你在使用emptyview 的時候,你所使用的emptyview必須和listview保持在同一層級,就是屬於同一個parent。如果你是動態添加到activity中的,必須使用

((ViewGroup)mListView.getParent()).addView(mEmptyView);


最後說一句是,以前有一個前輩提出過一個概念:當你把一份同樣的代碼寫2邊的時候,就該想想是否能抽象出來,成爲了個公共方法

我覺得這句話挺受用的


發佈了37 篇原創文章 · 獲贊 77 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章