“Pull To Refresh” is a UI gesture made popular by the Twitter for Iphone app. It allows a user to refresh a list by pulling down and releasing from the top of the list. IOS developers have had library support for this feature for some time now. Over in Android-land, only the official Twitter app has managed to implement this gesture. Long-promised to be open-sourced, Twitter’s solution is still secret and Android developers have no official means to implement this increasingly demanded feature.
Its not my own library. I don't know who is written this library. But i think it will help u more than when compared to other libraries. Here they implemented via frame layout and a list view. dragging and releasing part has done inside the frame layout. Check an example below.
Its not my own library. I don't know who is written this library. But i think it will help u more than when compared to other libraries. Here they implemented via frame layout and a list view. dragging and releasing part has done inside the frame layout. Check an example below.
In xml file ....
package com.example.helpers; import android.content.Context; import android.util.AttributeSet; import android.view.GestureDetector; import android.view.Gravity; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.animation.Animation; import android.view.animation.LinearInterpolator; import android.view.animation.RotateAnimation; import android.widget.AdapterView; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.Scroller; import android.widget.TextView; import com.example.R; public class PullToRefresh extends FrameLayout implements GestureDetector.OnGestureListener { public static final int STATE_CLOSE = 1; public static final int STATE_OPEN = 2; public static final int STATE_OPEN_MAX = 4; public static final int STATE_OPEN_MAX_RELEASE = 5; public static final int STATE_OPEN_RELEASE = 3; public static final int STATE_UPDATE = 6; public static final int STATE_UPDATE_SCROLL = 7; private final int MAXHEIGHT = 100; // private final String TAG = "PullToRefresh"; private ImageView mArrow; private String mDate; private GestureDetector mDetector; private Flinger mFlinger; private boolean mIsAutoScroller; private int mPading; private ProgressBar mProgressBar; private int mState; private TextView mTitle; private FrameLayout mUpdateContent; private UpdateHandle mUpdateHandle; private RotateAnimation mFlipAnimation; private RotateAnimation mReverseFlipAnimation; private Context ctx; public PullToRefresh(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); this.ctx = context; addUpdateBar(); init(); } public PullToRefresh(Context context, AttributeSet attrs) { super(context, attrs); this.ctx = context; addUpdateBar(); init(); } public PullToRefresh(Context context) { super(context); this.ctx = context; addUpdateBar(); init(); } // private void init() { // MAX_LENGHT = getResources().getDimensionPixelSize( // R.dimen.updatebar_height); // setDrawingCacheEnabled(true); // // setBackgroundDrawable(null); // setClipChildren(true); // this.mDetector.setIsLongpressEnabled(false); // } @Override public boolean dispatchTouchEvent(MotionEvent ev) { boolean bool1 = this.mIsAutoScroller; GestureDetector localGestureDetector = this.mDetector; localGestureDetector.onTouchEvent(ev); switch (ev.getAction()) { case MotionEvent.ACTION_MOVE: int i1 = getChildAt(1).getTop(); if (i1 != 0) { updateView(); } break; case MotionEvent.ACTION_UP: if (this.mState == STATE_OPEN) { this.mState = STATE_OPEN_RELEASE; } if (this.mState == STATE_OPEN_MAX) { this.mState = STATE_OPEN_MAX_RELEASE; } release(); break; } if (mState != STATE_UPDATE) { bool1 = super.dispatchTouchEvent(ev); } int i1 = getChildAt(1).getTop(); if (i1 != 0) { ev.setAction(3); super.dispatchTouchEvent(ev); updateView(); } return bool1; } private void init() { GestureDetector localGestureDetector = new GestureDetector(this); this.mDetector = localGestureDetector; Flinger localFlinger = new Flinger(); this.mFlinger = localFlinger; this.mState = 1; setDrawingCacheEnabled(true); setClipChildren(true); this.mDetector.setIsLongpressEnabled(false); } private void updateView() { View localView1 = getChildAt(0); View localView2 = getChildAt(1); if (this.mDate == null) this.mDate = ""; switch (this.mState) { case STATE_CLOSE: if (localView1.getVisibility() != View.INVISIBLE) localView1.setVisibility(View.INVISIBLE); case STATE_OPEN: case STATE_OPEN_RELEASE: // STATE_OPEN int m = localView2.getTop(); int n = -this.mPading - m; localView2.offsetTopAndBottom(n); if (localView1.getVisibility() != 0) localView1.setVisibility(View.VISIBLE); int i1 = localView1.getTop();// 相对于父窗å�£çš„顶部大å°� int i2 = -MAXHEIGHT; int i3 = this.mPading; int i4 = i2 - i3 - i1; localView1.offsetTopAndBottom(i4); TextView localTextView1 = this.mTitle; String str1 = ctx.getText(R.string.update_when_release_the_finger).toString(); StringBuilder localStringBuilder1 = new StringBuilder(str1) .append("\n"); // String str2 = this.mDate; // String str3 = str2; localStringBuilder1.append(this.mDate); localTextView1.setText(localStringBuilder1.toString()); this.mProgressBar.setVisibility(View.INVISIBLE); this.mArrow.setVisibility(View.VISIBLE); break; case STATE_OPEN_MAX_RELEASE: case STATE_OPEN_MAX: // STATE_OPEN_MAX int i5 = localView2.getTop(); int i6 = -this.mPading - i5; localView2.offsetTopAndBottom(i6); if (localView1.getVisibility() != View.VISIBLE) localView1.setVisibility(View.VISIBLE); int i7 = localView1.getTop(); int i8 = -MAXHEIGHT; int i9 = this.mPading; int i10 = i8 - i9 - i7; localView1.offsetTopAndBottom(i10); TextView localTextView2 = this.mTitle; String str4 = ctx.getText(R.string.update_when_release_the_finger).toString();// release_update: StringBuilder localStringBuilder2 = new StringBuilder(str4).append("\n"); localStringBuilder2.append(this.mDate); localTextView2.setText(localStringBuilder2.toString()); this.mProgressBar.setVisibility(View.INVISIBLE); this.mArrow.setVisibility(View.VISIBLE); break; case STATE_UPDATE: // STATE_UPDATE int i11 = localView2.getTop(); int i12 = -this.mPading - i11; localView2.offsetTopAndBottom(i12); int i13 = localView1.getTop(); if (this.mProgressBar.getVisibility() != View.VISIBLE) this.mProgressBar.setVisibility(View.VISIBLE); if (this.mArrow.getVisibility() != View.INVISIBLE) this.mArrow.setVisibility(View.INVISIBLE); TextView localTextView3 = this.mTitle; String str7 = ctx.getString(R.string.updating).toString();// doing_update:åŠ è½½ä¸... StringBuilder localStringBuilder3 = new StringBuilder(str7) .append("\n"); localStringBuilder3.append(this.mDate); localTextView3.setText(localStringBuilder3.toString()); int i14 = -MAXHEIGHT; int i15 = this.mPading; int i16 = i14 - i15 - i13; localView1.offsetTopAndBottom(i16); if (localView1.getVisibility() != 0) localView1.setVisibility(0); this.mProgressBar.setVisibility(View.VISIBLE); this.mArrow.setVisibility(View.GONE); mArrow.clearAnimation(); break; } invalidate(); } private void addUpdateBar() { Context localContext1 = getContext(); mFlipAnimation = new RotateAnimation(0, -180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); mFlipAnimation.setInterpolator(new LinearInterpolator()); mFlipAnimation.setDuration(200); mFlipAnimation.setFillAfter(true); mReverseFlipAnimation = new RotateAnimation(-180, 0, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); mReverseFlipAnimation.setInterpolator(new LinearInterpolator()); mReverseFlipAnimation.setDuration(200); mReverseFlipAnimation.setFillAfter(true); View localView = LayoutInflater.from(localContext1).inflate( R.layout.vw_update_bar, null); localView.setVisibility(4); addView(localView); this.mArrow = new ImageView(localContext1); FrameLayout.LayoutParams localLayoutParams1 = new FrameLayout.LayoutParams( android.view.ViewGroup.LayoutParams.FILL_PARENT, android.view.ViewGroup.LayoutParams.FILL_PARENT); ImageView localImageView2 = this.mArrow; ImageView.ScaleType localScaleType = ImageView.ScaleType.FIT_CENTER; localImageView2.setScaleType(localScaleType); this.mArrow.setLayoutParams(localLayoutParams1); this.mArrow.setImageResource(R.drawable.arrow_down); this.mUpdateContent = (FrameLayout) getChildAt(0).findViewById( R.id.iv_content); FrameLayout localFrameLayout2 = this.mUpdateContent; localFrameLayout2.addView(this.mArrow); FrameLayout.LayoutParams localLayoutParams2 = new FrameLayout.LayoutParams( android.view.ViewGroup.LayoutParams.FILL_PARENT, android.view.ViewGroup.LayoutParams.FILL_PARENT); localLayoutParams2.gravity = Gravity.CENTER_VERTICAL; this.mProgressBar = new ProgressBar(localContext1); int i = getResources().getDimensionPixelSize(R.dimen.progress_padding); this.mProgressBar.setPadding(i, i, i, i); this.mProgressBar.setLayoutParams(localLayoutParams2); this.mUpdateContent.addView(mProgressBar); this.mTitle = (TextView) findViewById(R.id.tv_title); } @Override protected void onLayout(boolean paramBoolean, int paramInt1, int paramInt2, int paramInt3, int paramInt4) { View localView1 = getChildAt(0); int i = -MAXHEIGHT; int j = this.mPading; int k = i - j; int l = getMeasuredWidth(); int i1 = -this.mPading; localView1.layout(0, k, l, i1); View localView2 = getChildAt(1); int i2 = -this.mPading; int i3 = getMeasuredWidth(); int i4 = getMeasuredHeight(); int i5 = this.mPading; int i6 = i4 - i5; localView2.layout(0, i2, i3, i6); } public void endUpdate(String paramString) { this.mDate = paramString; if (this.mPading != 0) { this.mState = STATE_CLOSE; scrollToClose(); } } @Override public boolean onDown(MotionEvent e) { return false; } @Override public void onShowPress(MotionEvent e) { } @Override public boolean onSingleTapUp(MotionEvent e) { return false; } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { @SuppressWarnings("rawtypes") AdapterView localAdapterView = (AdapterView) getChildAt(1); int k = localAdapterView.getCount(); if (k == 0) { return false; } k = localAdapterView.getFirstVisiblePosition();// 获å�–第一个显示项目的position if (k == 0) { int t = localAdapterView.getChildAt(0).getTop(); if (t != 0) { return false; } else { this.mPading = (int) (this.mPading + distanceY / 2); if (this.mPading > 0) this.mPading = 0; // if (distanceY < 0) { if (Math.abs(this.mPading) <= MAXHEIGHT) { this.mState = STATE_OPEN; } else { this.mState = STATE_OPEN_MAX; } // } updateView(); } } return false; } @Override public void onLongPress(MotionEvent e) { } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { return false; } @SuppressWarnings("unused") private int getScrollRange() { int scrollRange = 0; if (getChildCount() > 0) { View child = getChildAt(0); scrollRange = Math.max(0,child.getHeight() - (getHeight() - this.getBottomPaddingOffset() - this .getTopPaddingOffset())); } return scrollRange; } private boolean release() { int tempStatus = STATE_OPEN_MAX_RELEASE; int i = this.mPading; if (i >= 0) { return true; } int j = this.mState; switch (j) { case STATE_OPEN_RELEASE: int k = Math.abs(this.mPading); int i1 = MAXHEIGHT; if (k < i1) { tempStatus = STATE_OPEN_MAX_RELEASE; this.mState = tempStatus; } scrollToClose(); break; case STATE_OPEN_MAX_RELEASE: this.mState = tempStatus; scrollToUpdate(); break; } return false; } private void scrollToClose() { Flinger localFlinger = this.mFlinger; int i = -this.mPading; localFlinger.startUsingDistance(i, 300); } private void scrollToUpdate() { Flinger localFlinger = this.mFlinger; int k = -this.mPading - MAXHEIGHT; localFlinger.startUsingDistance(k, 300); } class Flinger implements Runnable { private int mLastFlingX; private Scroller mScroller; public Flinger() { Context localContext = PullToRefresh.this.getContext(); Scroller localScroller = new Scroller(localContext); this.mScroller = localScroller; } private void startCommon() { PullToRefresh.this.removeCallbacks(this); } @Override public void run() { boolean bool1 = Math.abs(mPading) != MAXHEIGHT; Scroller localScroller = this.mScroller; boolean bool2 = localScroller.computeScrollOffset(); int i = localScroller.getCurrX(); int j = this.mLastFlingX - i; PullToRefresh localPullDownView = PullToRefresh.this; localPullDownView.move(j, bool1); PullToRefresh.this.updateView(); if (bool2) { this.mLastFlingX = i; PullToRefresh.this.post(this); } else { PullToRefresh.this.mIsAutoScroller = bool1; PullToRefresh.this.removeCallbacks(this); } } public void startUsingDistance(int paramInt1, int paramInt2) { int i = 0; if (paramInt1 == 0) --paramInt1; startCommon(); this.mLastFlingX = i; Scroller localScroller = this.mScroller; localScroller.startScroll(i, 0, -paramInt1, 0, paramInt2); PullToRefresh.this.mIsAutoScroller = true; PullToRefresh.this.post(this); } } /** * * * @param f * @param bool1 */ public void move(float f, boolean bool1) { if (this.mState != STATE_CLOSE) { if (!bool1) { // 刷新 if (mState == STATE_OPEN_MAX_RELEASE) { this.mState = STATE_UPDATE; if (mUpdateHandle != null) { mUpdateHandle.onUpdate(); } } } if (this.mState == STATE_OPEN_MAX_RELEASE || this.mState == STATE_OPEN_RELEASE) { this.mPading += f; } } else { if (mIsAutoScroller) { this.mPading += f; } } } public abstract interface UpdateHandle { public abstract void onUpdate(); } public void setUpdateDate(String paramString) { this.mDate = paramString; } public void setUpdateHandle(UpdateHandle paramUpdateHandle) { this.mUpdateHandle = paramUpdateHandle; } // public void update() // { // int i = -MAXHEIGHT; // this.mPading = i; // this.mState = 7; // } public void updateWithoutOffset() { this.mState = STATE_UPDATE_SCROLL; invalidate(); } }Values for the strings.
vw_update_bar layout xml.Refresh Updating ... Last Updated : Release to update..
dimension.xml used
Update activity class as follows.120px 120px 20px 10px
package com.example public class Home extends Activity implements PullToRefresh.UpdateHandle { private PullToRefresh refresh; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); refresh = (PullToRefresh) findViewById(R.id.pullDownView1); refresh.setUpdateHandle(this); // ..... } //... @Override public void onUpdate() { // Update call .. do the need ful for updating. } //.... private final Handler handler = new Handler(Looper.getMainLooper()) { @Override public void handleMessage(Message msg) { refresh.endUpdate(getString(R.string.pulltorefreshhandle_text) + getTime()); } }; }After adding adapter values means child items to the list view then call this method to finish update.
Message msg = handler.obtainMessage(); handler.sendMessage(msg);
No comments:
Post a Comment