android scrollrefreshlist

简介:         package com.baoy.demo.demoscrollrefreshlist.activity; import java.text.SimpleDateFormat; import java.

 



 

 

 

package com.baoy.demo.demoscrollrefreshlist.activity;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;

import com.baoy.demo.demoscrollrefreshlist.R;
import com.baoy.demo.demoscrollrefreshlist.adapter.ProductAdapter;
import com.baoy.demo.demoscrollrefreshlist.entity.Product;
import com.baoy.demo.demoscrollrefreshlist.util.Config;
import com.baoy.demo.demoscrollrefreshlist.view.ScrollRefreshListView;
import com.baoy.demo.demoscrollrefreshlist.view.ScrollRefreshListView.onRefreshListener;
 

public class ProductListActivity extends Activity implements OnClickListener, OnItemClickListener, onRefreshListener{

	private ArrayList<Product> mDataList;
	private ProductAdapter mAdapter;
	private ScrollRefreshListView mListView;
	
	static int j = 0;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		Config.setContext(ProductListActivity.this);
		
		setContentView(R.layout.product_list);
		
		mDataList = new ArrayList<Product>();
		mListView = (ScrollRefreshListView) this.findViewById(R.id.listView_product);
		mAdapter = new ProductAdapter(this, mDataList);
		
		mListView.setAdapter(mAdapter);
		
		mListView.setOnItemClickListener( this );
	    mListView.setOnRefreshListener( this );
	     
	    j =0;
	    
	    doHandle(0);
	   // mListView.refreshSelf();
	}
	
	private void doHandle(int a) { 
		switch (a) {
		case 0:
		{
			 mListView.refreshSelf();
			for (int i = 0; i < 10; i++) {
				j += i;
			 mDataList.add(new Product(null,"商品"+j,"商品内容"+j,new SimpleDateFormat("yyyy-mm-dd HH:MM:ss").format(new Date()),null));
			}
			updateUIThread(0);
		}
			break;
		case 1:
		{ 
			 j++;
			 mDataList.add(new Product(null,"商品"+j,"商品内容"+j,new SimpleDateFormat("yyyy-mm-dd HH:MM:ss").format(new Date()),null));
			 updateUIThread(0);
		}
			break;

		case 2:
		{
			updateUIThread(1);
		}
			break;


		default:
			break;
		}
		
		
	}

	
	  public void updateUIThread( final int type ) {
	        new Thread( new Runnable() {
	            @Override
	            public void run() {
	            	mHandler.sendEmptyMessage( type );
	            }
	        } ).start();
	    }
	  
	Handler mHandler = new Handler(){
		 public void handleMessage(
                 Message msg ) {
			 switch (msg.what) {
			case 0:
				if (mDataList.size() == 0) {
					refreshEmptyView();
				}else{ 
					mListView.onRefreshComplete();
	                mListView.setLoadMoreComplete();
	                mAdapter.setDataList(mDataList);
	                refreshEmptyView();
				}
				break;
			case 1:
				mListView .removeListFooterView(ScrollRefreshListView.FOOTER_VIEW_NONE);
				mListView .removeListFooterView(ScrollRefreshListView.FOOTER_VIEW_MORE);
				break;
			default:
				break;
			}
		 }
	};
	
	@Override
	public void onRefresh() { 
		doHandle(1);
	}

	@Override
	public void onLoadMore() { 
		doHandle(2);
	}

	@Override
	public void onItemClick(AdapterView<?> parent, View view, int position,
			long id) { 
		
	}

	@Override
	public void onClick(View v) { 
		
	} 

	private void refreshEmptyView() {
		if (mAdapter.getCount() == 0) { 
			mListView .setListFooterView(ScrollRefreshListView.FOOTER_VIEW_EMPTY);
		} else { 
			mListView .removeListFooterView(ScrollRefreshListView.FOOTER_VIEW_NONE);
			mListView .setListFooterView(ScrollRefreshListView.FOOTER_VIEW_MORE);
		}
	}
	
	
}

 

 

package com.baoy.demo.demoscrollrefreshlist.adapter;

import java.util.ArrayList;

import android.content.Context;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.BaseAdapter;

/**
 * List view base adapter class Adapters that subclasses this base class will be
 * used in various kinds of list views including system default list view
 * control and the custom unrolled list view
 * 
 * @author Neusoft.E3
 * 
 */
public abstract class ListBaseAdapter extends BaseAdapter {
	protected LayoutInflater mLayoutInflater; // layout inflater
	protected int mResource; // item layout resource
	protected ArrayList<?> mData; // list data
	protected Context mContext; // parent
	protected OnClickListener mClickListener; // item click listener, not used
												// in every case

	/**
	 * Constructor
	 * 
	 * @param aContext
	 *            parent
	 * @param bf
	 * @param aData
	 *            list data
	 * @param aResource
	 *            item layout resource
	 */

	public ListBaseAdapter(Context aContext, ArrayList<?> aData) {
		mContext = aContext.getApplicationContext();
		mData = aData;
		mLayoutInflater = (LayoutInflater) aContext
				.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
	}

	public ListBaseAdapter(Context aContext, ArrayList<?> aData,
			Handler aHandler) {
		mContext = aContext;
		mData = aData;
		mLayoutInflater = (LayoutInflater) aContext
				.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
	}

	@Override
	public int getCount() {
		return mData.size();
	}

	@Override
	public Object getItem(int position) {
		return mData.get(position);
	}

	@Override
	public long getItemId(int position) {
		return position;
	}

	@Override
	public abstract View getView(int position, View convertView,
			ViewGroup parent);

	/**
	 * Set item click listener
	 * 
	 * @param aListener
	 */
	public void setItemOnClickListener(OnClickListener aListener) {
		mClickListener = aListener;
	}

	public boolean cleanDatas() {
		if (mData != null) {
			mData.clear();
			return true;
		}
		return false;
	}


}

 

 

package com.baoy.demo.demoscrollrefreshlist.adapter;

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

import com.baoy.demo.demoscrollrefreshlist.R; 
import com.baoy.demo.demoscrollrefreshlist.entity.Product;  

import android.content.Context;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

public class ProductAdapter extends ListBaseAdapter implements OnClickListener {

	
	private Context mContext;
	private LayoutInflater mInflater;
	private List<Product> mDataList;
	
	private static class ViewHolder {
		public ImageView productPhoto;
		public TextView  productName;
		public TextView  productContent;
		public TextView  productUpdateTime;
		public ImageView productBuy;
		
		public ViewHolder(View baseView) {
			this.productPhoto = (ImageView) baseView.findViewById(R.id.iv_product_photo);
			this.productName = (TextView) baseView.findViewById(R.id.tv_product_name);
			this.productContent = (TextView) baseView.findViewById(R.id.tv_product_content);
			this.productUpdateTime = (TextView) baseView.findViewById(R.id.tv_product_time);
			this.productBuy = (ImageView) baseView.findViewById(R.id.iv_product_buy);
		}
	}
	
	
	public ProductAdapter(Context aContext, ArrayList<Product> aData) {
		super(aContext, aData); 
		this.mContext = aContext;
		this.mInflater = LayoutInflater.from(aContext);
	}
	
	public void setDataList(List<Product> dataList) {
      mDataList = dataList; 
      notifyDataSetChanged();
	}
	
	public void addDataList(List<Product> dataList) {
		if (mDataList == null ) {
	    	 mDataList = new ArrayList<Product>();
		  }
	      mDataList.addAll(dataList);
	      notifyDataSetChanged();
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) { 
		ViewHolder viewHolder = null;
		if (convertView == null) {
			convertView = mInflater.inflate(R.layout.product_list_item, null);
			viewHolder = new ViewHolder(convertView);
			convertView.setTag(viewHolder);
		} else {
			viewHolder = (ViewHolder) convertView.getTag();
		}
		Product item = getItem(position);
		if( TextUtils.isEmpty(item.getProductUrl())){
			viewHolder.productPhoto.setImageResource(R.drawable.ic_launcher);
		}else{
			// ImageBank.getInstance().setImage();
			viewHolder.productPhoto.setImageResource(R.drawable.ic_launcher);
		}
		viewHolder.productName.setText( item.getProductName());
		viewHolder.productContent.setText(item.getProductContent());
		viewHolder.productUpdateTime.setText(item.getProductUpdateTime());
		if( TextUtils.isEmpty(item.getProductBuy())){
			viewHolder.productBuy.setImageResource(R.drawable.ic_launcher);
		}else{
			viewHolder.productBuy.setImageResource(R.drawable.ic_launcher);
		}
		 
		 
		return convertView;
	}

