新手发帖,很多方面都是刚入门,有错误的地方请大家见谅,欢迎批评指正
废话少说先上图
demo 下载地址
其中上半部份是一个gallery,下边是一个listview
UGallery .java
package com.gallery.test;
import android.content.Context; import android.util.AttributeSet; import android.view.KeyEvent; import android.view.MotionEvent; import android.widget.Gallery; public class UGallery extends Gallery { public UGallery(Context context, AttributeSet attrs) { super(context, attrs); } private boolean isScrollingLeft(MotionEvent e1, MotionEvent e2) { return e2.getX() > e1.getX(); } public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { int keyCode; if (isScrollingLeft(e1, e2)) { keyCode = KeyEvent.KEYCODE_DPAD_LEFT; } else { keyCode = KeyEvent.KEYCODE_DPAD_RIGHT; } onKeyDown(keyCode, null); return true; } }PullToRefreshListActivity .java
package com.stay.pull;
import android.app.ListActivity; import android.content.Context; import android.os.AsyncTask; import android.os.Bundle; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.Gallery; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; import android.widget.AdapterView.OnItemSelectedListener; import com.gallery.test.UGallery; import com.stay.pull.lib.PullToRefreshBase.OnRefreshListener; import com.stay.pull.lib.PullToRefreshListView; public class PullToRefreshListActivity extends ListActivity { static final int MENU_MANUAL_REFRESH = 0; static final int MENU_DISABLE_SCROLL = 1; private PullToRefreshListView mPullRefreshListView; // Gallery mGallery; private UGallery uGallery; private ViewGroup vg; private LinearLayout change_layout; private LinearLayout viewGroup; private LinearLayout title_layout; private ImageView imageView; private ImageView[] imageViews; private TextView[] txt_titles; private TextView txt_title; private ListView actualListView; private Integer[] mImage = { R.drawable.image1, R.drawable.image2, R.drawable.image3, }; private String[] mtitle = { "这是俏丽的风景", "这是可憎的稻草人", "这是迷人的大海" }; private ImageView change_1, change_2, change_3; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.pull_to_refresh_list); imageViews = new ImageView[mImage.length]; vg= (ViewGroup) LayoutInflater.from(this).inflate(R.layout.main1, null); uGallery = (UGallery) vg.findViewById(R.id.gly_images); change_layout = (LinearLayout) vg.findViewById(R.id.change_layout); viewGroup = (LinearLayout) vg.findViewById(R.id.viewGroup); title_layout = (LinearLayout) vg.findViewById(R.id.title_layout); txt_title = new TextView(this); title_layout.addView(txt_title); change_layout.getBackground().setAlpha(180); uGallery.setAdapter(new ImageAdapter(PullToRefreshListActivity.this)); for (int i = 0; i < mImage.length; i++) { imageView = new ImageView(this); imageView.setLayoutParams(new LayoutParams(18, 12)); imageViews[i] = imageView; if (i == 0) { // 默认进入程序后第一张图片被选中; imageViews[i].setBackgroundResource(R.drawable.selectedflag); } else { imageViews[i].setBackgroundResource(R.drawable.unselectedflag); } viewGroup.addView(imageView); } uGallery.setOnItemSelectedListener(new OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) { txt_title.setText(mtitle[arg2]); for (int i = 0; i < imageViews.length; i++) { imageViews[arg2].setBackgroundResource(R.drawable.selectedflag); if (arg2 != i) { imageViews[i].setBackgroundResource(R.drawable.unselectedflag); } } } @Override public void onNothingSelected(AdapterView<?> arg0) { // TODO Auto-generated method stub } }); mPullRefreshListView = (PullToRefreshListView) findViewById(R.id.pull_refresh_list); mPullRefreshListView.setOnRefreshListener(new OnRefreshListener() { @Override public void onRefresh() { new GetDataTask().execute(); } }); actualListView = mPullRefreshListView.getRefreshableView(); actualListView.setAdapter(new Mybaseadapter()); } private class GetDataTask extends AsyncTask<Void, Void, String[]> { @Override protected String[] doInBackground(Void... params) { try { Thread.sleep(4000); } catch (InterruptedException e) { } return new String[] { "返回数据" }; } @Override protected void onPostExecute(String[] result) { //mAdapter.notifyDataSetChanged(); mPullRefreshListView.onRefreshComplete(); super.onPostExecute(result); } } @Override public boolean onCreateOptionsMenu(Menu menu) { menu.add(0, MENU_MANUAL_REFRESH, 0, "Manual Refresh"); menu.add( 0, MENU_DISABLE_SCROLL, 1, mPullRefreshListView.isDisableScrollingWhileRefreshing() ? "Enable Scrolling while Refreshing" : "Disable Scrolling while Refreshing"); return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case MENU_MANUAL_REFRESH: new GetDataTask().execute(); mPullRefreshListView.setRefreshing(false); break; case MENU_DISABLE_SCROLL: mPullRefreshListView.setDisableScrollingWhileRefreshing(!mPullRefreshListView .isDisableScrollingWhileRefreshing()); break; } return super.onOptionsItemSelected(item); } private class Mybaseadapter extends BaseAdapter { @Override public int getCount() { return 31; } @Override public Object getItem(int position) { return 0; } @Override public long getItemId(int position) { return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { if (position == 0) { return vg; } else { TextView mTextView = new TextView(PullToRefreshListActivity.this); mTextView.setText(position - 1 + ""); return mTextView; } } } private class ImageAdapter extends BaseAdapter { private Context mContext; private int i = 0; public ImageAdapter(Context c) { mContext = c; } @Override public int getCount() { return mImage.length; } @Override public Object getItem(int position) { // TODO Auto-generated method stub return 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 ImageView i = new ImageView(mContext); i.setImageResource(mImage[position]); // i.setScaleType(ImageView.ScaleType.FIT_XY); i.setLayoutParams(new Gallery.LayoutParams(800, LayoutParams.WRAP_CONTENT)); return i; } }; }下拉刷新的动画部份
package com.stay.pull.lib;
import android.content.Context; import android.util.AttributeSet; import android.view.ContextMenu.ContextMenuInfo; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; import android.widget.AbsListView; import android.widget.AbsListView.OnScrollListener; import android.widget.FrameLayout; import android.widget.GridView; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import com.stay.pull.lib.internal.EmptyViewMethodAccessor; public abstract class PullToRefreshAdapterViewBase<T extends AbsListView> extends PullToRefreshBase<T> implements OnScrollListener { private int lastSavedFirstVisibleItem = -1; private OnScrollListener onScrollListener; private OnLastItemVisibleListener onLastItemVisibleListener; private View emptyView; private FrameLayout refreshableViewHolder; private ImageView mTopImageView; public PullToRefreshAdapterViewBase(Context context) { super(context); refreshableView.setOnScrollListener(this); } public PullToRefreshAdapterViewBase(Context context, int mode) { super(context, mode); refreshableView.setOnScrollListener(this); } public PullToRefreshAdapterViewBase(Context context, AttributeSet attrs) { super(context, attrs); refreshableView.setOnScrollListener(this); } abstract public ContextMenuInfo getContextMenuInfo(); public final void onScroll(final AbsListView view, final int firstVisibleItem, final int visibleItemCount, final int totalItemCount) { if (null != onLastItemVisibleListener) { // detect if last item is visible if (visibleItemCount > 0 && (firstVisibleItem + visibleItemCount == totalItemCount)) { // only process first event if (firstVisibleItem != lastSavedFirstVisibleItem) { lastSavedFirstVisibleItem = firstVisibleItem; onLastItemVisibleListener.onLastItemVisible(); } } } if (null != onScrollListener) { onScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount); } } public final void onScrollStateChanged(final AbsListView view, final int scrollState) { if (null != onScrollListener) { onScrollListener.onScrollStateChanged(view, scrollState); } } public void setBackToTopView(ImageView mTopImageView){ this.mTopImageView = mTopImageView; mTopImageView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (refreshableView instanceof ListView ) { ((ListView)refreshableView).setSelection(0); }else if(refreshableView instanceof GridView){ ((GridView)refreshableView).setSelection(0); } } }); } /** * Sets the Empty View to be used by the Adapter View. * * We need it handle it ourselves so that we can Pull-to-Refresh when the * Empty View is shown. * * Please note, you do <strong>not</strong> usually need to call this method * yourself. Calling setEmptyView on the AdapterView will automatically call * this method and set everything up. This includes when the Android * Framework automatically sets the Empty View based on it's ID. * * @param newEmptyView * - Empty View to be used */ public final void setEmptyView(View newEmptyView) { // If we already have an Empty View, remove it if (null != emptyView) { refreshableViewHolder.removeView(emptyView); } if (null != newEmptyView) { ViewParent newEmptyViewParent = newEmptyView.getParent(); if (null != newEmptyViewParent && newEmptyViewParent instanceof ViewGroup) { ((ViewGroup) newEmptyViewParent).removeView(newEmptyView); } this.refreshableViewHolder.addView(newEmptyView, ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT); } if (refreshableView instanceof EmptyViewMethodAccessor) { ((EmptyViewMethodAccessor) refreshableView).setEmptyViewInternal(newEmptyView); } else { this.refreshableView.setEmptyView(newEmptyView); } } public final void setOnLastItemVisibleListener(OnLastItemVisibleListener listener) { onLastItemVisibleListener = listener; } public final void setOnScrollListener(OnScrollListener listener) { onScrollListener = listener; } protected void addRefreshableView(Context context, T refreshableView) { refreshableViewHolder = new FrameLayout(context); refreshableViewHolder.addView(refreshableView, ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT); addView(refreshableViewHolder, new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, 0, 1.0f)); }; protected boolean isReadyForPullDown() { return isFirstItemVisible(); } protected boolean isReadyForPullUp() { return isLastItemVisible(); } private boolean isFirstItemVisible() { if (this.refreshableView.getCount() == 0) { return true; } else if (refreshableView.getFirstVisiblePosition() == 0) { final View firstVisibleChild = refreshableView.getChildAt(0); if (firstVisibleChild != null) { return firstVisibleChild.getTop() >= refreshableView.getTop(); } } return false; } private boolean isLastItemVisible() { final int count = this.refreshableView.getCount(); final int lastVisiblePosition = refreshableView.getLastVisiblePosition(); if (count == 0) { return true; } else if (lastVisiblePosition == count - 1) { final int childIndex = lastVisiblePosition - refreshableView.getFirstVisiblePosition(); final View lastVisibleChild = refreshableView.getChildAt(childIndex); if (lastVisibleChild != null) { return lastVisibleChild.getBottom() <= refreshableView.getBottom(); } } return false; } }
每日一道理 微笑,是春天里的一丝新绿,是秋日里的一缕阳光,是骄阳下的一片浓荫,是冬雪中的一株梅红……微笑着去面对吧,你会感到人生是那样的温馨与甜蜜!
package com.stay.pull.lib;
import android.content.Context; import android.content.res.TypedArray; import android.graphics.Color; import android.os.Handler; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.animation.AccelerateDecelerateInterpolator; import android.view.animation.Interpolator; import android.widget.LinearLayout; import com.stay.pull.R; import com.stay.pull.lib.internal.LoadingLayout; public abstract class PullToRefreshBase<T extends View> extends LinearLayout { final class SmoothScrollRunnable implements Runnable { static final int ANIMATION_DURATION_MS = 190; static final int ANIMATION_FPS = 1000 / 60; private final Interpolator interpolator; private final int scrollToY; private final int scrollFromY; private final Handler handler; private boolean continueRunning = true; private long startTime = -1; private int currentY = -1; public SmoothScrollRunnable(Handler handler, int fromY, int toY) { this.handler = handler; this.scrollFromY = fromY; this.scrollToY = toY; this.interpolator = new AccelerateDecelerateInterpolator(); } @Override public void run() { /** * Only set startTime if this is the first time we're starting, else * actually calculate the Y delta */ if (startTime == -1) { startTime = System.currentTimeMillis(); } else { /** * We do do all calculations in long to reduce software float * calculations. We use 1000 as it gives us good accuracy and * small rounding errors */ long normalizedTime = (1000 * (System.currentTimeMillis() - startTime)) / ANIMATION_DURATION_MS; normalizedTime = Math.max(Math.min(normalizedTime, 1000), 0); final int deltaY = Math.round((scrollFromY - scrollToY) * interpolator.getInterpolation(normalizedTime / 1000f)); this.currentY = scrollFromY - deltaY; setHeaderScroll(currentY); } // If we're not at the target Y, keep going... if (continueRunning && scrollToY != currentY) { handler.postDelayed(this, ANIMATION_FPS); } } public void stop() { this.continueRunning = false; this.handler.removeCallbacks(this); } }; // =========================================================== // Constants // =========================================================== static final float FRICTION = 2.0f; static final int PULL_TO_REFRESH = 0x0; static final int RELEASE_TO_REFRESH = 0x1; static final int REFRESHING = 0x2; static final int MANUAL_REFRESHING = 0x3; public static final int MODE_PULL_DOWN_TO_REFRESH = 0x1; public static final int MODE_PULL_UP_TO_REFRESH = 0x2; public static final int MODE_BOTH = 0x3; // =========================================================== // Fields // =========================================================== private int touchSlop; private float initialMotionY; private float lastMotionX; private float lastMotionY; private boolean isBeingDragged = false; private int state = PULL_TO_REFRESH; private int mode = MODE_PULL_DOWN_TO_REFRESH; private int currentMode; private boolean disableScrollingWhileRefreshing = true; T refreshableView; private boolean isPullToRefreshEnabled = true; private LoadingLayout headerLayout; private LoadingLayout footerLayout; private int headerHeight; private final Handler handler = new Handler(); private OnRefreshListener onRefreshListener; private SmoothScrollRunnable currentSmoothScrollRunnable; // =========================================================== // Constructors // =========================================================== public PullToRefreshBase(Context context) { super(context); init(context, null); } public PullToRefreshBase(Context context, int mode) { super(context); this.mode = mode; init(context, null); } public PullToRefreshBase(Context context, AttributeSet attrs) { super(context, attrs); init(context, attrs); } // =========================================================== // Getter & Setter // =========================================================== /** * Deprecated. Use {@link #getRefreshableView()} from now on. * * @deprecated * @return The Refreshable View which is currently wrapped */ public final T getAdapterView() { return refreshableView; } /** * Get the Wrapped Refreshable View. Anything returned here has already been * added to the content view. * * @return The View which is currently wrapped */ public final T getRefreshableView() { return refreshableView; } /** * Whether Pull-to-Refresh is enabled * * @return enabled */ public final boolean isPullToRefreshEnabled() { return isPullToRefreshEnabled; } /** * Returns whether the widget has disabled scrolling on the Refreshable View * while refreshing. * * @param true if the widget has disabled scrolling while refreshing */ public final boolean isDisableScrollingWhileRefreshing() { return disableScrollingWhileRefreshing; } /** * Returns whether the Widget is currently in the Refreshing state * * @return true if the Widget is currently refreshing */ public final boolean isRefreshing() { return state == REFRESHING || state == MANUAL_REFRESHING; } /** * By default the Widget disabled scrolling on the Refreshable View while * refreshing. This method can change this behaviour. * * @param disableScrollingWhileRefreshing * - true if you want to disable scrolling while refreshing */ public final void setDisableScrollingWhileRefreshing(boolean disableScrollingWhileRefreshing) { this.disableScrollingWhileRefreshing = disableScrollingWhileRefreshing; } /** * Mark the current Refresh as complete. Will Reset the UI and hide the * Refreshing View */ public final void onRefreshComplete() { if (state != PULL_TO_REFRESH) { resetHeader(); } } /** * Set OnRefreshListener for the Widget * * @param listener * - Listener to be used when the Widget is set to Refresh */ public final void setOnRefreshListener(OnRefreshListener listener) { onRefreshListener = listener; } /** * A mutator to enable/disable Pull-to-Refresh for the current View * * @param enable * Whether Pull-To-Refresh should be used */ public final void setPullToRefreshEnabled(boolean enable) { this.isPullToRefreshEnabled = enable; } /** * Set Text to show when the Widget is being pulled, and will refresh when * released * * @param releaseLabel * - String to display */ public void setReleaseLabel(String releaseLabel) { if (null != headerLayout) { headerLayout.setReleaseLabel(releaseLabel); } if (null != footerLayout) { footerLayout.setReleaseLabel(releaseLabel); } } /** * Set Text to show when the Widget is being Pulled * * @param pullLabel * - String to display */ public void setPullLabel(String pullLabel) { if (null != headerLayout) { headerLayout.setPullLabel(pullLabel); } if (null != footerLayout) { footerLayout.setPullLabel(pullLabel); } } /** * Set Text to show when the Widget is refreshing * * @param refreshingLabel * - String to display */ public void setRefreshingLabel(String refreshingLabel) { if (null != headerLayout) { headerLayout.setRefreshingLabel(refreshingLabel); } if (null != footerLayout) { footerLayout.setRefreshingLabel(refreshingLabel); } } public final void setRefreshing() { this.setRefreshing(true); } /** * Sets the Widget to be in the refresh state. The UI will be updated to * show the 'Refreshing' view. * * @param doScroll * - true if you want to force a scroll to the Refreshing view. */ public final void setRefreshing(boolean doScroll) { if (!isRefreshing()) { setRefreshingInternal(doScroll); state = MANUAL_REFRESHING; } } public final boolean hasPullFromTop() { return currentMode != MODE_PULL_UP_TO_REFRESH; } // =========================================================== // Methods for/from SuperClass/Interfaces // =========================================================== @Override public final boolean onTouchEvent(MotionEvent event) { if (!isPullToRefreshEnabled) { return false; } if (isRefreshing() && disableScrollingWhileRefreshing) { return true; } if (event.getAction() == MotionEvent.ACTION_DOWN && event.getEdgeFlags() != 0) { return false; } switch (event.getAction()) { case MotionEvent.ACTION_MOVE: { if (isBeingDragged) { lastMotionY = event.getY(); this.pullEvent(); return true; } break; } case MotionEvent.ACTION_DOWN: { if (isReadyForPull()) { lastMotionY = initialMotionY = event.getY(); return true; } break; } case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: { if (isBeingDragged) { isBeingDragged = false; if (state == RELEASE_TO_REFRESH && null != onRefreshListener) { setRefreshingInternal(true); onRefreshListener.onRefresh(); } else { smoothScrollTo(0); } return true; } break; } } return false; } @Override public final boolean onInterceptTouchEvent(MotionEvent event) { if (!isPullToRefreshEnabled) { return false; } if (isRefreshing() && disableScrollingWhileRefreshing) { return true; } final int action = event.getAction(); if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) { isBeingDragged = false; return false; } if (action != MotionEvent.ACTION_DOWN && isBeingDragged) { return true; } switch (action) { case MotionEvent.ACTION_MOVE: { if (isReadyForPull()) { final float y = event.getY(); final float dy = y - lastMotionY; final float yDiff = Math.abs(dy); final float xDiff = Math.abs(event.getX() - lastMotionX); if (yDiff > touchSlop && yDiff > xDiff) { if ((mode == MODE_PULL_DOWN_TO_REFRESH || mode == MODE_BOTH) && dy >= 0.0001f && isReadyForPullDown()) { lastMotionY = y; isBeingDragged = true; if (mode == MODE_BOTH) { currentMode = MODE_PULL_DOWN_TO_REFRESH; } } else if ((mode == MODE_PULL_UP_TO_REFRESH || mode == MODE_BOTH) && dy <= 0.0001f && isReadyForPullUp()) { lastMotionY = y; isBeingDragged = true; if (mode == MODE_BOTH) { currentMode = MODE_PULL_UP_TO_REFRESH; } } } } break; } case MotionEvent.ACTION_DOWN: { if (isReadyForPull()) { lastMotionY = initialMotionY = event.getY(); lastMotionX = event.getX(); isBeingDragged = false; } break; } } return isBeingDragged; } protected void addRefreshableView(Context context, T refreshableView) { addView(refreshableView, new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, 0, 1.0f)); } /** * This is implemented by derived classes to return the created View. If you * need to use a custom View (such as a custom ListView), override this * method and return an instance of your custom class. * * Be sure to set the ID of the view in this method, especially if you're * using a ListActivity or ListFragment. * * @param context * @param attrs * AttributeSet from wrapped class. Means that anything you * include in the XML layout declaration will be routed to the * created View * @return New instance of the Refreshable View */ protected abstract T createRefreshableView(Context context, AttributeSet attrs); protected final int getCurrentMode() { return currentMode; } protected final LoadingLayout getFooterLayout() { return footerLayout; } protected final LoadingLayout getHeaderLayout() { return headerLayout; } protected final int getHeaderHeight() { return headerHeight; } protected final int getMode() { return mode; } /** * Implemented by derived class to return whether the View is in a state * where the user can Pull to Refresh by scrolling down. * * @return true if the View is currently the correct state (for example, top * of a ListView) */ protected abstract boolean isReadyForPullDown(); /** * Implemented by derived class to return whether the View is in a state * where the user can Pull to Refresh by scrolling up. * * @return true if the View is currently in the correct state (for example, * bottom of a ListView) */ protected abstract boolean isReadyForPullUp(); // =========================================================== // Methods // =========================================================== protected void resetHeader() { state = PULL_TO_REFRESH; isBeingDragged = false; if (null != headerLayout) { headerLayout.reset(); } if (null != footerLayout) { footerLayout.reset(); } smoothScrollTo(0); } protected void setRefreshingInternal(boolean doScroll) { state = REFRESHING; if (null != headerLayout) { headerLayout.refreshing(); } if (null != footerLayout) { footerLayout.refreshing(); } if (doScroll) { smoothScrollTo(currentMode == MODE_PULL_DOWN_TO_REFRESH ? -headerHeight : headerHeight); } } protected final void setHeaderScroll(int y) { scrollTo(0, y); } protected final void smoothScrollTo(int y) { if (null != currentSmoothScrollRunnable) { currentSmoothScrollRunnable.stop(); } if (this.getScrollY() != y) { this.currentSmoothScrollRunnable = new SmoothScrollRunnable(handler, getScrollY(), y); handler.post(currentSmoothScrollRunnable); } } private void init(Context context, AttributeSet attrs) { setOrientation(LinearLayout.VERTICAL); touchSlop = ViewConfiguration.getTouchSlop(); // Styleables from XML TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PullToRefresh); if (a.hasValue(R.styleable.PullToRefresh_mode)) { mode = a.getInteger(R.styleable.PullToRefresh_mode, MODE_PULL_DOWN_TO_REFRESH); } // Refreshable View // By passing the attrs, we can add ListView/GridView params via XML refreshableView = this.createRefreshableView(context, attrs); this.addRefreshableView(context, refreshableView); // Loading View Strings String pullLabel = context.getString(R.string.pull_to_refresh_pull_label); String refreshingLabel = context.getString(R.string.pull_to_refresh_refreshing_label); String releaseLabel = context.getString(R.string.pull_to_refresh_release_label); // Add Loading Views if (mode == MODE_PULL_DOWN_TO_REFRESH || mode == MODE_BOTH) { headerLayout = new LoadingLayout(context, MODE_PULL_DOWN_TO_REFRESH, releaseLabel, pullLabel, refreshingLabel); addView(headerLayout, 0, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); measureView(headerLayout); headerHeight = headerLayout.getMeasuredHeight(); } if (mode == MODE_PULL_UP_TO_REFRESH || mode == MODE_BOTH) { footerLayout = new LoadingLayout(context, MODE_PULL_UP_TO_REFRESH, releaseLabel, pullLabel, refreshingLabel); addView(footerLayout, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); measureView(footerLayout); headerHeight = footerLayout.getMeasuredHeight(); } // Styleables from XML if (a.hasValue(R.styleable.PullToRefresh_headerTextColor)) { final int color = a.getColor(R.styleable.PullToRefresh_headerTextColor, Color.BLACK); if (null != headerLayout) { headerLayout.setTextColor(color); } if (null != footerLayout) { footerLayout.setTextColor(color); } } if (a.hasValue(R.styleable.PullToRefresh_headerBackground)) { this.setBackgroundResource(a.getResourceId(R.styleable.PullToRefresh_headerBackground, Color.WHITE)); } if (a.hasValue(R.styleable.PullToRefresh_adapterViewBackground)) { refreshableView.setBackgroundResource(a.getResourceId(R.styleable.PullToRefresh_adapterViewBackground, Color.WHITE)); } a.recycle(); // Hide Loading Views switch (mode) { case MODE_BOTH: setPadding(0, -headerHeight, 0, -headerHeight); break; case MODE_PULL_UP_TO_REFRESH: setPadding(0, 0, 0, -headerHeight); break; case MODE_PULL_DOWN_TO_REFRESH: default: setPadding(0, -headerHeight, 0, 0); break; } // If we're not using MODE_BOTH, then just set currentMode to current // mode if (mode != MODE_BOTH) { currentMode = mode; } } private void measureView(View child) { ViewGroup.LayoutParams p = child.getLayoutParams(); if (p == null) { p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_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); } /** * Actions a Pull Event * * @return true if the Event has been handled, false if there has been no * change */ private boolean pullEvent() { final int newHeight; final int oldHeight = this.getScrollY(); switch (currentMode) { case MODE_PULL_UP_TO_REFRESH: newHeight = Math.round(Math.max(initialMotionY - lastMotionY, 0) / FRICTION); //newHeight = Math.round((initialMotionY - lastMotionY) / FRICTION); break; case MODE_PULL_DOWN_TO_REFRESH: default: newHeight = Math.round(Math.min(initialMotionY - lastMotionY, 0) / FRICTION); //newHeight = Math.round((initialMotionY - lastMotionY) / FRICTION); break; } setHeaderScroll(newHeight); if (newHeight != 0) { if (state == PULL_TO_REFRESH && headerHeight < Math.abs(newHeight)) { state = RELEASE_TO_REFRESH; switch (currentMode) { case MODE_PULL_UP_TO_REFRESH: footerLayout.releaseToRefresh(); break; case MODE_PULL_DOWN_TO_REFRESH: headerLayout.releaseToRefresh(); break; } return true; } else if (state == RELEASE_TO_REFRESH && headerHeight >= Math.abs(newHeight)) { state = PULL_TO_REFRESH; switch (currentMode) { case MODE_PULL_UP_TO_REFRESH: footerLayout.pullToRefresh(); break; case MODE_PULL_DOWN_TO_REFRESH: headerLayout.pullToRefresh(); break; } return true; } } return oldHeight != newHeight; } private boolean isReadyForPull() { switch (mode) { case MODE_PULL_DOWN_TO_REFRESH: return isReadyForPullDown(); case MODE_PULL_UP_TO_REFRESH: return isReadyForPullUp(); case MODE_BOTH: return isReadyForPullUp() || isReadyForPullDown(); } return false; } // =========================================================== // Inner and Anonymous Classes // =========================================================== public static interface OnRefreshListener { public void onRefresh(); } public static interface OnLastItemVisibleListener { public void onLastItemVisible(); } @Override public void setLongClickable(boolean longClickable) { getRefreshableView().setLongClickable(longClickable); } }
package com.stay.pull.lib;
import android.content.Context; import android.util.AttributeSet; import android.view.ContextMenu.ContextMenuInfo; import android.view.View; import android.widget.ListView; import com.stay.pull.lib.internal.EmptyViewMethodAccessor; public class PullToRefreshListView extends PullToRefreshAdapterViewBase<ListView> { //private LoadingLayout headerLoadingView; //private LoadingLayout footerLoadingView; class InternalListView extends ListView implements EmptyViewMethodAccessor { public InternalListView(Context context, AttributeSet attrs) { super(context, attrs); } @Override public void setEmptyView(View emptyView) { PullToRefreshListView.this.setEmptyView(emptyView); } @Override public void setEmptyViewInternal(View emptyView) { super.setEmptyView(emptyView); } public ContextMenuInfo getContextMenuInfo() { return super.getContextMenuInfo(); } } public PullToRefreshListView(Context context) { super(context); this.setDisableScrollingWhileRefreshing(false); } public PullToRefreshListView(Context context, int mode) { super(context, mode); this.setDisableScrollingWhileRefreshing(false); } public PullToRefreshListView(Context context, AttributeSet attrs) { super(context, attrs); this.setDisableScrollingWhileRefreshing(false); } @Override public ContextMenuInfo getContextMenuInfo() { return ((InternalListView) getRefreshableView()).getContextMenuInfo(); } //public void setReleaseLabel(String releaseLabel) { //super.setReleaseLabel(releaseLabel); //if (null != headerLoadingView) { //headerLoadingView.setReleaseLabel(releaseLabel); //} //if (null != footerLoadingView) { //footerLoadingView.setReleaseLabel(releaseLabel); //} //} // //public void setPullLabel(String pullLabel) { //super.setPullLabel(pullLabel); // //if (null != headerLoadingView) { //headerLoadingView.setPullLabel(pullLabel); //} //if (null != footerLoadingView) { //footerLoadingView.setPullLabel(pullLabel); //} //} // //public void setRefreshingLabel(String refreshingLabel) { //super.setRefreshingLabel(refreshingLabel); // //if (null != headerLoadingView) { //headerLoadingView.setRefreshingLabel(refreshingLabel); //} //if (null != footerLoadingView) { //footerLoadingView.setRefreshingLabel(refreshingLabel); //} //} @Override protected final ListView createRefreshableView(Context context, AttributeSet attrs) { ListView lv = new InternalListView(context, attrs); //final int mode = this.getMode(); // Loading View Strings //String pullLabel = context.getString(R.string.pull_to_refresh_pull_label); //String refreshingLabel = context.getString(R.string.pull_to_refresh_refreshing_label); //String releaseLabel = context.getString(R.string.pull_to_refresh_release_label); // Add Loading Views //if (mode == MODE_PULL_DOWN_TO_REFRESH || mode == MODE_BOTH) { //FrameLayout frame = new FrameLayout(context); //headerLoadingView = new LoadingLayout(context, MODE_PULL_DOWN_TO_REFRESH, releaseLabel, pullLabel, //refreshingLabel); //frame.addView(headerLoadingView, FrameLayout.LayoutParams.FILL_PARENT, //FrameLayout.LayoutParams.WRAP_CONTENT); //headerLoadingView.setVisibility(View.GONE); //lv.addHeaderView(frame); //} //if (mode == MODE_PULL_UP_TO_REFRESH || mode == MODE_BOTH) { //FrameLayout frame = new FrameLayout(context); //footerLoadingView = new LoadingLayout(context, MODE_PULL_UP_TO_REFRESH, releaseLabel, pullLabel, //refreshingLabel); //frame.addView(footerLoadingView, FrameLayout.LayoutParams.FILL_PARENT, //FrameLayout.LayoutParams.WRAP_CONTENT); //footerLoadingView.setVisibility(View.GONE); //lv.addFooterView(frame); //} // Set it to this so it can be used in ListActivity/ListFragment lv.setId(android.R.id.list); return lv; } //@Override //protected void setRefreshingInternal(boolean doScroll) { //super.setRefreshingInternal(false); // //final LoadingLayout originalLoadingLayout, listViewLoadingLayout; //final int selection, scrollToY; // //switch (getCurrentMode()) { //case MODE_PULL_UP_TO_REFRESH: //originalLoadingLayout = this.getFooterLayout(); //listViewLoadingLayout = this.footerLoadingView; //selection = refreshableView.getCount() - 1; //scrollToY = getScrollY() - getHeaderHeight(); //break; //case MODE_PULL_DOWN_TO_REFRESH: //default: //originalLoadingLayout = this.getHeaderLayout(); //listViewLoadingLayout = this.headerLoadingView; //selection = 0; //scrollToY = getScrollY() + getHeaderHeight(); //break; //} // //if (doScroll) { We scroll slightly so that the ListView's header/footer is at the same Y position as our normal header/footer //this.setHeaderScroll(scrollToY); //} // Hide our original Loading View //originalLoadingLayout.setVisibility(View.INVISIBLE); // Show the ListView Loading View and set it to refresh //listViewLoadingLayout.setVisibility(View.VISIBLE); //listViewLoadingLayout.refreshing(); // //if (doScroll) { Make sure the ListView is scrolled to show the loading header/footer //refreshableView.setSelection(selection); // Smooth scroll as normal //smoothScrollTo(0); //} //} //@Override //protected void resetHeader() { // //LoadingLayout originalLoadingLayout; //LoadingLayout listViewLoadingLayout; // //int scrollToHeight = getHeaderHeight(); //final boolean doScroll; // //switch (getCurrentMode()) { //case MODE_PULL_UP_TO_REFRESH: //originalLoadingLayout = this.getFooterLayout(); //listViewLoadingLayout = footerLoadingView; //doScroll = this.isReadyForPullUp(); //break; //case MODE_PULL_DOWN_TO_REFRESH: //default: //originalLoadingLayout = this.getHeaderLayout(); //listViewLoadingLayout = headerLoadingView; //scrollToHeight *= -1; //doScroll = this.isReadyForPullDown(); //break; //} // Set our Original View to Visible //originalLoadingLayout.setVisibility(View.VISIBLE); // Scroll so our View is at the same Y as the ListView header/footer, but only scroll if the ListView is at the top/bottom //if (doScroll) { //this.setHeaderScroll(scrollToHeight); //} // Hide the ListView Header/Footer //listViewLoadingLayout.setVisibility(View.GONE); // //super.resetHeader(); //} }
package com.stay.pull.lib.internal;
import android.view.View; import android.widget.ImageView; /** * Interface that allows PullToRefreshBase to hijack the call to * AdapterView.setEmptyView() * * @author chris */ public interface EmptyViewMethodAccessor { /** * Calls upto AdapterView.setEmptyView() * * @param View * to set as Empty View */ public void setEmptyViewInternal(View emptyView); /** * Should call PullToRefreshBase.setEmptyView() which will then * automatically call through to setEmptyViewInternal() * * @param View * to set as Empty View */ public void setEmptyView(View emptyView); }
package com.stay.pull.lib.internal;
import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.animation.Animation; import android.view.animation.Interpolator; import android.view.animation.LinearInterpolator; import android.view.animation.RotateAnimation; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; import com.stay.pull.R; import com.stay.pull.lib.PullToRefreshBase; public class LoadingLayout extends FrameLayout { static final int DEFAULT_ROTATION_ANIMATION_DURATION = 150; private final ImageView headerImage; private final ProgressBar headerProgress; private final TextView headerText; private String pullLabel; private String refreshingLabel; private String releaseLabel; private final Animation rotateAnimation, resetRotateAnimation; public LoadingLayout(Context context, final int mode, String releaseLabel, String pullLabel, String refreshingLabel) { super(context); ViewGroup header = (ViewGroup) LayoutInflater.from(context).inflate(R.layout.pull_to_refresh_header, this); headerText = (TextView) header.findViewById(R.id.pull_to_refresh_text); headerImage = (ImageView) header.findViewById(R.id.pull_to_refresh_image); headerProgress = (ProgressBar) header.findViewById(R.id.pull_to_refresh_progress); final Interpolator interpolator = new LinearInterpolator(); rotateAnimation = new RotateAnimation(0, -180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); rotateAnimation.setInterpolator(interpolator); rotateAnimation.setDuration(DEFAULT_ROTATION_ANIMATION_DURATION); rotateAnimation.setFillAfter(true); resetRotateAnimation = new RotateAnimation(-180, 0, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); resetRotateAnimation.setInterpolator(interpolator); resetRotateAnimation.setDuration(DEFAULT_ROTATION_ANIMATION_DURATION); resetRotateAnimation.setFillAfter(true); this.releaseLabel = releaseLabel; this.pullLabel = pullLabel; this.refreshingLabel = refreshingLabel; switch (mode) { case PullToRefreshBase.MODE_PULL_UP_TO_REFRESH: headerImage.setImageResource(R.drawable.pulltorefresh_up_arrow); break; case PullToRefreshBase.MODE_PULL_DOWN_TO_REFRESH: default: headerImage.setImageResource(R.drawable.pulltorefresh_down_arrow); break; } } public void reset() { headerText.setText(pullLabel); headerImage.setVisibility(View.VISIBLE); headerProgress.setVisibility(View.GONE); } public void releaseToRefresh() { headerText.setText(releaseLabel); headerImage.clearAnimation(); headerImage.startAnimation(rotateAnimation); } public void setPullLabel(String pullLabel) { this.pullLabel = pullLabel; } public void refreshing() { headerText.setText(refreshingLabel); headerImage.clearAnimation(); headerImage.setVisibility(View.INVISIBLE); headerProgress.setVisibility(View.VISIBLE); } public void setRefreshingLabel(String refreshingLabel) { this.refreshingLabel = refreshingLabel; } public void setReleaseLabel(String releaseLabel) { this.releaseLabel = releaseLabel; } public void pullToRefresh() { headerText.setText(pullLabel); headerImage.clearAnimation(); headerImage.startAnimation(resetRotateAnimation); } public void setTextColor(int color) { headerText.setTextColor(color); } }
文章结束给大家分享下程序员的一些笑话语录: 程序语言综述
CLIPPER 程序员不去真的猎捕大象,他们只是购买大象部分的库然后花几年的时间试图综合它们。 DBASE 程序员只在夜间猎捕大象,因为那时没人会注意到他们还在使用石弓。 FOXPRO 程序员开始使用更新更好的步枪,这使他们花掉比实际狩猎更多的时间学习新的射击技术。 C 程序员拒绝直接购买步枪,宁可带着钢管和一个移动式机器车间到非洲,意欲从零开始造一枝完美的步枪。 PARADOX 程序员去非洲时带着好莱坞关于猎捕大象的电影剧本,他们认为照剧本行事就会逮到一头大象。 ACCESS 程序员在没有任何猎象经验的经验下就出发了,他们穿着华丽的猎装、带着全部装备,用漂亮的望远镜找到了大象,然后发觉忘了带扳机。 RBASE 程序员比大象还要稀少,事实上,如果一头大象看到了一个RBASE程序员,对他是个幸运日。 VISUAL ACCESS 程序员装上子弹、举起步枪、瞄准大象,这使大象感到可笑,究竟谁逃跑。他们无法抓住大象,因为由于他们对多重控制的偏爱,他们的吉普车有太多的方向盘因而无法驾驶。 ADA、APL和FORTRAN 程序员与圣诞老人和仙女一样是虚构的。 COBOL 程序员对和自己一样濒临灭绝的大象寄予了深切的同情。