android scrollrefreshlist_第1张图片

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;@Overrideprotected 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;} }};@Overridepublic void onRefresh() { doHandle(1);}@Overridepublic void onLoadMore() { doHandle(2);}@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position,long id) { }@Overridepublic 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 inflaterprotected int mResource; // item layout resourceprotected ArrayList<?> mData; // list dataprotected Context mContext; // parentprotected 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);}@Overridepublic int getCount() {return mData.size();}@Overridepublic Object getItem(int position) {return mData.get(position);}@Overridepublic long getItemId(int position) {return position;}@Overridepublic 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();}@Overridepublic 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;}@Overridepublic void onClick(View v) { }@Overridepublic int getCount() {if (mDataList == null) {return 0;}return mDataList.size();}@Overridepublic 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);}@Overridepublic 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.ScrollRefreshListViewimport 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() {@Overridepublic 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的sizeif (mState == PULL_TO_REFRESH) {mRefreshView.setPadding(0, -1 * mHeadContentHeight+ (tempY - mStartY) / RATIO, 0, 0);}// 更新headView的paddingTopif (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以及heightprivate 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;}@Overrideprotected 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();}}

更多相关文章

  1. android8.0屏蔽状态栏下拉
  2. Android手机屏幕的三种状态
  3. Android沉浸式状态栏(二)
  4. 沉浸式状态栏StatusBar
  5. Android全屏,隐藏状态栏和标题栏
  6. Android沉浸式状态栏、导航栏
  7. android 状态栏 时间 错误 adb连接
  8. Android状态机
  9. android设置状态栏颜色

随机推荐

  1. Android实现图片验证码
  2. android Webview 自适应屏幕
  3. Android(安卓)自定义view组件
  4. android ImageLoader加载本地图片的工具
  5. android通过led实现手电筒
  6. Android memory leak detection
  7. Compilation failed to complete:Program
  8. Android开发04—Android常用高级控件(上)
  9. android Seekbar双滑块滑动
  10. Android使用OpenGL(GLSurfaceView)视频画