	@Override
	public void onClick(View v) { 
		
	}

	@Override
	public int getCount() {
		if (mDataList == null) {
			return 0;
		}
		return mDataList.size();
	}
	
	@Override
	public Product getItem(int position) {
		if (mDataList != null && position >= 0 && position < mDataList.size()) {
			return mDataList.get(position);
		}
		return null;
	}
	
}

 

 

product_list_item.xml

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

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingBottom="11dp"
        android:paddingLeft="11dp"
        android:paddingRight="11dp"
        android:paddingTop="11dp" >

        <ImageView
            android:id="@+id/iv_product_photo"
            android:layout_width="37dp"
            android:layout_height="37dp"
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="true"
            android:layout_marginTop="7dp"
            android:scaleType="centerCrop"
            android:src="@drawable/ic_launcher" />

        <TextView
            android:id="@+id/tv_product_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="6dp"
            android:layout_marginLeft="7dp"
            android:layout_marginTop="4dp"
            android:layout_toRightOf="@+id/iv_product_photo"
            android:singleLine="true"
            android:text="商品名称"
            android:textColor="@color/black"
            android:textSize="13sp" />

        <TextView
            android:id="@+id/tv_product_content"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignLeft="@+id/tv_product_name"
            android:layout_below="@+id/tv_product_name"
            android:layout_marginBottom="6dp"
            android:layout_toLeftOf="@+id/iv_product_buy"
            android:singleLine="true"
            android:text="商品详细内容商品详细内容商品详细内容商品详细内容商品详细内容商品详细内容商品详细内容"
            android:textColor="@color/black"
            android:textSize="13sp" />

        <TextView
            android:id="@+id/tv_product_time"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignLeft="@+id/tv_product_name"
            android:layout_below="@+id/tv_product_content"
            android:textColor="@color/black"
            android:text="商品更新时间"
            android:textSize="11sp" />

        <ImageView
            android:id="@+id/iv_product_buy"
            android:layout_width="55dp"
            android:layout_height="55dp"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:layout_marginRight="11dp" 
            android:src="@drawable/ic_launcher"/>
    </RelativeLayout>

    <View
        android:layout_width="match_parent"
        android:layout_height="1px"
        android:layout_alignParentBottom="true"
        android:background="@color/black" />

</RelativeLayout>

 

 

product_list.xml

<?xml version="1.0" encoding="utf-8"?>
<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" >
  
    <com.baoy.demo.demoscrollrefreshlist.view.ScrollRefreshListView
            android:id="@+id/listView_product"
            style="@style/listView_normal_style"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:divider="@color/transparent"
            android:dividerHeight="0dp" />

</RelativeLayout>

 

 

scroll_refresh_head.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="@color/transparent" >

    <!-- 内容 -->

    <RelativeLayout
        android:id="@+id/head_contentLayout"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dip"
        android:paddingLeft="30dp" >

        <!-- 箭头图像、进度条 -->

        <FrameLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true" >

            <!-- 箭头 -->

            <ImageView
                android:id="@+id/head_arrowImageView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:src="@drawable/ic_pulltorefresh_arrow" />
            <!-- 进度条 -->

            <ProgressBar
                android:id="@+id/head_progressBar"
                style="?android:attr/progressBarStyleSmall"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:visibility="gone" />
        </FrameLayout>
        <!-- 提示、最近更新 -->

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:gravity="center_horizontal"
            android:orientation="vertical" >

            <!-- 提示 -->

            <TextView
                android:id="@+id/head_tipsTextView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/scroll_refresh_text"
                android:textSize="15dp" />
            <!-- 最近更新 -->

            <TextView
                android:id="@+id/head_lastUpdatedTextView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/scroll_refresh_last_text"
                android:textSize="12dp" />
        </LinearLayout>
    </RelativeLayout>

</LinearLayout>

 

 

listfooter.xml

<?xml version="1.0" encoding="utf-8"?>
<com.baoy.demo.demoscrollrefreshlist.view.AppendButton
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/appender"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content">
</com.baoy.demo.demoscrollrefreshlist.view.AppendButton>

 

 

empty_content.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
            android:id="@+id/txtEmptyText"
            android:layout_width="180dip"
            android:layout_height="150dip"
            android:layout_centerHorizontal="true"
            android:gravity="center_horizontal"
            android:text="@string/empty_text"
            android:textSize="14sp"
            android:linksClickable="true"
            android:paddingTop="50dip"
            android:textColor="@color/color_btn_bottom"
            android:layout_marginTop="50dip"/>
</RelativeLayout>

 

 

appendbutton.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/rlAppend"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" >

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="1dip"
        android:layout_alignParentTop="true" />

    <Button
        android:id="@+id/btnAppend"
        android:layout_width="fill_parent"
        android:layout_height="60dip"
        android:layout_centerHorizontal="true"
        android:background="@null"
        android:text="@string/append_more"
        android:textSize="15dip" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true" >
    <ProgressBar
        android:id="@+id/pbAppend"
        android:layout_width="15dip"
        android:layout_height="15dip" 
        android:layout_marginLeft="210dip"/>
   </LinearLayout>
</RelativeLayout>

 

 

package com.baoy.demo.demoscrollrefreshlist.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

import android.text.TextUtils;

/**
 * 
 * @author Neusoft
 * 
 */
public class TimeUtils {

    private static final String JUST_NOW              = "刚刚";
    private static final String MINUTE_AGO            = "分钟前";
    private static final String HOUR_AGO              = "小时前";
    private static final String TIME_TRANSFER_ERROR   = "时间传输有误";
    private static final String FORMAT_ERROR          = "";

    private static final String FORMAT_TODAY_TEXT     = "今天";
    private static final String FORMAT_YESTERDAY_TEXT = "昨天";
    private static final String FORMAT_BEFORE_TEXT    = "前天";

    /**
     * 获取转换时间
     * 
     * @param updateTime
     * @return
     */
    public static String getUpdateTime( long updateTime ) {
        String result = "";
        try {
            long currentTimeSec = System.currentTimeMillis() / 1000;
            // long calTime = Long.parseLong(updateTime);
            long calTime = updateTime;
            long timeDif = currentTimeSec - calTime;
            if ( timeDif < 60 ) {
                result = JUST_NOW;
            }
            else if ( timeDif < 60 * 60 ) {
                result = ( timeDif / 60 ) + MINUTE_AGO;
            }
            else if ( timeDif < 60 * 60 * 24 ) {
                result = timeDif / 3600 + HOUR_AGO;
            }
            else {
                String strfullres = getDetailDate( String.valueOf( calTime ) );
                result = strfullres.substring( 5, strfullres.length() - 3 );
            }
        }
        catch ( Exception e ) {
            result = FORMAT_ERROR;
        }

        return result;
    }

    public static String getUpdateTime( String updateTime ) {
        String result = "";
        try {
            long currentTimeSec = System.currentTimeMillis() / 1000;
            long calTime = Long.parseLong( updateTime );
            // long calTime = updateTime;
            long timeDif = currentTimeSec - calTime;
            if ( timeDif < 60 ) {
                result = JUST_NOW;
            }
            else if ( timeDif < 60 * 60 ) {
                result = ( timeDif / 60 ) + MINUTE_AGO;
            }
            else if ( timeDif < 60 * 60 * 24 ) {
                result = timeDif / 3600 + HOUR_AGO;
            }
            else {
                String strfullres = getDetailDate( String.valueOf( calTime ) );
                result = strfullres.substring( 5, strfullres.length() - 3 );
            }
        }
        catch ( Exception e ) {
            result = FORMAT_ERROR;
        }

        return result;
        // return "09:45";
    }

