最近学习了下拉刷新的方法,写在这里做个笔记,也跟大家分享一下。
MainActivity 类
LoadMyCourseAsyncTask 类
InitData 类
MyCourseAdapter类
GetTime类
Constants类
PullToRefreshListView类 (此类不是自己写的)
<?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2011 Johan Nilsson <http://markupartist.com> Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center" android:paddingBottom="15dip" android:paddingTop="10dip" > <!-- 小型圆形进度条,初始为不可见 --> <ProgressBar android:id="@+id/pull_to_refresh_progress" style="?android:attr/progressBarStyleSmall" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginLeft="30dip" android:layout_marginRight="20dip" android:layout_marginTop="10dip" android:indeterminate="true" android:visibility="gone" /> <!-- 下拉刷新的那个箭头 --> <ImageView android:id="@+id/pull_to_refresh_image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginLeft="30dip" android:layout_marginRight="20dip" android:gravity="center" android:src="@drawable/ic_pulltorefresh_arrow" android:visibility="gone" /> <!-- 下拉刷新的提示文本 --> <TextView android:id="@+id/pull_to_refresh_text" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:gravity="center" android:paddingTop="5dip" android:text="@string/pull_to_refresh_tap_label" android:textAppearance="?android:attr/textAppearanceMedium" android:textStyle="bold" /> <TextView android:id="@+id/pull_to_refresh_updated_at" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_below="@+id/pull_to_refresh_text" android:layout_gravity="center" android:gravity="center" android:textAppearance="?android:attr/textAppearanceSmall" android:visibility="gone" /> </RelativeLayout>
<?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" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginLeft="5sp" android:layout_marginRight="5sp" android:orientation="horizontal" > <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_weight="1" android:orientation="vertical" > <TextView android:id="@+id/mycourse_id" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:singleLine="true" android:text="001" android:visibility="gone" android:textSize="14sp" /> <TextView android:id="@+id/mycourse_class_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="小苹果速成2班" android:textColor="#475de0" android:textSize="12sp" /> </LinearLayout> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="vertical" > <TextView android:id="@+id/mycourse_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:gravity="center" android:text="《小苹果是怎么炼成的10》" android:textSize="22sp" /> <TextView android:id="@+id/mycourese_active" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="right" android:layout_marginRight="22sp" android:text="已购" android:textColor="#9ec762" android:textSize="10sp" /> </LinearLayout> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_weight="1" android:orientation="vertical" > <TextView android:id="@+id/mycourse_date" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_gravity="center" android:layout_marginTop="4sp" android:gravity="center" android:text="每周三下午第7节" android:textColor="#e09647" android:textSize="12sp" /> </LinearLayout> </LinearLayout> </RelativeLayout>
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/loadmore_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:paddingBottom="15dip" android:paddingTop="10dip" > <!-- <Button android:id="@+id/loadmore_btn" android:layout_width="match_parent" android:layout_height="60.0dip" android:layout_centerHorizontal="true" android:layout_marginTop="0.0dip" android:background="@drawable/weibo_list_item_selector" android:text="@string/loadmore_label" android:textColor="@color/loadmore_btn_selector" android:textSize="18.0sp" /> --> <ProgressBar android:id="@+id/loadmore_progress" style="?android:attr/progressBarStyleSmall" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginLeft="30dip" android:layout_marginRight="20dip" android:layout_marginTop="10dip" android:indeterminate="true" android:visibility="gone" /> <TextView android:id="@+id/loadmore_text" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:gravity="center" android:paddingTop="5dip" android:text="@string/loadmore_label" android:textAppearance="?android:attr/textAppearanceMedium" android:textStyle="bold" /> </RelativeLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <com.example.testpulltorefreshlistview.views.PullToRefreshListView android:id="@+id/academy_mycourse_list" android:layout_width="match_parent" android:layout_height="match_parent" android:cacheColorHint="#00000000" android:divider="#19000000" android:dividerHeight="4dp" android:fadingEdge="none" android:fastScrollEnabled="false" android:footerDividersEnabled="true" android:headerDividersEnabled="false" android:smoothScrollbar="true" /> </LinearLayout>
MainActivity 类
package com.example.testpulltorefreshlistview; import java.util.List; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.Menu; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.Toast; import com.example.testpulltorefreshlistview.adapter.MyCourseAdapter; import com.example.testpulltorefreshlistview.bean.MyCourseBean; import com.example.testpulltorefreshlistview.constants.Constants; import com.example.testpulltorefreshlistview.util.GetTime; import com.example.testpulltorefreshlistview.views.PullToRefreshListView; import com.example.testpulltorefreshlistview.views.PullToRefreshListView.OnRefreshListener; /** * 主界面 *@author Changel *@version 2014.07.22.1 * */ public class MainActivity extends Activity { private PullToRefreshListView myListView = null; private List<MyCourseBean> myList = null; private MyCourseAdapter myAdapter = null; private Handler mHandler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mHandler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case 0x123: myList = (List<MyCourseBean>) msg.obj; //设置适配器,刷新列表 myAdapter = new MyCourseAdapter(MainActivity.this, myList); myListView.setAdapter(myAdapter); break; case 0x124: myList = (List<MyCourseBean>) msg.obj; //设置适配器,刷新列表 myAdapter = new MyCourseAdapter(MainActivity.this, myList); myListView.setAdapter(myAdapter); Toast.makeText(MainActivity.this, "刷新成功", Toast.LENGTH_SHORT).show(); myListView.onRefreshComplete(GetTime.getLocalTime()); break; case 0x125: myList = (List<MyCourseBean>) msg.obj; //设置适配器,刷新列表 myAdapter = new MyCourseAdapter(MainActivity.this, myList); myListView.setAdapter(myAdapter); Toast.makeText(MainActivity.this, "加载成功", Toast.LENGTH_SHORT).show(); myListView.onRefreshComplete(GetTime.getLocalTime()); myListView.onLoadMoreComplete(); break; } } }; //初始化界面 initListView(); //启动异步线程加载数据 new LoadMyCourseAsyncTask(MainActivity.this, Constants.FIRST_LOAD, mHandler).execute(); } /** * 初始化界面 * 绑定下拉刷新和加载更多的监听器 * * */ public void initListView() { myListView = (PullToRefreshListView) findViewById(R.id.academy_mycourse_list); myListView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int positon, long arg3) { //点击每一项触发的方法 Toast.makeText(MainActivity.this, "单项点击!", positon-1).show(); } }); myListView.setOnRefreshListener(new OnRefreshListener() { @Override //下拉时触发的方法 public void onRefresh() { new LoadMyCourseAsyncTask(MainActivity.this, Constants.REFRESH, mHandler).execute(); } @Override //点击加载更多触发的方法 public void onLoadMore() { new LoadMyCourseAsyncTask(MainActivity.this, Constants.MORE_LOAD, mHandler).execute(); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }
LoadMyCourseAsyncTask 类
package com.example.testpulltorefreshlistview; import java.util.List; import android.app.ProgressDialog; import android.content.Context; import android.os.AsyncTask; import android.os.Handler; import android.os.Message; import com.example.testpulltorefreshlistview.bean.MyCourseBean; import com.example.testpulltorefreshlistview.constants.Constants; import com.example.testpulltorefreshlistview.util.InitData; /** * * 继承AsyncTask类,用异步线程来加载数据,在向主界面发送加载的信息 * * @author Changel<373386733@qq.com> * @version 2014.07.22.1 * */ public class LoadMyCourseAsyncTask extends AsyncTask<String, Integer, List<MyCourseBean>> { private Context context; private int flag; private Handler mHandler; private ProgressDialog progressDialog; public LoadMyCourseAsyncTask(Context context, int flag, Handler mHandler) { this.context = context; this.flag = flag; this.mHandler = mHandler; } @Override protected void onPostExecute(List<MyCourseBean> result) { Message msg = Message.obtain(); msg.obj = result; msg.what = flag; mHandler.sendMessage(msg); if (flag == Constants.FIRST_LOAD) { progressDialog.dismiss(); } } @Override protected void onPreExecute() { if (flag == Constants.FIRST_LOAD) { progressDialog = new ProgressDialog(context); progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);// 设置进度条的模型,有矩形,圆圈等 progressDialog.setMessage("正在获取数据"); progressDialog.onStart(); progressDialog.show(); } } @Override protected List<MyCourseBean> doInBackground(String... params) { List<MyCourseBean> myCourseList = new InitData().getCourseData(); return myCourseList; } }
InitData 类
package com.example.testpulltorefreshlistview.util; import java.util.ArrayList; import java.util.List; import com.example.testpulltorefreshlistview.bean.MyCourseBean; /** * * 模拟数据 * * @author Changel<373386733@qq.com> * @version 2014.07.22.1 * */ public class InitData { private static int i,isum; public List<MyCourseBean> getCourseData(){ List<MyCourseBean> list ; list = new ArrayList<MyCourseBean>(); isum = isum + 15; for (i=1; i < isum; i++) { MyCourseBean myCourseBean = new MyCourseBean(); myCourseBean.setmClassName("速成班"+i+"班"); myCourseBean.setmCourseActive("已购买"); myCourseBean.setmCourseDate("每周三"+"第"+i+"节"); myCourseBean.setmCourseName("《"+"小苹果是怎么炼成的"+i+"》"); myCourseBean.setmCourseId(" "+i); list.add(myCourseBean); } //模拟网络加载过程 for (int i = 0; i < 2; i++) { try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return list; } }
MyCourseAdapter类
package com.example.testpulltorefreshlistview.adapter; import java.util.List; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; import com.example.testpulltorefreshlistview.R; import com.example.testpulltorefreshlistview.bean.MyCourseBean; /** * * 继承BaseAdapter基类,构造一个Adapter来显示list的内容 * * @author Changel<373386733@qq.com> * @version 2014.07.22.1 * */ public class MyCourseAdapter extends BaseAdapter{ private List<MyCourseBean> list ; private LayoutInflater inflater; private Context context; public MyCourseAdapter(Context context ,List<MyCourseBean> list){ this.context = context; this.list = list; inflater=LayoutInflater.from(context); } @Override public int getCount() { // TODO Auto-generated method stub return list.size(); } @Override public Object getItem(int position) { // TODO Auto-generated method stub return list.get(position); } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub ViewHolder viewHolder; if(convertView==null){ convertView=inflater.inflate(R.layout.my_course_item, null); viewHolder = new ViewHolder(convertView); convertView.setTag(viewHolder); }else{ viewHolder=(ViewHolder) convertView.getTag(); } //将myCourseBean的信息显示在list上 MyCourseBean myCourseBean = list.get(position); viewHolder.getCourseIdTextView().setText(myCourseBean.getmCourseId()); viewHolder.getDateTextView().setText(myCourseBean.getmCourseDate()); viewHolder.getClassNameTextView().setText(myCourseBean.getmClassName()); viewHolder.getCourseNameTextView().setText(myCourseBean.getmCourseName()); viewHolder.getActiveTextView().setText(myCourseBean.getmCourseActive()); return convertView; } /** * * 初始化MyCourseAdapter * */ class ViewHolder{ TextView idTextView; TextView dateTextView; TextView courseNameTextView; TextView classNameTextView; TextView activeTextView; ImageView image; View view; public ViewHolder(View view){ this.view = view; } public TextView getCourseIdTextView(){ if(idTextView == null){ idTextView = (TextView)view.findViewById(R.id.mycourse_id); } return idTextView; } public TextView getDateTextView(){ if(dateTextView == null){ dateTextView = (TextView)view.findViewById(R.id.mycourse_date); } return dateTextView; } public TextView getCourseNameTextView(){ if(courseNameTextView == null){ courseNameTextView = (TextView)view.findViewById(R.id.mycourse_name); } return courseNameTextView; } public TextView getClassNameTextView(){ if(classNameTextView == null){ classNameTextView = (TextView)view.findViewById(R.id.mycourse_class_name); } return classNameTextView; } public TextView getActiveTextView(){ if(activeTextView == null){ activeTextView = (TextView)view.findViewById(R.id.mycourese_active); } return activeTextView; } } }
GetTime类
package com.example.testpulltorefreshlistview.util; import java.net.URL; import java.net.URLConnection; import java.text.SimpleDateFormat; import java.util.Date; /** * * 创建一个获取时间的Util,用于获取更新的时间 * * @author Changel<373386733@qq.com> * @version 2014.07.22.1 * */ public class GetTime { private static String timeString = null; //获取网络时间 public static String getNetTime() throws Exception{ //取得资源对象 URL url = new URL("http://www.bjtime.cn"); //生成连接对象 URLConnection uc = url.openConnection(); //发出连接 uc.connect(); long time = uc.getDate(); Date date = new Date(time); timeString = new SimpleDateFormat("yyyy-MM-dd").format(date).toString(); return timeString; } //获取本地时间 public static String getLocalTime(){ SimpleDateFormat sm=new SimpleDateFormat("yyyy-MM-dd"); timeString = sm.format(new Date()).toString(); System.out.println(timeString); return timeString; } }
Constants类
package com.example.testpulltorefreshlistview.constants; public class Constants { public final static int FIRST_LOAD = 0x123; public final static int REFRESH = 0x124; public final static int MORE_LOAD = 0x125; }
PullToRefreshListView类 (此类不是自己写的)
package com.example.testpulltorefreshlistview.views; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import android.content.Context; 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.ImageView; import android.widget.ListAdapter; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.RelativeLayout; import android.widget.TextView; import com.example.testpulltorefreshlistview.R; /** * 自定义ListView,实现OnScrollListener接口 * 此ListView是为实现"下拉刷新"和"上拉加载更多"而定制的,具体效果可参考新浪微博、腾讯微博 * */ public class PullToRefreshListView extends ListView implements OnScrollListener { private static final int TAP_TO_REFRESH = 1; // (未刷新) private static final int PULL_TO_REFRESH = 2; // 下拉刷新 private static final int RELEASE_TO_REFRESH = 3; // 释放刷新 private static final int REFRESHING = 4; // 正在刷新 private static final int TAP_TO_LOADMORE = 5; // 未加载更多 private static final int LOADING = 6; // 正在加载 private static final String TAG = "PullToRefreshListView"; private OnRefreshListener mOnRefreshListener; // 刷新监听器 /** * Listener that will receive notifications every time the list scrolls. */ private OnScrollListener mOnScrollListener; // 列表滚动监听器 private LayoutInflater mInflater; // 用于加载布局文件 private RelativeLayout mRefreshHeaderView; // 刷新视图(也就是头部那部分) private TextView mRefreshViewText; // 刷新提示文本 private ImageView mRefreshViewImage; // 刷新向上向下的那个图片 private ProgressBar mRefreshViewProgress; // 这里是圆形进度条 private TextView mRefreshViewLastUpdated; // 最近更新的文本 private RelativeLayout mLoadMoreFooterView; // 加载更多 private TextView mLoadMoreText; // 提示文本 private ProgressBar mLoadMoreProgress; // 加载更多进度条 private int mCurrentScrollState; // 当前滚动位置 private int mRefreshState; // 刷新状态 private int mLoadState; // 加载状态 private RotateAnimation mFlipAnimation; // 下拉动画 private RotateAnimation mReverseFlipAnimation; // 恢复动画 private int mRefreshViewHeight; // 刷新视图高度 private int mRefreshOriginalTopPadding; // 原始上部间隙 private int mLastMotionY; // 记录点击位置 public PullToRefreshListView(Context context) { super(context); init(context); } public PullToRefreshListView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public PullToRefreshListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context); } private void init(Context context) { // Load all of the animations we need in code rather than through XML /** 定义旋转动画 **/ // 参数:1.旋转开始的角度 2.旋转结束的角度 3. X轴伸缩模式 4.X坐标的伸缩值 5.Y轴的伸缩模式 6.Y坐标的伸缩值 mFlipAnimation = new RotateAnimation(0, -180, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f); mFlipAnimation.setInterpolator(new LinearInterpolator()); mFlipAnimation.setDuration(250); // 设置持续时间 mFlipAnimation.setFillAfter(true); // 动画执行完是否停留在执行完的状态 mReverseFlipAnimation = new RotateAnimation(-180, 0, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f); mReverseFlipAnimation.setInterpolator(new LinearInterpolator()); mReverseFlipAnimation.setDuration(250); mReverseFlipAnimation.setFillAfter(true); // 获取LayoutInflater实例对象 mInflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); // 加载下拉刷新的头部视图 mRefreshHeaderView = (RelativeLayout) mInflater.inflate( R.layout.pull_to_refresh_header, this, false); mRefreshViewText = (TextView) mRefreshHeaderView .findViewById(R.id.pull_to_refresh_text); mRefreshViewImage = (ImageView) mRefreshHeaderView .findViewById(R.id.pull_to_refresh_image); mRefreshViewProgress = (ProgressBar) mRefreshHeaderView .findViewById(R.id.pull_to_refresh_progress); mRefreshViewLastUpdated = (TextView) mRefreshHeaderView .findViewById(R.id.pull_to_refresh_updated_at); mLoadMoreFooterView = (RelativeLayout) mInflater.inflate( R.layout.loadmore_footer, this, false); mLoadMoreText = (TextView) mLoadMoreFooterView .findViewById(R.id.loadmore_text); mLoadMoreProgress = (ProgressBar) mLoadMoreFooterView .findViewById(R.id.loadmore_progress); mRefreshViewImage.setMinimumHeight(50); // 设置图片最小高度 mRefreshHeaderView.setOnClickListener(new OnClickRefreshListener()); mRefreshOriginalTopPadding = mRefreshHeaderView.getPaddingTop(); mLoadMoreFooterView.setOnClickListener(new OnClickLoadMoreListener()); mRefreshState = TAP_TO_REFRESH; // 初始刷新状态 mLoadState = TAP_TO_LOADMORE; addHeaderView(mRefreshHeaderView); // 增加头部视图 addFooterView(mLoadMoreFooterView); // 增加尾部视图 super.setOnScrollListener(this); measureView(mRefreshHeaderView); // 测量视图 mRefreshViewHeight = mRefreshHeaderView.getMeasuredHeight(); // 得到视图的高度 } @Override protected void onAttachedToWindow() { setSelection(1); // 设置当前选中的项 } @Override public void setAdapter(ListAdapter adapter) { super.setAdapter(adapter); setSelection(1); } /** * Set the listener that will receive notifications every time the list * scrolls. * * @param l * The scroll listener. */ @Override public void setOnScrollListener(AbsListView.OnScrollListener l) { mOnScrollListener = l; } /** * Register a callback to be invoked when this list should be refreshed. * 注册监听器 * * @param onRefreshListener * The callback to run. */ public void setOnRefreshListener(OnRefreshListener onRefreshListener) { mOnRefreshListener = onRefreshListener; } /** * Set a text to represent when the list was last updated. * 设置一个文本来表示最近更新的列表,显示的是最近更新列表的时间 * * @param lastUpdated * Last updated at. */ public void setLastUpdated(CharSequence lastUpdated) { if (lastUpdated != null) { mRefreshViewLastUpdated.setVisibility(View.VISIBLE); mRefreshViewLastUpdated.setText("更新于: " + lastUpdated); } else { mRefreshViewLastUpdated.setVisibility(View.GONE); } } @Override public boolean onTouchEvent(MotionEvent event) { final int y = (int) event.getY(); // 获取点击位置的Y坐标 switch (event.getAction()) { case MotionEvent.ACTION_UP: // 手指抬起 if (!isVerticalScrollBarEnabled()) { setVerticalScrollBarEnabled(true); } if (getFirstVisiblePosition() == 0 && mRefreshState != REFRESHING) { if ((mRefreshHeaderView.getBottom() > mRefreshViewHeight || mRefreshHeaderView .getTop() >= 0) && mRefreshState == RELEASE_TO_REFRESH) { // Initiate the refresh mRefreshState = REFRESHING; // 刷新状态 prepareForRefresh(); onRefresh(); } else if (mRefreshHeaderView.getBottom() < mRefreshViewHeight || mRefreshHeaderView.getTop() < 0) { // Abort refresh and scroll down below the refresh view resetHeader(); setSelection(1); } } break; case MotionEvent.ACTION_DOWN: mLastMotionY = y; break; case MotionEvent.ACTION_MOVE: applyHeaderPadding(event); break; } return super.onTouchEvent(event); } private void applyHeaderPadding(MotionEvent ev) { final int historySize = ev.getHistorySize(); // Workaround for getPointerCount() which is unavailable in 1.5 // (it's always 1 in 1.5) int pointerCount = 1; try { Method method = MotionEvent.class.getMethod("getPointerCount"); pointerCount = (Integer) method.invoke(ev); } catch (NoSuchMethodException e) { pointerCount = 1; } catch (IllegalArgumentException e) { throw e; } catch (IllegalAccessException e) { System.err.println("unexpected " + e); } catch (InvocationTargetException e) { System.err.println("unexpected " + e); } for (int h = 0; h < historySize; h++) { for (int p = 0; p < pointerCount; p++) { if (mRefreshState == RELEASE_TO_REFRESH) { if (isVerticalFadingEdgeEnabled()) { setVerticalScrollBarEnabled(false); } int historicalY = 0; try { // For Android > 2.0 Method method = MotionEvent.class.getMethod( "getHistoricalY", Integer.TYPE, Integer.TYPE); historicalY = ((Float) method.invoke(ev, p, h)) .intValue(); } catch (NoSuchMethodException e) { // For Android < 2.0 historicalY = (int) (ev.getHistoricalY(h)); } catch (IllegalArgumentException e) { throw e; } catch (IllegalAccessException e) { System.err.println("unexpected " + e); } catch (InvocationTargetException e) { System.err.println("unexpected " + e); } // Calculate the padding to apply, we divide by 1.7 to // simulate a more resistant effect during pull. int topPadding = (int) (((historicalY - mLastMotionY) - mRefreshViewHeight) / 1.7); // 设置上、下、左、右四个位置的间隙间隙 mRefreshHeaderView.setPadding( mRefreshHeaderView.getPaddingLeft(), topPadding, mRefreshHeaderView.getPaddingRight(), mRefreshHeaderView.getPaddingBottom()); } } } } /** * Sets the header padding back to original size. 设置头部填充会原始大小 */ private void resetHeaderPadding() { mRefreshHeaderView.setPadding(mRefreshHeaderView.getPaddingLeft(), mRefreshOriginalTopPadding, mRefreshHeaderView.getPaddingRight(), mRefreshHeaderView.getPaddingBottom()); } /** * Resets the header to the original state. 重新设置头部为原始状态 */ private void resetHeader() { if (mRefreshState != TAP_TO_REFRESH) { mRefreshState = TAP_TO_REFRESH; resetHeaderPadding(); // Set refresh view text to the pull label mRefreshViewText.setText(R.string.pull_to_refresh_tap_label); // Replace refresh drawable with arrow drawable mRefreshViewImage .setImageResource(R.drawable.ic_pulltorefresh_arrow); // Clear the full rotation animation mRefreshViewImage.clearAnimation(); // Hide progress bar and arrow. mRefreshViewImage.setVisibility(View.GONE); mRefreshViewProgress.setVisibility(View.GONE); } } /** * 重设ListView尾部视图为初始状态 */ private void resetFooter() { if (mLoadState != TAP_TO_LOADMORE) { mLoadState = TAP_TO_LOADMORE; // 进度条设置为不可见 mLoadMoreProgress.setVisibility(View.GONE); // 按钮的文本替换为“加载更多” mLoadMoreText.setText(R.string.loadmore_label); } } /** * 测量视图的大小 * * @param child */ 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); } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { // When the refresh view is completely visible, change the text to say // "Release to refresh..." and flip the arrow drawable. if (mCurrentScrollState == SCROLL_STATE_TOUCH_SCROLL && mRefreshState != REFRESHING) { if (firstVisibleItem == 0) { // 如果第一个可见条目为0 mRefreshViewImage.setVisibility(View.VISIBLE); // 让指示箭头变得可见 /** 如果头部视图相对与父容器的位置大于其自身高度+20或者头部视图的顶部位置>0,并且要在刷新状态不等于"释放以刷新" **/ if ((mRefreshHeaderView.getBottom() > mRefreshViewHeight + 20 || mRefreshHeaderView .getTop() >= 0) && mRefreshState != RELEASE_TO_REFRESH) { mRefreshViewText .setText(R.string.pull_to_refresh_release_label);// 设置刷新文本为"Release to refresh..." mRefreshViewImage.clearAnimation(); // 清除动画 mRefreshViewImage.startAnimation(mFlipAnimation); // 启动动画 mRefreshState = RELEASE_TO_REFRESH; // 更改刷新状态为“释放以刷新" } else if (mRefreshHeaderView.getBottom() < mRefreshViewHeight + 20 && mRefreshState != PULL_TO_REFRESH) { mRefreshViewText .setText(R.string.pull_to_refresh_pull_label);// 设置刷新文本为"Pull to refresh..." if (mRefreshState != TAP_TO_REFRESH) { mRefreshViewImage.clearAnimation(); mRefreshViewImage.startAnimation(mReverseFlipAnimation); } mRefreshState = PULL_TO_REFRESH; } } else { mRefreshViewImage.setVisibility(View.GONE); // 让刷新箭头不可见 resetHeader(); // 重新设置头部为原始状态 } } else if (mCurrentScrollState == SCROLL_STATE_FLING && firstVisibleItem == 0 && mRefreshState != REFRESHING) { setSelection(1); } if (mOnScrollListener != null) { mOnScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount); } } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { mCurrentScrollState = scrollState; if (mOnScrollListener != null) { mOnScrollListener.onScrollStateChanged(view, scrollState); } } /** 为刷新做准备 **/ public void prepareForRefresh() { resetHeaderPadding(); mRefreshViewImage.setVisibility(View.GONE); // 去掉刷新的箭头 // We need this hack, otherwise it will keep the previous drawable. mRefreshViewImage.setImageDrawable(null); mRefreshViewProgress.setVisibility(View.VISIBLE); // 圆形进度条变为可见 // Set refresh view text to the refreshing label mRefreshViewText.setText(R.string.pull_to_refresh_refreshing_label); mRefreshState = REFRESHING; } /** 为加载更多做准备 **/ public void prepareForLoadMore() { mLoadMoreProgress.setVisibility(View.VISIBLE); mLoadMoreText.setText(R.string.loading_label); mLoadState = LOADING; } public void onRefresh() { Log.d(TAG, "onRefresh"); if (mOnRefreshListener != null) { mOnRefreshListener.onRefresh(); } } public void OnLoadMore() { Log.d(TAG, "onLoadMore"); if (mOnRefreshListener != null) { mOnRefreshListener.onLoadMore(); } } /** * Resets the list to a normal state after a refresh. * * @param lastUpdated * Last updated at. */ public void onRefreshComplete(CharSequence lastUpdated) { setLastUpdated(lastUpdated); // 显示更新时间 onRefreshComplete(); } /** * Resets the list to a normal state after a refresh. */ public void onRefreshComplete() { Log.d(TAG, "onRefreshComplete"); resetHeader(); // If refresh view is visible when loading completes, scroll down to // the next item. if (mRefreshHeaderView.getBottom() > 0) { invalidateViews(); setSelection(1); } } public void onLoadMoreComplete() { Log.d(TAG, "onLoadMoreComplete"); resetFooter(); } /** * Invoked when the refresh view is clicked on. This is mainly used when * there's only a few items in the list and it's not possible to drag the * list. 点击刷新 */ private class OnClickRefreshListener implements OnClickListener { @Override public void onClick(View v) { if (mRefreshState != REFRESHING) { prepareForRefresh(); onRefresh(); } } } /** * * 加载更多 */ private class OnClickLoadMoreListener implements OnClickListener { @Override public void onClick(View v) { if (mLoadState != LOADING) { prepareForLoadMore(); OnLoadMore(); } } } /** * Interface definition for a callback to be invoked when list should be * refreshed. 接口定义一个回调方法当列表应当被刷新 */ public interface OnRefreshListener { /** * Called when the list should be refreshed. 当列表应当被刷新是调用这个方法 * <p> * A call to {@link PullToRefreshListView #onRefreshComplete()} is * expected to indicate that the refresh has completed. */ public void onRefresh(); public void onLoadMore(); } }
相关推荐
【作品名称】:基于servlet+jsp+mysql实现的影视管理系统【课程设计】 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【项目介绍】: 基于servlet+jsp+mysql实现的影视管理系统【课程设计】 基于servlet+jsp+mysql实现的影视管理系统【课程设计】 Java Web课程设计,基于servlet+jsp+ajax+mysql做的影视管理系统 运行环境: Tomcat 9.0 JDK 1.8 MySQL 8.0 后台管理账号密码均为:root,项目依赖:lib 目录 【资源声明】:本资源作为“参考资料”而不是“定制需求”,代码只能作为参考,不能完全复制照搬。需要有一定的基础看懂代码,自行调试代码并解决报错,能自行添加功能修改代码。
kernel-5.15-ky10-x86.tar.gz
【作品名称】:基于AT89C51 单片机为核心器件,程序设计采用C 语言,Keil 软件编译程序,配以相关外围接口电路,实现了方波、锯齿波、正弦波、三角波、梯形波五种特定波形的产生【论文+源码】 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【项目介绍】:本设计中的波形发生器系统要求基于51单片机,因此选用以AT89C51单片机作为整个系统的控制核心,应用其强大的接口功能,构成整个波形发生器的硬件系统。使用C 语言对单片机编程可产生相应的正弦波,方波,三角波,锯齿波梯形波波形信号。在程序运行时,当接收到按键信息后,需要输出某种波形时,调用相应的中断服务子程序和波形发生程序,经电路的数/模转换器和运算放大器处理后,从信号发生器的输出端口输出即可得到要求的波形。 当需要改变频率时只需要改变单片机的波形发生程序中的递增或者递减变量即可。 【资源声明】:本资源作为“参考资料”而不是“定制需求”,代码只能作为参考,不能完全复制照搬。需要有一定的基础看懂代码,自行调试代码并解决报错,能自行添加功能修改代码。
基于java的法律咨询系统设计与实现.docx
适用于元营销 API 的 Python SDK适用于 Python 的 Facebook Business SDK 介绍Facebook Business SDK是一站式服务,可帮助我们的合作伙伴更好地服务于他们的业务。合作伙伴正在使用多个 Facebook API 来满足其客户的需求。采用所有这些 API 并在各个平台上保持最新状态可能非常耗时,而且最终会造成高昂的成本。为此,Facebook 开发了 Business SDK,将其许多 API 捆绑到一个 SDK 中,以简化实施和维护。Business SDK 是 Marketing API SDK 的升级版,其中包括 Marketing API 以及来自不同平台(如 Pages、Business Manager、Instagram 等)的许多 Facebook API。快速入门商业SDK入门指南Python 目前是我们第三方开发人员最常用的语言。是一个 Python 包,它提供了您的 Python 应用程序与Business SDK 内的 Facebook APIfacebook_business之间的
数学建模培训资料 数学建模实战题目真题答案解析解题过程&论文报告 公交车调度的运作数学模型 共12页.pdf
smart-http 是一款可编程的 Http 应用微内核,方便用户根据自身需求进行 Server 或 Client 的应用开发。支持GET、POST的 HTTP 请求。提供了 URL 路由组件,可以快速搭建一套静态服务器。支持部分 RFC2612 规范,后续会逐渐完善。支持 Https 协议,由 smart-socket 为其赋能。具备文件上传的能力。支持 websocket、Cookie支持 Server、Client 开发
新闻资讯系统 微信小程序+SpringBoot毕业设计 源码+数据库+论文+启动教程 项目启动教程:https://www.bilibili.com/video/BV1oiBpYcEBp
高校师生工作室-JAVA-基于微信小程序的高校师生工作室管理系统的设计与实现
基于java的常见小儿疾病中医护理系统设计与实现.docx
本教程播放列表涵盖了 Python 中的数据结构和算法。每个教程都有数据结构或算法背后的理论、BIG O 复杂性分析和可供练习的练习。使用 Python 的数据结构和算法本教程涵盖了 Python 中的数据结构和算法。每个教程都包含数据结构或算法背后的理论、BIG O 复杂度分析以及可供练习的练习。要观看视频,您可以访问播放列表https://www.youtube.com/playlist?list=PLeo1K3hjS3uu_n_a__MI_KktGTLYopZ12订阅 codebasics youtube 频道https://www.youtube.com/c/codebasics
数学建模学习资料 蒙特卡罗方法课件教程 第2章.随机数 共29页.pptx
python实现基于CNN网络的新闻数据集文本分类源码+数据集(Python期末大作业),个人大三学期的期末大作业、经导师指导并认可通过的高分大作业设计项目,评审分98分。主要针对计算机相关专业的正在做大作业的学生和需要项目实战练习的学习者,可作为课程设计、期末大作业。 python实现基于CNN网络的新闻数据集文本分类源码+数据集(Python期末大作业)python实现基于CNN网络的新闻数据集文本分类源码+数据集(Python期末大作业),个人大三学期的期末大作业、经导师指导并认可通过的高分大作业设计项目,评审分98分。主要针对计算机相关专业的正在做大作业的学生和需要项目实战练习的学习者,可作为课程设计、期末大作业。python实现基于CNN网络的新闻数据集文本分类源码+数据集(Python期末大作业),个人大三学期的期末大作业、经导师指导并认可通过的高分大作业设计项目,评审分98分。主要针对计算机相关专业的正在做大作业的学生和需要项目实战练习的学习者,可作为课程设计、期末大作业。python实现基于CNN网络的新闻数据集文本分类源码+数据集(Python期末大作业),个人大
中小学知识产权教育试点学校申报表.doc
基于django的音乐推荐系统.zip
在建工程涉及专项行动情况检查表.docx
本项目是一个基于Python技术的学生管理系统,采用Django框架进行开发,旨在为计算机相关专业的学生提供一个实践性强、功能全面的管理系统,以帮助他们完成毕业设计或进行项目实战练习。 系统实现了对学生信息、课程信息、成绩、考勤等多方面的管理功能。学生信息管理包括学生基本信息的增删改查;课程信息管理允许管理员设置课程信息,包括课程名称、授课老师、学分等;成绩管理功能使学生和教师能够录入、查看和修改成绩;考勤管理则方便教师记录学生的出勤情况。 该项目采用B/S架构,前端使用HTML、CSS、JavaScript等技术,后端使用Python语言和Django框架,数据库采用MySQL。Django框架提供了强大的后台管理功能,使得系统管理更加便捷。 通过开发这个项目,学生不仅能提升自己的编程能力,还能学习到如何构建一个实际应用的系统,对于即将步入职场的学生来说,具有很高的实用价值。
适用于 Python 的 Splunk 软件开发工具包参考文档适用于 Python 的 Splunk Enterprise 软件开发工具包版本 2.1.0适用于 Python 的 Splunk Enterprise 软件开发套件 (SDK) 包含库代码,旨在使开发人员能够使用 Splunk 平台构建应用程序。Splunk 平台是一个搜索引擎和分析环境,它使用分布式 map-reduce 架构来有效地索引、搜索和处理大型时变数据集。Splunk 平台深受系统管理员的欢迎,用于聚合和监控 IT 机器数据、安全性、合规性以及各种其他场景,这些场景都需要有效地从大量时间序列数据中索引、搜索、分析和生成实时通知。Splunk 开发者平台使开发人员能够利用 Splunk 平台所使用的相同技术来构建令人兴奋的新应用程序。开始使用 Python 版 Splunk SDK开始使用 Python 版 Splunk Enterprise SDKSplunk Enterprise SDK for Python 包含库代码,其示例位于splunk-app-examples存储库
分布式事务练习
家庭财务管理系统 微信小程序+SSM毕业设计 源码+数据库+论文+启动教程 项目启动教程:https://www.bilibili.com/video/BV1BfB2YYEnS