Android下拉刷新,在目前好多應用被使用到。
比如微博,下拉刷新更多數據。
一般我們在運用的ListView,本身就實現了下拉獲取更多數據。只是這個下拉刷新的操作時在listView拉到底端的監聽。
對於ListView刷新,我們可以分為兩種情況:
1.獲取更多的數據,按服務器數據庫時間順序存儲入情況,此刻我們是獲取是顯示在我們應用中的數據更早前的數據,這也是最常見的情況。
比如(微博獲取更多信息,就是獲取更多更早前的信息,然後動態的添加到已有的數據的下方);
2.獲取更多的最新的數據,其實還是一種獲取更多的操作方式。但是這裡主要考慮到用戶的操作習慣了。一般,用戶的操作習慣分這麼兩種
第一種,獲取下一頁,第二種,類似於網頁的F5刷新,停留在當前頁面的刷新。
ListView刷新其實類似於網頁。如果沒用下拉刷新,那麼用戶得將ListView拖拉到最後(當然也可以是在界面頂端添加一個刷新按鈕控件,但是,對於手機這樣界面不是很大,這樣的設計其實是不應太多的。),如果數據太多,那麼用戶要下拉到很下面才能執行刷新。而對於大多數用戶習慣,獲取更多的最新資訊後,希望他添加的時候是在界面最上面的顯眼處的。也就是,用戶還是喜歡的是懶操作,在同一個可顯示界面完成所有操作。那麼,下拉刷新是一個不錯的設計。
效果圖:正常狀態
下拉刷新:
基本效果就是這樣。
自定義控件代碼
[java]
- /**
- * 刷新控制view
- *
- * @author Nono
- *
- */
- public class RefreshableView extends LinearLayout {
-
- private static final String TAG = "LILITH";
- private Scroller scroller;
- private View refreshView;
- private ImageView refreshIndicatorView;
- private int refreshTargetTop = -60;
- private ProgressBar bar;
- private TextView downTextView;
- private TextView timeTextView;
-
- private RefreshListener refreshListener;
-
- private String downTextString;
- private String releaseTextString;
-
- private Long refreshTime = null;
- private int lastX;
- private int lastY;
- // 拉動標記
- private boolean isDragging = false;
- // 是否可刷新標記
- private boolean isRefreshEnabled = true;
- // 在刷新中標記
- private boolean isRefreshing = false;
-
-
- private Context mContext;
- public RefreshableView(Context context) {
- super(context);
- mContext = context;
-
- }
- public RefreshableView(Context context, AttributeSet attrs) {
- super(context, attrs);
- mContext = context;
- init();
-
- }
- private void init() {
- // TODO Auto-generated method stub
- //滑動對象,
- scroller = new Scroller(mContext);
-
- //刷新視圖頂端的的view
- refreshView = LayoutInflater.from(mContext).inflate(R.layout.refresh_top_item, null);
- //指示器view
- refreshIndicatorView = (ImageView) refreshView.findViewById(R.id.indicator);
- //刷新bar
- bar = (ProgressBar) refreshView.findViewById(R.id.progress);
- //下拉顯示text
- downTextView = (TextView) refreshView.findViewById(R.id.refresh_hint);
- //下來顯示時間
- timeTextView = (TextView) refreshView.findViewById(R.id.refresh_time);
-
- LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, -refreshTargetTop);
- lp.topMargin = refreshTargetTop;
- lp.gravity = Gravity.CENTER;
- addView(refreshView, lp);
- downTextString = mContext.getResources().getString(R.string.refresh_down_text);
- releaseTextString = mContext.getResources().getString(R.string.refresh_release_text);
- }
-
-
-
-
- /**
- * 刷新
- * @param time
- */
- private void setRefreshText(String time) {
- // TODO Auto-generated method stub
- //timeTextView.setText(time);
- }
-
-
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
-
- int y= (int) event.getRawY();
-
-
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- //記錄下y坐標
- lastY = y;
- break;
-
- case MotionEvent.ACTION_MOVE:
- Log.i(TAG, "ACTION_MOVE");
- //y移動坐標
- int m = y - lastY;
- if(((m < 6) && (m > -1)) || (!isDragging )){
- doMovement(m);
- }
- //記錄下此刻y坐標
- this.lastY = y;
- break;
-
- case MotionEvent.ACTION_UP:
- Log.i(TAG, "ACTION_UP");
-
- fling();
-
- break;
- }
- return true;
- }
-
-
- /**
- * up事件處理
- */
- private void fling() {
- // TODO Auto-generated method stub
- LinearLayout.LayoutParams lp = (LayoutParams) refreshView.getLayoutParams();
- Log.i(TAG, "fling()" + lp.topMargin);
- if(lp.topMargin > 0){//拉到了觸發可刷新事件
- refresh();
- }else{
- returnInitState();
- }
- }
-
-
-
- private void returnInitState() {
- // TODO Auto-generated method stub
- LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)this.refreshView.getLayoutParams();
- int i = lp.topMargin;
- scroller.startScroll(0, i, 0, refreshTargetTop);
- invalidate();
- }
- private void refresh() {
- // TODO Auto-generated method stub
- LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)this.refreshView.getLayoutParams();
- int i = lp.topMargin;
- refreshIndicatorView.setVisibility(View.GONE);
- bar.setVisibility(View.VISIBLE);
- timeTextView.setVisibility(View.GONE);
- downTextView.setVisibility(View.GONE);
- scroller.startScroll(0, i, 0, 0-i);
- invalidate();
- if(refreshListener !=null){
- refreshListener.onRefresh(this);
- isRefreshing = true;
- }
- }
-
- /**
- *
- */
- @Override
- public void computeScroll() {
- // TODO Auto-generated method stub
- if(scroller.computeScrollOffset()){
- int i = this.scroller.getCurrY();
- LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)this.refreshView.getLayoutParams();
- int k = Math.max(i, refreshTargetTop);
- lp.topMargin = k;
- this.refreshView.setLayoutParams(lp);
- this.refreshView.invalidate();
- invalidate();
- }
- }
- /**
- * 下拉move事件處理
- * @param moveY
- */
- private void doMovement(int moveY) {
- // TODO Auto-generated method stub
- LinearLayout.LayoutParams lp = (LayoutParams) refreshView.getLayoutParams();
- if(moveY > 0){
- //獲取view的上邊距
- float f1 =lp.topMargin;
- float f2 = moveY * 0.3F;
- int i = (int)(f1+f2);
- //修改上邊距
- lp.topMargin = i;
- //修改後刷新
- refreshView.setLayoutParams(lp);
- refreshView.invalidate();
- invalidate();
- }
- timeTextView.setVisibility(View.VISIBLE);
- if(refreshTime!= null){
- setRefreshTime(refreshTime);
- }
- downTextView.setVisibility(View.VISIBLE);
-
- refreshIndicatorView.setVisibility(View.VISIBLE);
- bar.setVisibility(View.GONE);
- if(lp.topMargin > 0){
- downTextView.setText(R.string.refresh_release_text);
- refreshIndicatorView.setImageResource(R.drawable.refresh_arrow_up);
- }else{
- downTextView.setText(R.string.refresh_down_text);
- refreshIndicatorView.setImageResource(R.drawable.refresh_arrow_down);
- }
-
- }
-
- public void setRefreshEnabled(boolean b) {
- this.isRefreshEnabled = b;
- }
-
- public void setRefreshListener(RefreshListener listener) {
- this.refreshListener = listener;
- }
-
- /**
- * 刷新時間
- * @param refreshTime2
- */
- private void setRefreshTime(Long time) {
- // TODO Auto-generated method stub
-
- }
-
- /**
- * 結束刷新事件
- */
- public void finishRefresh(){
- Log.i(TAG, "執行了=====finishRefresh");
- LinearLayout.LayoutParams lp= (LinearLayout.LayoutParams)this.refreshView.getLayoutParams();
- int i = lp.topMargin;
- refreshIndicatorView.setVisibility(View.VISIBLE);
- timeTextView.setVisibility(View.VISIBLE);
- scroller.startScroll(0, i, 0, refreshTargetTop);
- invalidate();
- isRefreshing = false;
- }
-
-
- /*該方法一般和ontouchEvent 一起用
- * (non-Javadoc)
- * @see android.view.ViewGroup#onInterceptTouchEvent(android.view.MotionEvent)
- */
- @Override
- public boolean onInterceptTouchEvent(MotionEvent e) {
- // TODO Auto-generated method stub
- int action = e.getAction();
- int y= (int) e.getRawY();
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- lastY = y;
- break;
-
- case MotionEvent.ACTION_MOVE:
- //y移動坐標
- int m = y - lastY;
-
- //記錄下此刻y坐標
- this.lastY = y;
- if(m > 6 && canScroll()){
- return true;
- }
- break;
- case MotionEvent.ACTION_UP:
-
- break;
-
- case MotionEvent.ACTION_CANCEL:
-
- break;
- }
- return false;
- }
- private boolean canScroll() {
- // TODO Auto-generated method stub
- View childView;
- if(getChildCount()>1){
- childView = this.getChildAt(1);
- if(childView instanceof ListView){
- int top =((ListView)childView).getChildAt(0).getTop();
- int pad =((ListView)childView).getListPaddingTop();
- if((Math.abs(top-pad)) < 3&&
- ((ListView) childView).getFirstVisiblePosition() == 0){
- return true;
- }else{
- return false;
- }
- }else if(childView instanceof ScrollView){
- if(((ScrollView)childView).getScrollY() == 0){
- return true;
- }else{
- return false;
- }
- }
-
- }
- return false;
- }
- /**
- * 刷新監聽接口
- * @author Nono
- *
- */
- public interface RefreshListener{
- public void onRefresh(RefreshableView view);
- }
- }
此控件自定義實現一個線性布局,內部包含一個第一個子控件,刷新顯示的View。