    /**
     * 获取转换时间
     * 
     * @param updateTime
     * @return
     */
    public static String getUpdateTimeWithYear( String updateTime ) {
        String result = "";
        try {
            long currentTimeSec = System.currentTimeMillis() / 1000;
            long calTime = Long.parseLong( updateTime );
            long timeDif = currentTimeSec - calTime;
            if ( timeDif < 60 ) {
                result = JUST_NOW;
            }
            else if ( timeDif < 60 * 60 ) {
                result = ( timeDif / 60 ) + MINUTE_AGO;
            }
            else if ( timeDif < 60 * 60 * 24 ) {
                result = timeDif / 3600 + HOUR_AGO;
            }
            else {
                String strfullres = getDetailDate( String.valueOf( calTime ) );
                result = strfullres.substring( 0, strfullres.length() - 3 );
            }
        }
        catch ( Exception e ) {
            result = FORMAT_ERROR;
        }

        return result;
    }

    /**
     * 格式转化:yy-MM-dd
     * 
     * @param timeSec
     * @return
     */
    public static String getDate( Long timeSec ) {
        StringBuilder sb = new StringBuilder();
        if ( timeSec == -1 ) {
            return "";
        }
        Long time = timeSec * 1000;
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis( time );
        sb.append( cal.get( Calendar.YEAR ) ).append( "-" );
        sb.append( cal.get( Calendar.MONTH ) + 1 ).append( "-" );
        sb.append( cal.get( Calendar.DATE ) );
        return sb.toString();
    }

    /**
     * 格式转化:yy-MM-dd
     * 
     * @param timeSec
     * @return
     */
    public static String getDate( String timeSec ) {
        StringBuilder sb = new StringBuilder();
        if ( timeSec.equals( "-1" ) ) {
            return "";
        }
        Long time = Long.parseLong( timeSec ) * 1000;
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis( time );
        sb.append( cal.get( Calendar.YEAR ) ).append( "-" );
        sb.append( cal.get( Calendar.MONTH ) + 1 ).append( "-" );
        sb.append( cal.get( Calendar.DATE ) );
        return sb.toString();
    }

    /**
     * 格式转化:yy-MM-dd HH:mm
     * 
     * @param timeSec
     * @return
     */
    public static String getDateEndMinute( Long timeSec ) {
        StringBuilder sb = new StringBuilder();
        if ( timeSec == -1 ) {
            return "";
        }
        Long time = timeSec * 1000;
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis( time );
        sb.append( cal.get( Calendar.YEAR ) ).append( "-" );
        sb.append( cal.get( Calendar.MONTH ) + 1 ).append( "-" );
        sb.append( cal.get( Calendar.DATE ) );

        sb.append( " " );

        // 小时
        int hours = cal.get( Calendar.HOUR_OF_DAY );
        if ( hours == 0 ) {
            sb.append( "00" ).append( ":" );
        }
        else if ( hours < 10 ) {
            sb.append( "0" + hours ).append( ":" );
        }
        else {
            sb.append( hours ).append( ":" );
        }

        // 分钟
        int minutes = cal.get( Calendar.MINUTE );
        if ( minutes == 0 ) {
            sb.append( "00" );
        }
        else if ( minutes < 10 ) {
            sb.append( "0" + minutes );
        }
        else {
            sb.append( minutes );
        }

        return sb.toString();
    }

    /**
     * 格式转化:yy-MM-dd HH:mm:ss
     * 
     * @param timeSec
     *            网络传输回来的时间(秒)
     * @return 详细时间
     */
    public static String getDetailDate( String timeSec ) {
        try {
            Long time = Long.parseLong( timeSec ) * 1000;
            Calendar cal = Calendar.getInstance();
            cal.setTimeInMillis( time );
            StringBuilder sb = new StringBuilder();
            sb.append( cal.get( Calendar.YEAR ) ).append( "-" );
            sb.append( cal.get( Calendar.MONTH ) + 1 ).append( "-" );
            sb.append( cal.get( Calendar.DATE ) ).append( " " );

            // 小时
            int hours = cal.get( Calendar.HOUR_OF_DAY );
            if ( hours == 0 ) {
                sb.append( "00" ).append( ":" );
            }
            else if ( hours < 10 ) {
                sb.append( "0" + hours ).append( ":" );
            }
            else {
                sb.append( hours ).append( ":" );
            }

            // 分钟
            int minutes = cal.get( Calendar.MINUTE );
            if ( minutes == 0 ) {
                sb.append( "00" ).append( ":" );
            }
            else if ( minutes < 10 ) {
                sb.append( "0" + minutes ).append( ":" );
            }
            else {
                sb.append( minutes ).append( ":" );
            }

            // 秒
            int seconds = cal.get( Calendar.SECOND );
            if ( seconds == 0 ) {
                sb.append( "00" );
            }
            else if ( seconds < 10 ) {
                sb.append( "0" + seconds );
            }
            else {
                sb.append( seconds );
            }
            return sb.toString();
        }
        catch ( Exception e ) {
            return TIME_TRANSFER_ERROR;
        }
    }

    /**
     * 得到字符串日期,格式为yyyy-MM-dd HH:mm 当前年份日期不显示年
     * 
     * @param date
     * @return
     */
    public static String getFormatDate( Date date ) {
        String format = "MM-dd HH:mm";
        if ( date.getYear() == ( new Date() ).getYear() ) {
            format = "yyyy-MM-dd HH:mm";
        }

        SimpleDateFormat df = new SimpleDateFormat( format, Locale.getDefault() );
        return df.format( date );
    }

    /**
     * 得到字符串日期,格式为yyyy-MM-dd HH:mm 当前年份日期不显示年
     * 
     * @param date
     * @return
     */
    public static String getFormatDate( String date ) {
        if ( TextUtils.isEmpty( date ) )
            return null;
        String format = "yyyy-MM-dd HH:mm";
        SimpleDateFormat df = new SimpleDateFormat( format, Locale.getDefault() );
        Date d = null;
        try {
            d = df.parse( date );
        }
        catch ( ParseException e ) {
            e.printStackTrace();
            return date;
        }
        if ( d.getYear() != ( new Date() ).getYear() ) {
            format = "yyyy-MM-dd HH:mm";
        }
        else {
            format = "MM-dd HH:mm";
        }
        df = new SimpleDateFormat( format, Locale.getDefault() );
        return df.format( d );
    }

    public static String getCurrentDateTime() {
        SimpleDateFormat format = new SimpleDateFormat( "yyyy年MM月dd日  HH:mm" );
        String date = format.format( new Date() );

        return date;
    }

    public static String getCurrentDate() {
        SimpleDateFormat format = new SimpleDateFormat( "yyyy-MM-dd" );
        String date = format.format( new Date() );

        return date;
    }

    public static String getCurrentWeekOfDate( Date date ) {
        SimpleDateFormat format = new SimpleDateFormat( "yyyy-MM-dd" );
        String dataString = format.format( date );

        SimpleDateFormat dateFm = new SimpleDateFormat( "EEEE" );
        String weekString = dateFm.format( date );

        return dataString + " " + weekString;
    }

    public static String getDetailDateTime( long timeSec ) {
        SimpleDateFormat format = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" );
        Date date = new Date( timeSec );
        return format.format( date );
    }

    public static String getDateDay( long timeSec ) {
        SimpleDateFormat format = new SimpleDateFormat( "yyyy-MM-dd",
                Locale.CHINA );
        Date date = new Date( timeSec );
        return format.format( date );
    }

    public static String getTimeOfDay( long timeSec ) {
        SimpleDateFormat format = new SimpleDateFormat( "HH:mm" );
        Date date = new Date( timeSec );
        return format.format( date );
    }

    public static String getYearAndMonth( long timeSec ) {
        SimpleDateFormat format = new SimpleDateFormat( "yyyy年MM月" );
        Date date = new Date( timeSec );
        return format.format( date );
    }

