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捐助),没钱捧个人场,谢谢各位。



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

 

 

目录
相关文章
|
Android开发 安全 数据格式
Android LocalBroadcastManager 的使用总结
转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/53105494 本文出自【赵彦军的博客】 前言 在Android中,Broadcast是一种广泛运用的在应用程序之间传输信息的机制。
1286 0
|
Dart Android开发 Kotlin
android - FlutterActivity MethodChannel和FlutterView
android - FlutterActivity MethodChannel和FlutterView 因此,大约4个月前,我编写了Flutter应用程序。现在,我想做一个小小的更改,但是我不能再编译应用程序了,因为GeneratedPluginRegistrant.registerWith(this)不再起作用了,我没有更改Kotlin代码,只更改了Dart代码。
266 0
|
算法 Android开发
Android的路接下来该怎么走?
其实想写这篇文章好久了,很多小伙伴们也经常在群里探讨android移动开发者的走向,一部分人都想多快好省,间歇性踌躇满志、持续性混吃等死 ,只想用CV的开发模式们快速完成工作,然后回家王者农药。其实这种现象很普遍,我想告诉你的是 ,只要你走对方向,不断地学习,android的春天依然是健在的。
8833 0
|
Android开发
android 记一次解决键盘遮挡问题
文章链接:https://mp.weixin.qq.com/s/1gkMtLu0BTXOUOj6isDjUw 日常android开发过程中,会遇到编辑框输入内容弹出软键盘,往往会出现键盘遮挡内容,或者出现页面整体上移的,或多或少在体验上都不是很优雅,今天提供个方法是自行控制页面上移距离,竟可能让页面呈现给用户友好点。
2432 0
|
编解码 Java Android开发
Android小知识10则(上)(2018.8重编版)
Android小知识10则(下) 目录 前言 横竖屏锁定 不同分辨率的图标 将字符串写在资源文件中 为AlertDialog设置点击监听 ProgressDialog了解一下 最后 前言 Android的知识还是比较碎的, 日常积累很重要.
1027 0
|
定位技术 Android开发 UED
|
XML Android开发 数据格式