ScrollView 实现下拉刷新(二)
来源:互联网 发布:女装淘宝店铺特别名字 编辑:程序博客网 时间:2024/06/05 21:12
在 ScrollView 实现下拉刷新(一)的基础上再做封装,使得更好的进行复用。
package edu.jxau.tboing.layout;import java.util.Date;import android.content.Context;import android.os.AsyncTask;import android.util.AttributeSet;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.ImageView;import android.widget.LinearLayout;import android.widget.ProgressBar;import android.widget.ScrollView;import android.widget.TextView;import edu.jxau.tboing.jwassistant.R;public class DropLayout extends LinearLayout {private ScrollView sc;private LayoutInflater inflater;private LinearLayout header;private ImageView arrowImg;private ProgressBar headProgress;private TextView lastUpdateTxt;private TextView tipsTxt;private RotateAnimation tipsAnimation;private RotateAnimation reverseAnimation;private int headerHeight;//头高度private int lastHeaderPadding; //最后一次调用Move Header的Paddingprivate boolean isBack; //从Release 转到 pullprivate int headerState = DONE;private RefreshCallBack callBack;private LinearLayout subLayout;static final private int RELEASE_To_REFRESH = 0;static final private int PULL_To_REFRESH = 1;static final private int REFRESHING = 2;static final private int DONE = 3;public DropLayout(Context context, AttributeSet attrs) { super(context, attrs); init(context); }private void init(Context context) {inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);sc = new ScrollView(context);sc.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));//由于ScrollView 只允许有一个ChildView所以再用LinearLayout来做容器subLayout = new LinearLayout(context);subLayout.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));subLayout.setOrientation(VERTICAL);sc.addView(subLayout);header = (LinearLayout) inflater.inflate(R.layout.drag_drop_header, null);measureView(header);headerHeight = header.getMeasuredHeight();lastHeaderPadding = (-1*headerHeight); //最后一次调用Move Header的Paddingheader.setPadding(0, lastHeaderPadding, 0, 0);header.invalidate();this.addView(header,0);this.addView(sc,1);headProgress = (ProgressBar) findViewById(R.id.head_progressBar);arrowImg = (ImageView) findViewById(R.id.head_arrowImageView);arrowImg.setMinimumHeight(50);arrowImg.setMinimumWidth(50);tipsTxt = (TextView) findViewById(R.id.head_tipsTextView);lastUpdateTxt = (TextView) findViewById(R.id.head_lastUpdatedTextView);//箭头转动动画tipsAnimation = new RotateAnimation(0, -180,RotateAnimation.RELATIVE_TO_SELF, 0.5f,RotateAnimation.RELATIVE_TO_SELF, 0.5f);tipsAnimation.setInterpolator(new LinearInterpolator());tipsAnimation.setDuration(200);//动画持续时间tipsAnimation.setFillAfter(true);//动画结束后保持动画//箭头反转动画reverseAnimation = new RotateAnimation(-180, 0,RotateAnimation.RELATIVE_TO_SELF, 0.5f,RotateAnimation.RELATIVE_TO_SELF, 0.5f);reverseAnimation.setInterpolator(new LinearInterpolator());reverseAnimation.setDuration(200);reverseAnimation.setFillAfter(true);//为scrollview绑定事件sc.setOnTouchListener(new OnTouchListener() {private int beginY;@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_MOVE://sc.getScrollY == 0 scrollview 滑动到头了 //lastHeaderPadding > (-1*headerHeight) 表示header还没完全隐藏起来时//headerState != REFRESHING 当正在刷新时if((sc.getScrollY() == 0 || lastHeaderPadding > (-1*headerHeight)) && headerState != REFRESHING) {//拿到滑动的Y轴距离int interval = (int) (event.getY() - beginY);//是向下滑动而不是向上滑动if (interval > 0) {interval = interval/2;//下滑阻力lastHeaderPadding = interval + (-1*headerHeight);header.setPadding(0, lastHeaderPadding, 0, 0);if(lastHeaderPadding > 0) {//txView.setText("我要刷新咯");headerState = RELEASE_To_REFRESH;//是否已经更新了UIif(! isBack) {isBack = true; //到了Release状态,如果往回滑动到了pull则启动动画changeHeaderViewByState();}} else {headerState = PULL_To_REFRESH;changeHeaderViewByState();//txView.setText("看到我了哦");//sc.scrollTo(0, headerPadding);}}}break;case MotionEvent.ACTION_DOWN://加上下滑阻力与实际滑动距离的差(大概值)beginY = (int) ((int) event.getY() + sc.getScrollY()*1.5);break;case MotionEvent.ACTION_UP:if (headerState != REFRESHING) {switch (headerState) {case DONE://什么也不干break;case PULL_To_REFRESH:headerState = DONE;lastHeaderPadding = -1*headerHeight;header.setPadding(0, lastHeaderPadding, 0, 0);changeHeaderViewByState();break;case RELEASE_To_REFRESH:isBack = false; //准备开始刷新,此时将不会往回滑动headerState = REFRESHING;changeHeaderViewByState();onRefresh();break;default:break;}}break;}//如果Header是完全被隐藏的则让ScrollView正常滑动,让事件继续否则的话就阻断事件if(lastHeaderPadding > (-1*headerHeight) && headerState != REFRESHING) {return true;} else {return false;}}});}@Overridepublic void addView(View child, int index, android.view.ViewGroup.LayoutParams params) {//读取XML中的默认给 -1 自己添加的为0 和 1if(index == -1) {subLayout.addView(child, params);return ;}super.addView(child, index, params);}public void setRefreshCallBack(RefreshCallBack callBack) {this.callBack = callBack;}private void changeHeaderViewByState() {switch (headerState) {case PULL_To_REFRESH:// 是由RELEASE_To_REFRESH状态转变来的if (isBack) {isBack = false;arrowImg.startAnimation(reverseAnimation);tipsTxt.setText("下拉刷新");}tipsTxt.setText("下拉刷新");break;case RELEASE_To_REFRESH:arrowImg.setVisibility(View.VISIBLE);headProgress.setVisibility(View.GONE);tipsTxt.setVisibility(View.VISIBLE);lastUpdateTxt.setVisibility(View.VISIBLE);arrowImg.clearAnimation();arrowImg.startAnimation(tipsAnimation);tipsTxt.setText("松开刷新");break;case REFRESHING:lastHeaderPadding = 0;header.setPadding(0, lastHeaderPadding, 0, 0);header.invalidate();headProgress.setVisibility(View.VISIBLE);arrowImg.clearAnimation();arrowImg.setVisibility(View.INVISIBLE);tipsTxt.setText("正在刷新...");lastUpdateTxt.setVisibility(View.VISIBLE);break;case DONE:lastHeaderPadding = -1 * headerHeight;header.setPadding(0, lastHeaderPadding, 0, 0);header.invalidate();headProgress.setVisibility(View.GONE);arrowImg.clearAnimation();arrowImg.setVisibility(View.VISIBLE);tipsTxt.setText("下拉刷新");lastUpdateTxt.setVisibility(View.VISIBLE);break;default:break;}}private void onRefresh() {new RefreshAsyncTask().execute();}private class RefreshAsyncTask extends AsyncTask<Void, Void, Void> {protected Void doInBackground(Void... params) {if(callBack != null) {callBack.doInBackground();}return null;}@Overrideprotected void onPostExecute(Void result) {onRefreshComplete();if(callBack != null) {callBack.complete();}}}public interface RefreshCallBack {public void doInBackground();public void complete();}@SuppressWarnings("deprecation")public void onRefreshComplete() {headerState = DONE;lastUpdateTxt.setText("最近更新:" + new Date().toLocaleString());changeHeaderViewByState();}//由于OnCreate里面拿不到header的高度所以需要手动计算private void measureView(View childView) {android.view.ViewGroup.LayoutParams p = childView.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 height = p.height;int childHeightSpec;if (height > 0) {childHeightSpec = MeasureSpec.makeMeasureSpec(height,MeasureSpec.EXACTLY);} else {childHeightSpec = MeasureSpec.makeMeasureSpec(0,MeasureSpec.UNSPECIFIED);}childView.measure(childWidthSpec, childHeightSpec);}}
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <edu.jxau.tboing.layout.DropLayout android:id="@+id/dropView" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > </edu.jxau.tboing.layout.DropLayout></LinearLayout>
然后记得带上图片和header的XML :
<?xml version="1.0" encoding="utf-8"?><!-- ListView的头部 --><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/head_rootLayout" android:layout_width="fill_parent" android:layout_height="wrap_content" > <!-- 内容 --> <RelativeLayout android:id="@+id/head_contentLayout" android:layout_width="fill_parent" android:layout_height="wrap_content" 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:contentDescription="@string/app_name" android:src="@drawable/head_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/pulltorefresh" android:textSize="20sp" /> <!-- 最近更新 --> <TextView android:id="@+id/head_lastUpdatedTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/lastupdate" android:textColor="#cc6600" android:textSize="12sp" /> </LinearLayout> </RelativeLayout></LinearLayout>
这样就大功告成了,这样就能比较好的进行复用了。
这样比ListView的下拉刷新更有优势。
- ScrollView 实现下拉刷新(二)
- 使用ScrollView实现下拉刷新(一)
- 使用ScrollView实现下拉刷新(一)
- 自定义ScrollView实现下拉刷新
- UI:实现ScrollView能够下拉刷新效果
- scrollview下拉刷新
- 下拉刷新ScrollView
- ScrollView 下拉刷新
- ScrollView下拉刷新
- Android自定义控件(二) 下拉刷新,上拉分页加载更多(支持ListView, GridView, ScrollView)
- Iphone开发(十四)深入理解scrollView的contentOffset等属性,实现下拉刷新功能
- Iphone开发(十四)深入理解scrollView的contentOffset等属性,实现下拉刷新功能
- Iphone开发(十四)深入理解scrollView的contentOffset等属性,实现下拉刷新功能
- Android 下拉刷新控件之ScrollView版本实现
- Android 下拉刷新控件之ScrollView版本实现
- Android 下拉刷新控件之ScrollView版本实现 .
- <Android>使用ScrollView 实现 ListView 的下拉刷新
- iOS实现scrollView下拉刷新和上拉加载
- 初识EJB3.0的答疑总结(一)
- 2011年薪超百万职业(组图)
- JavaScript 中 window.setTimeout() 的详细用法
- HDU 1176 免费馅饼
- Bash游戏
- ScrollView 实现下拉刷新(二)
- 读取Nutch抓取文件中的Segments中Parse_Text的内容
- Codeforces Beta Round #70 (Div. 2)——A,B,C
- android111--looper
- 学习日记-观察者模式
- C++内存分配方式详解——堆、栈、自由存储区、全局/静态存储区和常量存储区
- HTMLParser的两种使用方法
- HEVC-Tool list
- windows阻塞队列