    public static String formatDateTime( long aTime ) {
        String ret = null;

        Date date = new Date( aTime * 1000 );
        Calendar c = Calendar.getInstance();
        c.setTime( date );

        Date currentDate = new Date();
        Calendar cc = Calendar.getInstance();
        cc.setTime( currentDate );

        if ( c.get( Calendar.YEAR ) == cc.get( Calendar.YEAR ) ) {
            int day = cc.get( Calendar.DAY_OF_YEAR )
                    - c.get( Calendar.DAY_OF_YEAR );
            if ( day == 0 ) {
                ret = FORMAT_TODAY_TEXT;
                ret += " ";

                SimpleDateFormat format = new SimpleDateFormat( "HH:mm",
                        Locale.CHINA );
                ret += format.format( date );
            }
            else if ( day == 1 ) {
                ret = FORMAT_YESTERDAY_TEXT;
                ret += " ";

                SimpleDateFormat format = new SimpleDateFormat( "HH:mm",
                        Locale.CHINA );
                ret += format.format( date );
            }
            else if ( day == 2 ) {
                ret = FORMAT_BEFORE_TEXT;
                ret += " ";

                SimpleDateFormat format = new SimpleDateFormat( "HH:mm",
                        Locale.CHINA );
                ret += format.format( date );
            }
            else {
                SimpleDateFormat format = new SimpleDateFormat( "MM-dd HH:mm",
                        Locale.CHINA );
                ret = format.format( date );
            }

        }
        else {
            SimpleDateFormat format = new SimpleDateFormat( "yyyy-MM-dd HH:mm",
                    Locale.CHINA );

            ret = format.format( date );
        }

        return ret;
    }

    public static String formatChatDataTime( long aTime ) {
        String ret = "";

        Date date = new Date( aTime * 1000 );
        Calendar c = Calendar.getInstance();
        c.setTime( date );

        Date currentDate = new Date();
        Calendar cc = Calendar.getInstance();
        cc.setTime( currentDate );

        if ( c.get( Calendar.YEAR ) == cc.get( Calendar.YEAR ) ) {
            int day = cc.get( Calendar.DAY_OF_YEAR )
                    - c.get( Calendar.DAY_OF_YEAR );
            if ( day == 0 ) {
                SimpleDateFormat format = new SimpleDateFormat( "HH:mm",
                        Locale.CHINA );
                ret = format.format( date );
            }
            else if ( day == 1 ) {
                ret = FORMAT_YESTERDAY_TEXT;
            }
            else if ( day == 2 ) {
                ret = FORMAT_BEFORE_TEXT;
            }
            else {
                SimpleDateFormat format = new SimpleDateFormat( "MM-dd",
                        Locale.CHINA );
                ret = format.format( date );
            }

        }
        else {
            SimpleDateFormat format = new SimpleDateFormat( "yyyy-MM-dd",
                    Locale.CHINA );

            ret = format.format( date );
        }

        return ret;
    }

    public static long getCurrentTime() {
        Date currentDate = new Date();
        Calendar cc = Calendar.getInstance();
        cc.setTime( currentDate );

        long time = cc.getTimeInMillis() / 1000;
        return time;
    }
}

 

 

package com.baoy.demo.demoscrollrefreshlist.util;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;

import android.content.Context;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ListAdapter;
import android.widget.ListView;

public class Config {
	
	public static final String FILE_NAME = "settings.properties";
	public static final int BASE_DISPLAY_WIDTH = 320;
	public static final int BASE_DISPLAY_HEIGHT = 480;
    public static final int    LOADING_PROGRESS_SIZE       = 15;
    public static final int    LOADING_PROGRESS_MARGIN     = 210;
	private static Context sContext;
	private static Properties sProperties;
 
	public static void setContext(Context aContext) {
		sContext = aContext.getApplicationContext();
		sProperties = new Properties();
		loadProperties();
	}

	private static void loadProperties() {
		try {
			sProperties.load(sContext.openFileInput(FILE_NAME));
		} catch (FileNotFoundException e) {
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static int getViewPx(int aValue) {
		int ret = 0;
		int width = Config.getWindowWidth();
		ret = (int) (width * aValue / Config.BASE_DISPLAY_WIDTH);

		return ret;
	}
	
	public static int getWindowWidth() {
		System.out.println("getWindowWidth:  开始:sContext:" + sContext);
		WindowManager windowManager = (WindowManager) sContext
				.getSystemService(Context.WINDOW_SERVICE);
		DisplayMetrics mMetric = new DisplayMetrics();
		windowManager.getDefaultDisplay().getMetrics(mMetric);
		System.out.println("getWindowWidth:  " + mMetric.widthPixels);
		return mMetric.widthPixels;
	}

}

 

 

package com.baoy.demo.demoscrollrefreshlist.view;

import com.baoy.demo.demoscrollrefreshlist.R;
import com.baoy.demo.demoscrollrefreshlist.util.Config;

import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
 

/**
 * Common appending button for all lists
 * 
 * @author Neusoft.E3
 * 
 */
public class AppendButton extends LinearLayout {

	private Button mBtnAppend;
	private ProgressBar mPbLoading;
	private RelativeLayout mRlAppend;
	private int mNormalTextResource;
	private int mLoadingTextResource;
	private boolean misLoading = false;

	public AppendButton(Context context) {
		super(context);
		loadResources();
	}

	public AppendButton(Context context, AttributeSet attrs) {
		super(context, attrs);
		loadResources();
	}

	private void loadResources() {
		LayoutInflater inflater = (LayoutInflater) getContext()
				.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		inflater.inflate(R.layout.appendbutton, this, true);

		mLoadingTextResource = R.string.append_loading;
		mNormalTextResource = R.string.append_more;

		mRlAppend = (RelativeLayout) findViewById(R.id.rlAppend);
		mBtnAppend = (Button) findViewById(R.id.btnAppend);
		mPbLoading = (ProgressBar) findViewById(R.id.pbAppend);
		mPbLoading.setVisibility(View.GONE);
		LayoutParams params = new LayoutParams(
				Config.getViewPx(Config.LOADING_PROGRESS_SIZE),
				Config.getViewPx(Config.LOADING_PROGRESS_SIZE));
		params.setMargins(Config.getViewPx(Config.LOADING_PROGRESS_MARGIN), 0,
				0, 0);
		mPbLoading.setLayoutParams(params);
	}

	@Override
	public void setOnClickListener(OnClickListener aListener) {
		mBtnAppend.setOnClickListener(aListener);
	}

	/**
	 * Set whole item background
	 * 
	 * @param aResourceId
	 */
	public void setBgColor(int aColorId) {
		mRlAppend.setBackgroundColor(aColorId);
	}

	/**
	 * Set custom button bg resource id
	 * 
	 * @param aResourceId
	 */
	public void setButtonBgResource(int aResourceId) {
		mBtnAppend.setBackgroundResource(aResourceId);
	}

	/**
	 * Set custom button text color resource id
	 * 
	 * @param aResourceId
	 */
	public void setTextColorResource(int aResourceId) {
		mBtnAppend.setTextColor(getContext().getResources().getColorStateList(
				aResourceId));
	}

	/**
	 * Set if loading state is enabled
	 * 
	 * @param aLoading
	 */
	public void setLoading(boolean aLoading) {
		misLoading = aLoading;
		if (aLoading) {
			mBtnAppend.setText(mLoadingTextResource);
			mPbLoading.setVisibility(View.VISIBLE);
		} else {
			mBtnAppend.setText(mNormalTextResource);
			mPbLoading.setVisibility(View.GONE);
		}
		mBtnAppend.setEnabled(!aLoading);
	}

	public boolean isLoading() {
		return misLoading;
	}

	/**
	 * Set text
	 * 
	 * @param text
	 */
	public void setText(int aNormalResource, int aLoadingResource) {
		mNormalTextResource = aNormalResource;
		mLoadingTextResource = aLoadingResource;
		mBtnAppend.setText(mNormalTextResource);
	}

}

 

 

 

package com.baoy.demo.demoscrollrefreshlist.view;

import com.baoy.demo.demoscrollrefreshlist.R;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.TextView;
 

public class EmptyView extends RelativeLayout {
    private TextView mTxtEmpty;

    public EmptyView( Context context ) {
        super( context );

        LayoutInflater layoutInflater = ( LayoutInflater ) getContext()
                .getSystemService( Context.LAYOUT_INFLATER_SERVICE );

        View view = layoutInflater.inflate( R.layout.empty_content, this, true );

        mTxtEmpty = ( TextView ) view.findViewById( R.id.txtEmptyText );

    }

    public void setEmptyText( int aResId ) {
        mTxtEmpty.setText( aResId );
    }

    public void setEmptyText( String aTxt ) {
        mTxtEmpty.setText( aTxt );
    }

}

 

 

 

package com.baoy.demo.demoscrollrefreshlist.view;
//com.baoy.demo.demoscrollrefreshlist.view.ScrollRefreshListView
import com.baoy.demo.demoscrollrefreshlist.R;
import com.baoy.demo.demoscrollrefreshlist.util.TimeUtils;

import android.content.Context;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
 

public class ScrollRefreshListView extends ListView implements OnScrollListener {
    public static final String id                 = "ScrollRefreshListView";

    public static final int    FOOTER_VIEW_NONE   = 0;
    public static final int    FOOTER_VIEW_MORE   = 1;
    public static final int    FOOTER_VIEW_EMPTY  = 2;

    private final static int   RELEASE_TO_REFRESH = 0;                      // 释放
    private final static int   PULL_TO_REFRESH    = 1;                      // 下拉刷新
    public final static int    REFRESHING         = 2;                      // 正在刷新
    private final static int   DONE               = 3;                      // 按下
    private final static int   LOADING            = 4;
    // 实际的padding的距离与界面上偏移距离的比例
    private final static int   RATIO              = 3;

    private LayoutInflater     mInflater;
    private LinearLayout       mRefreshView;
    private TextView           mTipsTextview;
    private TextView           mLastUpdatedTextView;
    private ImageView          mArrowImageView;
    private ProgressBar        mProgressBar;
    private RotateAnimation    mAnimation;
    private RotateAnimation    mReverseAnimation;
    // 用于保证startY的值在一个完整的touch事件中只被记录一次
    private boolean            mIsRecored;
    private int                mHeadContentWidth;
    private int                mHeadContentHeight;
    private int                mStartY;
    private int                mFirstItemIndex;
    private int                mState;
    private boolean            mIsBack;
    private onRefreshListener  mRefreshListener;
    private boolean            mIsRefreshable;
    private Context            mContext;

    private View               mListFooter;
    private View               mEmptyView;
    private AppendButton       mBtnAppend;

    private OnResizeListener   mOnResizeListener;

    public interface onRefreshListener {
        public void onRefresh();

        public void onLoadMore();
    }

    public interface OnResizeListener {
        void OnResize( int w, int h, int oldw, int oldh );
    }

    public ScrollRefreshListView( Context context ) {
        super( context );
        mContext = context;

        init( context );
    }

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

        init( context );
    }

    private void init( Context context ) {
        mInflater = LayoutInflater.from( context );
        // head 布局文件
        mRefreshView = ( LinearLayout ) mInflater.inflate(
                R.layout.scroll_refresh_head, null );
        // 下拉箭头
        mArrowImageView = ( ImageView ) mRefreshView
                .findViewById( R.id.head_arrowImageView );
        mArrowImageView.setMinimumWidth( 70 );
        mArrowImageView.setMinimumHeight( 50 );
        // 进度条
        mProgressBar = ( ProgressBar ) mRefreshView
                .findViewById( R.id.head_progressBar );
        // 下拉提示刷新
        mTipsTextview = ( TextView ) mRefreshView
                .findViewById( R.id.head_tipsTextView );
        // 最新一次刷新时间
        mLastUpdatedTextView = ( TextView ) mRefreshView
                .findViewById( R.id.head_lastUpdatedTextView );
        // 计算head的高宽
        measureView( mRefreshView );
        mHeadContentHeight = mRefreshView.getMeasuredHeight();
        mHeadContentWidth = mRefreshView.getMeasuredWidth();
        // 初始状态是 隐藏掉head 布局
        mRefreshView.setPadding( 0, -1 * mHeadContentHeight, 0, 0 );
        mRefreshView.invalidate();
        Log.v( "size", "width:" + mHeadContentWidth + " height:"
                + mHeadContentHeight );
        // list添加头文件

        addHeaderView( mRefreshView, null, false );
        setOnScrollListener( this );
        // 下拉以及恢复动画
        mAnimation = new RotateAnimation( 0, -180,
                RotateAnimation.RELATIVE_TO_SELF, 0.5f,
                RotateAnimation.RELATIVE_TO_SELF, 0.5f );
        mAnimation.setInterpolator( new LinearInterpolator() );
        mAnimation.setDuration( 250 );
        mAnimation.setFillAfter( true );
        mReverseAnimation = new RotateAnimation( -180, 0,
                RotateAnimation.RELATIVE_TO_SELF, 0.5f,
                RotateAnimation.RELATIVE_TO_SELF, 0.5f );
        mReverseAnimation.setInterpolator( new LinearInterpolator() );
        mReverseAnimation.setDuration( 200 );
        mReverseAnimation.setFillAfter( true );
        mState = DONE;
        mIsRefreshable = false;
        System.out.println( "mListFooter:" + mListFooter + ",,mListFooter:"
                + mListFooter );
        mListFooter = mInflater.inflate( R.layout.listfooter, null );
        mBtnAppend = ( AppendButton ) mListFooter.findViewById( R.id.appender );
        mBtnAppend.setVisibility( View.GONE );
        mEmptyView = new EmptyView( mContext );

        addFooterView( mListFooter );
        mBtnAppend.setOnClickListener( new OnClickListener() {

            @Override
            public void onClick( View v ) {

                mBtnAppend.setVisibility( View.VISIBLE );
                mBtnAppend.setLoading( true );
                mRefreshListener.onLoadMore();
            }
        } );

    }

    public void onScroll( AbsListView arg0, int firstVisiableItem, int arg2,
            int arg3 ) {
        mFirstItemIndex = firstVisiableItem;
    }

    public void onScrollStateChanged( AbsListView arg0, int scrollState ) {
    }

    public boolean onTouchEvent( MotionEvent event ) {

        if ( mIsRefreshable ) {
            switch ( event.getAction() ) {
            // 在down时候记录当前Y的位置
                case MotionEvent.ACTION_DOWN:
                    if ( mFirstItemIndex == 0 && !mIsRecored ) {
                        mIsRecored = true;
                        mStartY = ( int ) event.getY();
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    if ( mState != REFRESHING && mState != LOADING ) {
                        if ( mState == DONE ) {
                            // 什么都不做
                        }
                        // 由下拉刷新状态,到done状态
                        if ( mState == PULL_TO_REFRESH ) {
                            mState = DONE;
                            changeHeaderViewByState();
                        }

                        if ( mState == RELEASE_TO_REFRESH ) {
                            mState = REFRESHING;
                            changeHeaderViewByState();
                            onRefresh();
                        }
                    }
                    mIsRecored = false;
                    mIsBack = false;
                    break;

                case MotionEvent.ACTION_MOVE:
                    int tempY = ( int ) event.getY();
                    if ( !mIsRecored && mFirstItemIndex == 0 ) {
                        mIsRecored = true;
                        mStartY = tempY;
                    }
                    if ( mState != REFRESHING && mIsRecored
                            && mState != LOADING ) {
                        // 保证在设置padding的过程中,当前的位置一直是在head,否则如果当列表超出屏幕的话,当在上推的时候,列表会同时进行滚动
                        // 可以松手去刷新了
                        if ( mState == RELEASE_TO_REFRESH ) {
                            setSelection( 0 );
                            // 往上推了,推到了屏幕足够掩盖head的程度,但是还没有推到全部掩盖的地步
                            if ( ( ( tempY - mStartY ) / RATIO < mHeadContentHeight )
                                    && ( tempY - mStartY ) > 0 ) {
                                mState = PULL_TO_REFRESH;
                                changeHeaderViewByState();
                            }
                            // 一下子推到顶了
                            else if ( tempY - mStartY <= 0 ) {
                                mState = DONE;
                                changeHeaderViewByState();
                            }
                            // 往下拉了,或者还没有上推到屏幕顶部掩盖head的地步
                            else {
                                // 不用进行特别的操作,只用更新paddingTop的值就行了
                            }
                        }
                        // 还没有到达显示松开刷新的时候,DONE或者是PULL_To_REFRESH状态
                        if ( mState == PULL_TO_REFRESH ) {
                            setSelection( 0 );
                            // 下拉到可以进入RELEASE_TO_REFRESH的状态
                            if ( ( tempY - mStartY ) / RATIO >= mHeadContentHeight ) {
                                mState = RELEASE_TO_REFRESH;
                                mIsBack = true;
                                changeHeaderViewByState();
                            }
                            // 上推到顶了
                            else if ( tempY - mStartY <= 0 ) {
                                mState = DONE;
                                changeHeaderViewByState();
                            }
                        }
                        // done状态下
                        if ( mState == DONE ) {
                            if ( tempY - mStartY > 0 ) {
                                mState = PULL_TO_REFRESH;
                                changeHeaderViewByState();
                            }
                        }
                        // 更新headView的size
                        if ( mState == PULL_TO_REFRESH ) {
                            mRefreshView.setPadding( 0, -1 * mHeadContentHeight
                                    + ( tempY - mStartY ) / RATIO, 0, 0 );
                        }
                        // 更新headView的paddingTop
                        if ( mState == RELEASE_TO_REFRESH ) {
                            mRefreshView.setPadding( 0, ( tempY - mStartY )
                                    / RATIO - mHeadContentHeight, 0, 0 );
                        }
                    }
                    break;
            }
        }
        return super.onTouchEvent( event );
    }

    public void changeHeaderViewByState() {
        switch ( mState ) {
        // 松开刷新状态
            case RELEASE_TO_REFRESH:
                mArrowImageView.setVisibility( View.VISIBLE );
                mProgressBar.setVisibility( View.GONE );
                mTipsTextview.setVisibility( View.VISIBLE );
                mLastUpdatedTextView.setVisibility( View.VISIBLE );
                mArrowImageView.clearAnimation();
                mArrowImageView.startAnimation( mAnimation );
                mTipsTextview.setText( R.string.scroll_refresh_release_text );
                break;
            // 下拉刷新
            case PULL_TO_REFRESH:
                mProgressBar.setVisibility( View.GONE );
                mTipsTextview.setVisibility( View.VISIBLE );
                mLastUpdatedTextView.setVisibility( View.VISIBLE );
                mArrowImageView.clearAnimation();
                mArrowImageView.setVisibility( View.VISIBLE );
                // 是由RELEASE_To_REFRESH状态转变来的
                // 箭头反转向上
                if ( mIsBack ) {
                    mIsBack = false;
                    mArrowImageView.clearAnimation();
                    mArrowImageView.startAnimation( mReverseAnimation );
                    mTipsTextview.setText( R.string.scroll_refresh_text );
                }
                else {
                    mTipsTextview.setText( R.string.scroll_refresh_text );
                }
                break;
            // 刷新中 状态
            case REFRESHING:
                mRefreshView.setPadding( 0, 0, 0, 0 );
                mProgressBar.setVisibility( View.VISIBLE );
                mArrowImageView.clearAnimation();
                mArrowImageView.setVisibility( View.GONE );
                mTipsTextview.setText( R.string.append_loading );
                mLastUpdatedTextView.setVisibility( View.VISIBLE );
                break;
            // 刷新完毕
            case DONE:
                mRefreshView.setPadding( 0, -1 * mHeadContentHeight, 0, 0 );
                mProgressBar.setVisibility( View.GONE );
                mArrowImageView.clearAnimation();
                mArrowImageView
                        .setImageResource( R.drawable.ic_pulltorefresh_arrow );
                mTipsTextview.setText( R.string.scroll_refresh_text );
                mLastUpdatedTextView.setVisibility( View.VISIBLE );
                break;
        }
    }

    public void setOnRefreshListener( onRefreshListener refreshListener ) {
        this.mRefreshListener = refreshListener;
        mIsRefreshable = true;
    }

    public void onRefreshComplete() {
        mState = DONE;

        mLastUpdatedTextView.setText( mContext
                .getString( R.string.last_update_text )
                + TimeUtils.getCurrentDateTime() );

        changeHeaderViewByState();
    }

    private void onRefresh() {
        if ( mRefreshListener != null ) {
            mRefreshListener.onRefresh();
        }
    }

    // 估计headView的width以及height
    private void measureView( View child ) {
        ViewGroup.LayoutParams p = child.getLayoutParams();
        if ( p == null ) {
            p = new ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT );
        }
        int childWidthSpec = ViewGroup.getChildMeasureSpec( 0, 0 + 0, p.width );
        int lpHeight = p.height;
        int childHeightSpec;
        if ( lpHeight > 0 ) {
            childHeightSpec = MeasureSpec.makeMeasureSpec( lpHeight,
                    MeasureSpec.EXACTLY );
        }
        else {
            childHeightSpec = MeasureSpec.makeMeasureSpec( 0,
                    MeasureSpec.UNSPECIFIED );
        }
        child.measure( childWidthSpec, childHeightSpec );
    }

    public void setAdapter( BaseAdapter aAdapter ) {
        mLastUpdatedTextView.setText( mContext
                .getString( R.string.scroll_refresh_last_text )
                + TimeUtils.getCurrentDateTime() );
        super.setAdapter( aAdapter );
    }

    public void setState( int aState ) {
        mState = aState;
    }

    public void setOnResizeListener( OnResizeListener aListener ) {
        mOnResizeListener = aListener;
    }

    @Override
    protected void onSizeChanged( int w, int h, int oldw, int oldh ) {
        super.onSizeChanged( w, h, oldw, oldh );

        if ( mOnResizeListener != null ) {
            mOnResizeListener.OnResize( w, h, oldw, oldh );
        }

    }

    public void setListFooterView( int aView ) {
        removeFooterView( mEmptyView );
        removeFooterView( mListFooter );

        if ( aView == FOOTER_VIEW_MORE ) {
            addFooterView( mListFooter );
            mBtnAppend.setVisibility( View.VISIBLE );
        }
        else if ( aView == FOOTER_VIEW_EMPTY ) {
            addFooterView( mEmptyView );
        }
    }

    public void removeListFooterView( int aView ) {
        removeFooterView( mEmptyView );
        removeFooterView( mListFooter );
        if ( aView == FOOTER_VIEW_EMPTY ) {
            addFooterView( mEmptyView );
        }
    }

    public void setEmptyViewText( int resId ) {
        if ( mEmptyView != null ) {
            ( ( EmptyView ) mEmptyView ).setEmptyText( resId );
        }
    }

    public void setLoadMoreComplete() {
        mBtnAppend.setLoading( false );
    }

    public void setHeaderView( boolean aEnable ) {
        if ( aEnable ) {
            addHeaderView( mRefreshView, null, false );
        }
        else {
            removeHeaderView( mRefreshView );
        }
    }

    public void refreshSelf() {
        int tempStartY = 0;
        int tempY = tempStartY + mHeadContentHeight * RATIO + 200;
        long downTime = SystemClock.uptimeMillis();
        MotionEvent downEvent = MotionEvent.obtain( downTime,
                SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN,
                tempStartY, tempStartY, 0 );
        MotionEvent moveEvent = MotionEvent.obtain( downTime,
                SystemClock.uptimeMillis(), MotionEvent.ACTION_MOVE,
                tempStartY, tempY, 0 );
        MotionEvent moveEvent2 = MotionEvent.obtain( downTime,
                SystemClock.uptimeMillis(), MotionEvent.ACTION_MOVE,
                tempStartY, tempY + 10, 0 );
        MotionEvent upEvent = MotionEvent.obtain( downTime,
                SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, tempStartY,
                tempY + 20, 0 );
        onTouchEvent( downEvent );
        onTouchEvent( moveEvent );
        onTouchEvent( moveEvent2 );
        onTouchEvent( upEvent );
        downEvent.recycle();
        moveEvent.recycle();
        upEvent.recycle();
    }
}

 

 

package com.baoy.demo.demoscrollrefreshlist.view;

import com.baoy.demo.demoscrollrefreshlist.R;
import com.baoy.demo.demoscrollrefreshlist.util.TimeUtils;

import android.content.Context;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.BaseAdapter;
import android.widget.ExpandableListView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
 

public class ScrollRefreshExpandableListView extends ExpandableListView implements OnScrollListener {
	public static final String id = "ScrollRefreshListView";

	public static final int FOOTER_VIEW_NONE = 0;
	public static final int FOOTER_VIEW_MORE = 1;
	public static final int FOOTER_VIEW_EMPTY = 2;

	private final static int RELEASE_TO_REFRESH = 0; // 释放
	private final static int PULL_TO_REFRESH = 1; // 下拉刷新
	public final static int REFRESHING = 2; // 正在刷新
	private final static int DONE = 3; // 按下
	private final static int LOADING = 4;
	// 实际的padding的距离与界面上偏移距离的比例
	private final static int RATIO = 3;

	private LayoutInflater mInflater;
	private LinearLayout mRefreshView;
	private TextView mTipsTextview;
	private TextView mLastUpdatedTextView;
	private ImageView mArrowImageView;
	private ProgressBar mProgressBar;
	private RotateAnimation mAnimation;
	private RotateAnimation mReverseAnimation;
	// 用于保证startY的值在一个完整的touch事件中只被记录一次
	private boolean mIsRecored;
	private int mHeadContentWidth;
	private int mHeadContentHeight;
	private int mStartY;
	private int mFirstItemIndex;
	private int mState;
	private boolean mIsBack;
	private onRefreshListener mRefreshListener;
	private boolean mIsRefreshable;
	private Context mContext;

	private View mListFooter;
	private View mEmptyView;
	private AppendButton mBtnAppend;

	private OnResizeListener mOnResizeListener;

	public interface onRefreshListener {
		public void onRefresh();

		public void onLoadMore();
	}

	public interface OnResizeListener {
		void OnResize(int w, int h, int oldw, int oldh);
	}

	public ScrollRefreshExpandableListView(Context context) {
		super(context);
		mContext = context;

		init(context);
	}

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

		init(context);
	}

	private void init(Context context) {
		mInflater = LayoutInflater.from(context);
		// head 布局文件
		mRefreshView = (LinearLayout) mInflater.inflate(
				R.layout.scroll_refresh_head, null);
		// 下拉箭头
		mArrowImageView = (ImageView) mRefreshView
				.findViewById(R.id.head_arrowImageView);
		mArrowImageView.setMinimumWidth(70);
		mArrowImageView.setMinimumHeight(50);
		// 进度条
		mProgressBar = (ProgressBar) mRefreshView
				.findViewById(R.id.head_progressBar);
		// 下拉提示刷新
		mTipsTextview = (TextView) mRefreshView
				.findViewById(R.id.head_tipsTextView);
		// 最新一次刷新时间
		mLastUpdatedTextView = (TextView) mRefreshView
				.findViewById(R.id.head_lastUpdatedTextView);
		// 计算head的高宽
		measureView(mRefreshView);
		mHeadContentHeight = mRefreshView.getMeasuredHeight();
		mHeadContentWidth = mRefreshView.getMeasuredWidth();
		// 初始状态是 隐藏掉head 布局
		mRefreshView.setPadding(0, -1 * mHeadContentHeight, 0, 0);
		mRefreshView.invalidate();
		Log.v("size", "width:" + mHeadContentWidth + " height:"
				+ mHeadContentHeight);
		// list添加头文件

		addHeaderView(mRefreshView, null, false);
		setOnScrollListener(this);
		// 下拉以及恢复动画
		mAnimation = new RotateAnimation(0, -180,
				RotateAnimation.RELATIVE_TO_SELF, 0.5f,
				RotateAnimation.RELATIVE_TO_SELF, 0.5f);
		mAnimation.setInterpolator(new LinearInterpolator());
		mAnimation.setDuration(250);
		mAnimation.setFillAfter(true);
		mReverseAnimation = new RotateAnimation(-180, 0,
				RotateAnimation.RELATIVE_TO_SELF, 0.5f,
				RotateAnimation.RELATIVE_TO_SELF, 0.5f);
		mReverseAnimation.setInterpolator(new LinearInterpolator());
		mReverseAnimation.setDuration(200);
		mReverseAnimation.setFillAfter(true);
		mState = DONE;
		mIsRefreshable = false;
		System.out.println("mListFooter:" + mListFooter + ",,mListFooter:"
				+ mListFooter);
		mListFooter = mInflater.inflate(R.layout.listfooter, null);
		System.out.println("mListFooter:" + mListFooter );
		mBtnAppend = (AppendButton) mListFooter.findViewById(R.id.appender);
		mBtnAppend.setVisibility(View.GONE);
		mEmptyView = new EmptyView(mContext);

		addFooterView(mListFooter);
		mBtnAppend.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {

				mBtnAppend.setVisibility(View.VISIBLE);
				mBtnAppend.setLoading(true);
				mRefreshListener.onLoadMore();
			}
		});

	}

	public void onScroll(AbsListView arg0, int firstVisiableItem, int arg2,
			int arg3) {
		mFirstItemIndex = firstVisiableItem;
	}

	public void onScrollStateChanged(AbsListView arg0, int scrollState) {
	}

	public boolean onTouchEvent(MotionEvent event) {

		if (mIsRefreshable) {
			switch (event.getAction()) {
			// 在down时候记录当前Y的位置
			case MotionEvent.ACTION_DOWN:
				if (mFirstItemIndex == 0 && !mIsRecored) {
					mIsRecored = true;
					mStartY = (int) event.getY();
				}
				break;
			case MotionEvent.ACTION_UP:
				if (mState != REFRESHING && mState != LOADING) {
					if (mState == DONE) {
						// 什么都不做
					}
					// 由下拉刷新状态,到done状态
					if (mState == PULL_TO_REFRESH) {
						mState = DONE;
						changeHeaderViewByState();
					}

					if (mState == RELEASE_TO_REFRESH) {
						mState = REFRESHING;
						changeHeaderViewByState();
						onRefresh();
					}
				}
				mIsRecored = false;
				mIsBack = false;
				break;

			case MotionEvent.ACTION_MOVE:
				int tempY = (int) event.getY();
				if (!mIsRecored && mFirstItemIndex == 0) {
					mIsRecored = true;
					mStartY = tempY;
				}
				if (mState != REFRESHING && mIsRecored && mState != LOADING) {
					// 保证在设置padding的过程中,当前的位置一直是在head,否则如果当列表超出屏幕的话,当在上推的时候,列表会同时进行滚动
					// 可以松手去刷新了
					if (mState == RELEASE_TO_REFRESH) {
						setSelection(0);
						// 往上推了,推到了屏幕足够掩盖head的程度,但是还没有推到全部掩盖的地步
						if (((tempY - mStartY) / RATIO < mHeadContentHeight)
								&& (tempY - mStartY) > 0) {
							mState = PULL_TO_REFRESH;
							changeHeaderViewByState();
						}
						// 一下子推到顶了
						else if (tempY - mStartY <= 0) {
							mState = DONE;
							changeHeaderViewByState();
						}
						// 往下拉了,或者还没有上推到屏幕顶部掩盖head的地步
						else {
							// 不用进行特别的操作,只用更新paddingTop的值就行了
						}
					}
					// 还没有到达显示松开刷新的时候,DONE或者是PULL_To_REFRESH状态
					if (mState == PULL_TO_REFRESH) {
						setSelection(0);
						// 下拉到可以进入RELEASE_TO_REFRESH的状态
						if ((tempY - mStartY) / RATIO >= mHeadContentHeight) {
							mState = RELEASE_TO_REFRESH;
							mIsBack = true;
							changeHeaderViewByState();
						}
						// 上推到顶了
						else if (tempY - mStartY <= 0) {
							mState = DONE;
							changeHeaderViewByState();
						}
					}
					// done状态下
					if (mState == DONE) {
						if (tempY - mStartY > 0) {
							mState = PULL_TO_REFRESH;
							changeHeaderViewByState();
						}
					}
					// 更新headView的size
					if (mState == PULL_TO_REFRESH) {
						mRefreshView.setPadding(0, -1 * mHeadContentHeight
								+ (tempY - mStartY) / RATIO, 0, 0);
					}
					// 更新headView的paddingTop
					if (mState == RELEASE_TO_REFRESH) {
						mRefreshView.setPadding(0, (tempY - mStartY) / RATIO
								- mHeadContentHeight, 0, 0);
					}
				}
				break;
			}
		}
		return super.onTouchEvent(event);
	}

	public void changeHeaderViewByState() {
		switch (mState) {
		// 松开刷新状态
		case RELEASE_TO_REFRESH:
			mArrowImageView.setVisibility(View.VISIBLE);
			mProgressBar.setVisibility(View.GONE);
			mTipsTextview.setVisibility(View.VISIBLE);
			mLastUpdatedTextView.setVisibility(View.VISIBLE);
			mArrowImageView.clearAnimation();
			mArrowImageView.startAnimation(mAnimation);
			mTipsTextview.setText(R.string.scroll_refresh_release_text);
			break;
		// 下拉刷新
		case PULL_TO_REFRESH:
			mProgressBar.setVisibility(View.GONE);
			mTipsTextview.setVisibility(View.VISIBLE);
			mLastUpdatedTextView.setVisibility(View.VISIBLE);
			mArrowImageView.clearAnimation();
			mArrowImageView.setVisibility(View.VISIBLE);
			// 是由RELEASE_To_REFRESH状态转变来的
			// 箭头反转向上
			if (mIsBack) {
				mIsBack = false;
				mArrowImageView.clearAnimation();
				mArrowImageView.startAnimation(mReverseAnimation);
				mTipsTextview.setText(R.string.scroll_refresh_text);
			} else {
				mTipsTextview.setText(R.string.scroll_refresh_text);
			}
			break;
		// 刷新中 状态
		case REFRESHING:
			mRefreshView.setPadding(0, 0, 0, 0);
			mProgressBar.setVisibility(View.VISIBLE);
			mArrowImageView.clearAnimation();
			mArrowImageView.setVisibility(View.GONE);
			mTipsTextview.setText(R.string.append_loading);
			mLastUpdatedTextView.setVisibility(View.VISIBLE);
			break;
		// 刷新完毕
		case DONE:
			mRefreshView.setPadding(0, -1 * mHeadContentHeight, 0, 0);
			mProgressBar.setVisibility(View.GONE);
			mArrowImageView.clearAnimation();
			mArrowImageView.setImageResource(R.drawable.ic_pulltorefresh_arrow);
			mTipsTextview.setText(R.string.scroll_refresh_text);
			mLastUpdatedTextView.setVisibility(View.VISIBLE);
			break;
		}
	}

	public void setOnRefreshListener(onRefreshListener refreshListener) {
		this.mRefreshListener = refreshListener;
		mIsRefreshable = true;
	}

	public void onRefreshComplete() {
		mState = DONE;

		mLastUpdatedTextView.setText(mContext
				.getString(R.string.last_update_text)
				+ TimeUtils.getCurrentDateTime());

		changeHeaderViewByState();
	}

	private void onRefresh() {
		if (mRefreshListener != null) {
			mRefreshListener.onRefresh();
		}
	}

	// 估计headView的width以及height
	private void measureView(View child) {
		ViewGroup.LayoutParams p = child.getLayoutParams();
		if (p == null) {
			p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
					ViewGroup.LayoutParams.WRAP_CONTENT);
		}
		int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, p.width);
		int lpHeight = p.height;
		int childHeightSpec;
		if (lpHeight > 0) {
			childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight,
					MeasureSpec.EXACTLY);
		} else {
			childHeightSpec = MeasureSpec.makeMeasureSpec(0,
					MeasureSpec.UNSPECIFIED);
		}
		child.measure(childWidthSpec, childHeightSpec);
	}

	public void setAdapter(BaseAdapter aAdapter) {
		mLastUpdatedTextView.setText(mContext
				.getString(R.string.scroll_refresh_last_text)
				+ TimeUtils.getCurrentDateTime());
		super.setAdapter(aAdapter);
	}

	public void setState(int aState) {
		mState = aState;
	}

	public void setOnResizeListener(OnResizeListener aListener) {
		mOnResizeListener = aListener;
	}

	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);

		if (mOnResizeListener != null) {
			mOnResizeListener.OnResize(w, h, oldw, oldh);
		}

	}

	public void setListFooterView(int aView) {
		removeFooterView(mEmptyView);
		removeFooterView(mListFooter);

		if (aView == FOOTER_VIEW_MORE) {
			addFooterView(mListFooter);
			mBtnAppend.setVisibility(View.VISIBLE);
		} else if (aView == FOOTER_VIEW_EMPTY) {
			addFooterView(mEmptyView);
		}
	}
	
	public void removeListFooterView(int aView){
        removeFooterView(mListFooter);
		removeFooterView(mEmptyView);
        if (aView == FOOTER_VIEW_EMPTY) {
            addFooterView(mEmptyView);
        }
    }

	public void setLoadMoreComplete() {
		mBtnAppend.setLoading(false);
	}

	public void setHeaderView(boolean aEnable) {
		if (aEnable) {
			addHeaderView(mRefreshView, null, false);
		} else {
			removeHeaderView(mRefreshView);
		}
	}
	public void setEmptyViewText(int resId) {
		if (mEmptyView != null) {
			((EmptyView) mEmptyView).setEmptyText(resId);
		}
	}
	public void setEmptyViewText(String text) {
		if (mEmptyView != null) {
			((EmptyView) mEmptyView).setEmptyText(text);
		}
	}
	
	public void refreshSelf(){
		int tempStartY = 0;
		int tempY = tempStartY + mHeadContentHeight * RATIO + 200;
		long downTime = SystemClock.uptimeMillis();
		MotionEvent downEvent = MotionEvent.obtain(downTime,
				SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN,
				tempStartY, tempStartY, 0);
		MotionEvent moveEvent = MotionEvent.obtain(downTime,
				SystemClock.uptimeMillis(), MotionEvent.ACTION_MOVE,
				tempStartY, tempY, 0);
		MotionEvent moveEvent2 = MotionEvent.obtain(downTime,
				SystemClock.uptimeMillis(), MotionEvent.ACTION_MOVE,
				tempStartY, tempY + 10, 0);
		MotionEvent upEvent = MotionEvent.obtain(downTime,
				SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, tempStartY,
				tempY + 20, 0);
		onTouchEvent(downEvent);
		onTouchEvent(moveEvent);
		onTouchEvent(moveEvent2);
		onTouchEvent(upEvent);
		downEvent.recycle();
		moveEvent.recycle();
		upEvent.recycle();
	}
}

 

 

 

 

 

 

 

 

 

 

 

 

 

捐助开发者

在兴趣的驱动下,写一个免费的东西,有欣喜,也还有汗水,希望你喜欢我的作品,同时也能支持一下。 当然,有钱捧个钱场(右上角的爱心标志,支持支付宝和PayPal捐助),没钱捧个人场,谢谢各位。



 
 
 谢谢您的赞助,我会做的更好!

 

 

目录
相关文章
|
6月前
|
数据建模 Java 开发工具
Android bugreport的使用
Android bugreport的使用
107 0
|
存储 安全 物联网
Android:Android 应用权限详解
这篇文章为大家系统的梳理一下 Android 权限相关的知识,在日常开发中,我们都用过权限,但是对于权限的一些细节我们可能掌握的还不够全面,这篇文章会全面的为大家介绍权限相关的知识。
1111 0
Android:Android 应用权限详解
|
安全 编译器 API
Now in Android #15 —— 最新 Android 知识分享
Now in Android #15 —— 最新 Android 知识分享
Now in Android #15 —— 最新 Android 知识分享
|
传感器 存储 SQL
Android 值得学【Android 专题 2】
Android 系统到底提供了哪些东西,供我们可以开发出优秀的应用程序。 四大组件 Android 系统四大组件分别是活动(Activity)、服务(Service)、广播接收器(BroadcastReceiver)和内容提供器(Content Provider)。其中活动是所有 Android 应用程序的门面,凡是在应用中你看得到的东西,都是放在活动中的。而服务就比较低调了,你无法看到它,但它会一直在后台默默地运行,即使用户退出了应用,服务仍然是可以继续运行的。广播接收器可以应用接收来自各处的广播消息,比如电话、短信等,当然你的应用同样也可以向外发出广播消息。内容提供器则为应用程序之间共享数
121 0
|
Android开发 数据格式 XML
|
Android开发 API
Android BaseRecyclerViewAdapterHelper使用
BaseRecyclerViewAdapterHelper项目下载 1 . 使用 // 基类 具体实现类 布局 数据源 ...
2424 0
|
存储 Java 数据库