上拉刷新下拉加載PullToRefreshLayout

java    java

pullable代碼android

package com.example.lsy.tianmi.base.commonview;

public interface Pullable
{
   /**
    * 判斷是否能夠下拉,若是不須要下拉功能能夠直接return false
    * 
    * @return true若是能夠下拉不然返回false
    */
   boolean canPullDown();

   /**
    * 判斷是否能夠上拉,若是不須要上拉功能能夠直接return false
    * 
    * @return true若是能夠上拉不然返回false
    */
   boolean canPullUp();
}
PullableScrollview   注意這個能夠改爲你想要的 只要繼承它,好比繼承scrollView
package com.example.lsy.tianmi.base.commonview;

import android.content.Context;
import android.util.AttributeSet;

import android.widget.ScrollView;

public class PullableScrollview extends ScrollView implements Pullable
{

   public PullableScrollview(Context context)
   {
      super(context);
   }

   public PullableScrollview(Context context, AttributeSet attrs)
   {
      super(context, attrs);
   }

   public PullableScrollview(Context context, AttributeSet attrs, int defStyle)
   {
      super(context, attrs, defStyle);
   }

   @Override
   public boolean canPullDown()
   {
      if (getScrollY() == 0)
         return true;
      else
         return false;
   }

   @Override
   public boolean canPullUp()
   {
      if (getScrollY() >= (getChildAt(0).getHeight() - getMeasuredHeight()))
         return true;
      else
         return false;
   }
}
PullToRefreshLayout
package com.example.lsy.tianmi.base.commonview;

import android.content.Context;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.RelativeLayout;
import android.widget.TextView;


import com.example.lsy.tianmi.R;

import java.util.Timer;
import java.util.TimerTask;

/**
 * 自定義的佈局,用來管理三個子控件,其中一個是下拉頭,一個是包含內容的pullableView(能夠是實現Pullable接口的的任何View),
 * 還有一個上拉頭,更多詳解見博客http://blog.csdn.net/zhongkejingwang/article/details/38868463
 * 
 * @author 陳靖
 */
public class PullToRefreshLayout extends RelativeLayout
{
   public static final String TAG = "PullToRefreshLayout";
   // 初始狀態
   public static final int INIT = 0;
   // 釋放刷新
   public static final int RELEASE_TO_REFRESH = 1;
   // 正在刷新
   public static final int REFRESHING = 2;
   // 釋放加載
   public static final int RELEASE_TO_LOAD = 3;
   // 正在加載
   public static final int LOADING = 4;
   // 操做完畢
   public static final int DONE = 5;
   // 當前狀態
   private int state = INIT;
   // 刷新回調接口
   private OnRefreshListener mListener;
   // 刷新成功
   public static final int SUCCEED = 0;
   // 刷新失敗
   public static final int FAIL = 1;
   // 按下Y座標,上一個事件點Y座標
   private float downY, lastY;

   // 下拉的距離。注意:pullDownY和pullUpY不可能同時不爲0
   public float pullDownY = 0;
   // 上拉的距離
   private float pullUpY = 0;

   // 釋放刷新的距離
   private float refreshDist = 200;
   // 釋放加載的距離
   private float loadmoreDist = 200;

   private MyTimer timer;
   // 回滾速度
   public float MOVE_SPEED = 8;
   // 第一次執行佈局
   private boolean isLayout = false;
   // 在刷新過程當中滑動操做
   private boolean isTouch = false;
   // 手指滑動距離與下拉頭的滑動距離比,中間會隨正切函數變化
   private float radio = 2;

   // 下拉箭頭的轉180°動畫
   private RotateAnimation rotateAnimation;
   // 均勻旋轉動畫
   private RotateAnimation refreshingAnimation;

   // 下拉頭
   private View refreshView;
   // 下拉的箭頭
   private View pullView;
   // 正在刷新的圖標
   private View refreshingView;
   // 刷新結果圖標
   private View refreshStateImageView;
   // 刷新結果:成功或失敗
   private TextView refreshStateTextView;

   // 上拉頭
   private View loadmoreView;
   // 上拉的箭頭
   private View pullUpView;
   // 正在加載的圖標
   private View loadingView;
   // 加載結果圖標
   private View loadStateImageView;
   // 加載結果:成功或失敗
   private TextView loadStateTextView;

   // 實現了Pullable接口的View
   private View pullableView;
   // 過濾多點觸碰
   private int mEvents;
   // 這兩個變量用來控制pull的方向,若是不加控制,當狀況知足可上拉又可下拉時無法下拉
   private boolean canPullDown = true;
   private boolean canPullUp = true;

   private Context mContext;

   /**
    * 執行自動回滾的handler
    */
   Handler updateHandler = new Handler()
   {

      @Override
      public void handleMessage(Message msg)
      {
         // 回彈速度隨下拉距離moveDeltaY增大而增大
         MOVE_SPEED = (float) (8 + 5 * Math.tan(Math.PI / 2
               / getMeasuredHeight() * (pullDownY + Math.abs(pullUpY))));
         if (!isTouch)
         {
            // 正在刷新,且沒有往上推的話則懸停,顯示"正在刷新..."
            if (state == REFRESHING && pullDownY <= refreshDist)
            {
               pullDownY = refreshDist;
               timer.cancel();
            } else if (state == LOADING && -pullUpY <= loadmoreDist)
            {
               pullUpY = -loadmoreDist;
               timer.cancel();
            }

         }
         if (pullDownY > 0)
            pullDownY -= MOVE_SPEED;
         else if (pullUpY < 0)
            pullUpY += MOVE_SPEED;
         if (pullDownY < 0)
         {
            // 已完成回彈
            pullDownY = 0;
            pullView.clearAnimation();
            // 隱藏下拉頭時有可能還在刷新,只有當前狀態不是正在刷新時才改變狀態
            if (state != REFRESHING && state != LOADING)
               changeState(INIT);
            timer.cancel();
            requestLayout();
         }
         if (pullUpY > 0)
         {
            // 已完成回彈
            pullUpY = 0;
            pullUpView.clearAnimation();
            // 隱藏上拉頭時有可能還在刷新,只有當前狀態不是正在刷新時才改變狀態
            if (state != REFRESHING && state != LOADING)
               changeState(INIT);
            timer.cancel();
            requestLayout();
         }
         Log.d("handle", "handle");
         // 刷新佈局,會自動調用onLayout
         requestLayout();
         // 沒有拖拉或者回彈完成
         if (pullDownY + Math.abs(pullUpY) == 0)
            timer.cancel();
      }

   };

   public void setOnRefreshListener(OnRefreshListener listener)
   {
      mListener = listener;
   }

   public PullToRefreshLayout(Context context)
   {
      super(context);
      initView(context);
   }

   public PullToRefreshLayout(Context context, AttributeSet attrs)
   {
      super(context, attrs);
      initView(context);
   }

   public PullToRefreshLayout(Context context, AttributeSet attrs, int defStyle)
   {
      super(context, attrs, defStyle);
      initView(context);
   }

   private void initView(Context context)
   {
      mContext = context;
      timer = new MyTimer(updateHandler);
      rotateAnimation = (RotateAnimation) AnimationUtils.loadAnimation(
            context, R.anim.reverse_anim);
      refreshingAnimation = (RotateAnimation) AnimationUtils.loadAnimation(
            context, R.anim.rotating);
      // 添加勻速轉動動畫
      LinearInterpolator lir = new LinearInterpolator();
      rotateAnimation.setInterpolator(lir);
      refreshingAnimation.setInterpolator(lir);
   }

   private void hide()
   {
      timer.schedule(5);
   }

   /**
    * 完成刷新操做,顯示刷新結果。注意:刷新完成後必定要調用這個方法
    */
   /**
    * @param refreshResult
    *            PullToRefreshLayout.SUCCEED表明成功,PullToRefreshLayout.FAIL表明失敗
    */
   public void refreshFinish(int refreshResult)
   {
      refreshingView.clearAnimation();
      refreshingView.setVisibility(View.GONE);
      switch (refreshResult)
      {
      case SUCCEED:
         // 刷新成功
         refreshStateImageView.setVisibility(View.VISIBLE);
         refreshStateTextView.setText(R.string.refresh_succeed);
         refreshStateImageView
               .setBackgroundResource(R.mipmap.refresh_succeed);
         break;
      case FAIL:
      default:
         // 刷新失敗
         refreshStateImageView.setVisibility(View.VISIBLE);
         refreshStateTextView.setText(R.string.refresh_fail);
         refreshStateImageView
               .setBackgroundResource(R.mipmap.refresh_failed);
         break;
      }
      if (pullDownY > 0)
      {
         // 刷新結果停留1秒
         new Handler()
         {
            @Override
            public void handleMessage(Message msg)
            {
               changeState(DONE);
               hide();
            }
         }.sendEmptyMessageDelayed(0, 1000);
      } else
      {
         changeState(DONE);
         hide();
      }
   }

   /**
    * 加載完畢,顯示加載結果。注意:加載完成後必定要調用這個方法
    * 
    * @param refreshResult
    *            PullToRefreshLayout.SUCCEED表明成功,PullToRefreshLayout.FAIL表明失敗
    */
   public void loadmoreFinish(int refreshResult)
   {
      loadingView.clearAnimation();
      loadingView.setVisibility(View.GONE);
      switch (refreshResult)
      {
      case SUCCEED:
         // 加載成功
         loadStateImageView.setVisibility(View.VISIBLE);
         loadStateTextView.setText(R.string.load_succeed);
         loadStateImageView.setBackgroundResource(R.mipmap.load_succeed);
         break;
      case FAIL:
      default:
         // 加載失敗
         loadStateImageView.setVisibility(View.VISIBLE);
         loadStateTextView.setText(R.string.load_fail);
         loadStateImageView.setBackgroundResource(R.mipmap.load_failed);
         break;
      }
      if (pullUpY < 0)
      {
         // 刷新結果停留1秒
         new Handler()
         {
            @Override
            public void handleMessage(Message msg)
            {
               changeState(DONE);
               hide();
            }
         }.sendEmptyMessageDelayed(0, 1000);
      } else
      {
         changeState(DONE);
         hide();
      }
   }

   private void changeState(int to)
   {
      state = to;
      switch (state)
      {
      case INIT:
         // 下拉布局初始狀態
         refreshStateImageView.setVisibility(View.GONE);
         refreshStateTextView.setText(R.string.pull_to_refresh);
         pullView.clearAnimation();
         pullView.setVisibility(View.VISIBLE);
         // 上拉布局初始狀態
         loadStateImageView.setVisibility(View.GONE);
         loadStateTextView.setText(R.string.pullup_to_load);
         pullUpView.clearAnimation();
         pullUpView.setVisibility(View.VISIBLE);
         break;
      case RELEASE_TO_REFRESH:
         // 釋放刷新狀態
         refreshStateTextView.setText(R.string.release_to_refresh);
         pullView.startAnimation(rotateAnimation);
         break;
      case REFRESHING:
         // 正在刷新狀態
         pullView.clearAnimation();
         refreshingView.setVisibility(View.VISIBLE);
         pullView.setVisibility(View.INVISIBLE);
         refreshingView.startAnimation(refreshingAnimation);
         refreshStateTextView.setText(R.string.refreshing);
         break;
      case RELEASE_TO_LOAD:
         // 釋放加載狀態
         loadStateTextView.setText(R.string.release_to_load);
         pullUpView.startAnimation(rotateAnimation);
         break;
      case LOADING:
         // 正在加載狀態
         pullUpView.clearAnimation();
         loadingView.setVisibility(View.VISIBLE);
         pullUpView.setVisibility(View.INVISIBLE);
         loadingView.startAnimation(refreshingAnimation);
         loadStateTextView.setText(R.string.loading);
         break;
      case DONE:
         // 刷新或加載完畢,啥都不作
         break;
      }
   }

   /**
    * 不限制上拉或下拉
    */
   private void releasePull()
   {
      canPullDown = true;
      canPullUp = true;
   }

   /*
    * (非 Javadoc)由父控件決定是否分發事件,防止事件衝突
    * 
    * @see android.view.ViewGroup#dispatchTouchEvent(android.view.MotionEvent)
    */
   @Override
   public boolean dispatchTouchEvent(MotionEvent ev)
   {
      switch (ev.getActionMasked())
      {
      case MotionEvent.ACTION_DOWN:
         downY = ev.getY();
         lastY = downY;
         timer.cancel();
         mEvents = 0;
         releasePull();
         break;
      case MotionEvent.ACTION_POINTER_DOWN:
      case MotionEvent.ACTION_POINTER_UP:
         // 過濾多點觸碰
         mEvents = -1;
         break;
      case MotionEvent.ACTION_MOVE:
         if (mEvents == 0)
         {
            if (pullDownY > 0
                  || (((Pullable) pullableView).canPullDown()
                        && canPullDown && state != LOADING))
            {
               // 能夠下拉,正在加載時不能下拉
               // 對實際滑動距離作縮小,形成用力拉的感受
               pullDownY = pullDownY + (ev.getY() - lastY) / radio;
               if (pullDownY < 0)
               {
                  pullDownY = 0;
                  canPullDown = false;
                  canPullUp = true;
               }
               if (pullDownY > getMeasuredHeight())
                  pullDownY = getMeasuredHeight();
               if (state == REFRESHING)
               {
                  // 正在刷新的時候觸摸移動
                  isTouch = true;
               }
            } else if (pullUpY < 0
                  || (((Pullable) pullableView).canPullUp() && canPullUp && state != REFRESHING))
            {
               // 能夠上拉,正在刷新時不能上拉
               pullUpY = pullUpY + (ev.getY() - lastY) / radio;
               if (pullUpY > 0)
               {
                  pullUpY = 0;
                  canPullDown = true;
                  canPullUp = false;
               }
               if (pullUpY < -getMeasuredHeight())
                  pullUpY = -getMeasuredHeight();
               if (state == LOADING)
               {
                  // 正在加載的時候觸摸移動
                  isTouch = true;
               }
            } else
               releasePull();
         } else
            mEvents = 0;
         lastY = ev.getY();
         // 根據下拉距離改變比例
         radio = (float) (2 + 2 * Math.tan(Math.PI / 2 / getMeasuredHeight()
               * (pullDownY + Math.abs(pullUpY))));
         if (pullDownY > 0 || pullUpY < 0)
            requestLayout();
         if (pullDownY > 0)
         {
            if (pullDownY <= refreshDist
                  && (state == RELEASE_TO_REFRESH || state == DONE))
            {
               // 若是下拉距離沒達到刷新的距離且當前狀態是釋放刷新,改變狀態爲下拉刷新
               changeState(INIT);
            }
            if (pullDownY >= refreshDist && state == INIT)
            {
               // 若是下拉距離達到刷新的距離且當前狀態是初始狀態刷新,改變狀態爲釋放刷新
               changeState(RELEASE_TO_REFRESH);
            }
         } else if (pullUpY < 0)
         {
            // 下面是判斷上拉加載的,同上,注意pullUpY是負值
            if (-pullUpY <= loadmoreDist
                  && (state == RELEASE_TO_LOAD || state == DONE))
            {
               changeState(INIT);
            }
            // 上拉操做
            if (-pullUpY >= loadmoreDist && state == INIT)
            {
               changeState(RELEASE_TO_LOAD);
            }

         }
         // 由於刷新和加載操做不能同時進行,因此pullDownY和pullUpY不會同時不爲0,所以這裏用(pullDownY +
         // Math.abs(pullUpY))就能夠不對當前狀態做區分了
         if ((pullDownY + Math.abs(pullUpY)) > 8)
         {
            // 防止下拉過程當中誤觸發長按事件和點擊事件
            ev.setAction(MotionEvent.ACTION_CANCEL);
         }
         break;
      case MotionEvent.ACTION_UP:
         if (pullDownY > refreshDist || -pullUpY > loadmoreDist)
         // 正在刷新時往下拉(正在加載時往上拉),釋放後下拉頭(上拉頭)不隱藏
         {
            isTouch = false;
         }
         if (state == RELEASE_TO_REFRESH)
         {
            changeState(REFRESHING);
            // 刷新操做
            if (mListener != null)
               mListener.onRefresh(this);
         } else if (state == RELEASE_TO_LOAD)
         {
            changeState(LOADING);
            // 加載操做
            if (mListener != null)
               mListener.onLoadMore(this);
         }
         hide();
      default:
         break;
      }
      // 事件分發交給父類
      super.dispatchTouchEvent(ev);
      return true;
   }

   /**
    * @author chenjing 自動模擬手指滑動的task
    * 
    */
   private class AutoRefreshAndLoadTask extends
         AsyncTask<Integer, Float, String>
   {

      @Override
      protected String doInBackground(Integer... params)
      {
         while (pullDownY < 4 / 3 * refreshDist)
         {
            pullDownY += MOVE_SPEED;
            publishProgress(pullDownY);
            try
            {
               Thread.sleep(params[0]);
            } catch (InterruptedException e)
            {
               e.printStackTrace();
            }
         }
         return null;
      }

      @Override
      protected void onPostExecute(String result)
      {
         changeState(REFRESHING);
         // 刷新操做
         if (mListener != null)
            mListener.onRefresh(PullToRefreshLayout.this);
         hide();
      }

      @Override
      protected void onProgressUpdate(Float... values)
      {
         if (pullDownY > refreshDist)
            changeState(RELEASE_TO_REFRESH);
         requestLayout();
      }

   }

   /**
    * 自動刷新
    */
   public void autoRefresh()
   {
      AutoRefreshAndLoadTask task = new AutoRefreshAndLoadTask();
      task.execute(20);
   }

   /**
    * 自動加載
    */
   public void autoLoad()
   {
      pullUpY = -loadmoreDist;
      requestLayout();
      changeState(LOADING);
      // 加載操做
      if (mListener != null)
         mListener.onLoadMore(this);
   }

   private void initView()
   {
      // 初始化下拉布局
      pullView = refreshView.findViewById(R.id.pull_icon);
      refreshStateTextView = (TextView) refreshView
            .findViewById(R.id.state_tv);
      refreshingView = refreshView.findViewById(R.id.refreshing_icon);
      refreshStateImageView = refreshView.findViewById(R.id.state_iv);
      // 初始化上拉布局
      pullUpView = loadmoreView.findViewById(R.id.pullup_icon);
      loadStateTextView = (TextView) loadmoreView
            .findViewById(R.id.loadstate_tv);
      loadingView = loadmoreView.findViewById(R.id.loading_icon);
      loadStateImageView = loadmoreView.findViewById(R.id.loadstate_iv);
   }

   @Override
   protected void onLayout(boolean changed, int l, int t, int r, int b)
   {
      Log.d("Test", "Test");
      if (!isLayout)
      {
         // 這裏是第一次進來的時候作一些初始化
         refreshView = getChildAt(0);
         pullableView = getChildAt(1);
         loadmoreView = getChildAt(2);
         isLayout = true;
         initView();
         refreshDist = ((ViewGroup) refreshView).getChildAt(0)
               .getMeasuredHeight();
         loadmoreDist = ((ViewGroup) loadmoreView).getChildAt(0)
               .getMeasuredHeight();
      }
      // 改變子控件的佈局,這裏直接用(pullDownY + pullUpY)做爲偏移量,這樣就能夠不對當前狀態做區分
      refreshView.layout(0,
            (int) (pullDownY + pullUpY) - refreshView.getMeasuredHeight(),
            refreshView.getMeasuredWidth(), (int) (pullDownY + pullUpY));
      pullableView.layout(0, (int) (pullDownY + pullUpY),
            pullableView.getMeasuredWidth(), (int) (pullDownY + pullUpY)
                  + pullableView.getMeasuredHeight());
      loadmoreView.layout(0,
            (int) (pullDownY + pullUpY) + pullableView.getMeasuredHeight(),
            loadmoreView.getMeasuredWidth(),
            (int) (pullDownY + pullUpY) + pullableView.getMeasuredHeight()
                  + loadmoreView.getMeasuredHeight());
   }

   class MyTimer
   {
      private Handler handler;
      private Timer timer;
      private MyTask mTask;

      public MyTimer(Handler handler)
      {
         this.handler = handler;
         timer = new Timer();
      }

      public void schedule(long period)
      {
         if (mTask != null)
         {
            mTask.cancel();
            mTask = null;
         }
         mTask = new MyTask(handler);
         timer.schedule(mTask, 0, period);
      }

      public void cancel()
      {
         if (mTask != null)
         {
            mTask.cancel();
            mTask = null;
         }
      }

      class MyTask extends TimerTask
      {
         private Handler handler;

         public MyTask(Handler handler)
         {
            this.handler = handler;
         }

         @Override
         public void run()
         {
            handler.obtainMessage().sendToTarget();
         }

      }
   }

   /**
    * 刷新加載回調接口
    * 
    * @author chenjing
    * 
    */
   public interface OnRefreshListener
   {
      /**
       * 刷新操做
       */
      void onRefresh(PullToRefreshLayout pullToRefreshLayout);

      /**
       * 加載操做
       */
      void onLoadMore(PullToRefreshLayout pullToRefreshLayout);
   }

}

animide

progressbar函數

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
        android:drawable="@mipmap/loading"
        android:fromDegrees="0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toDegrees="360">
</rotate>

reverse_anim佈局

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="100"
    android:fillAfter="true"
    android:fromDegrees="0"
    android:pivotX="50%"
    android:pivotY="50%"
    android:repeatCount="0"
    android:toDegrees="180" >

</rotate>

rotating動畫

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1500"
    android:fillAfter="true"
    android:fromDegrees="0"
    android:pivotX="50%"
    android:pivotY="50%"
    android:repeatCount="-1"
    android:toDegrees="360" >

</rotate>

stringsthis

<string name="pull_to_refresh">下拉刷新</string>
<string name="release_to_refresh">釋放當即刷新</string>
<string name="refreshing">正在刷新...</string>
<string name="refresh_succeed">刷新成功</string>
<string name="refresh_fail">已經是最新</string>
<string name="pullup_to_load">上拉加載更多</string>
<string name="release_to_load">釋放當即加載</string>
<string name="loading">正在加載...</string>
<string name="load_succeed">加載成功</string>
<string name="load_fail">已所有加載</string>

load_morespa

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/loadmore_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/bar_orange" >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:paddingBottom="10dp"
        android:paddingTop="10dp" >

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true" >

            <ImageView
                android:id="@+id/pullup_icon"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_marginLeft="60dp"
                android:background="@mipmap/pullup_icon_big" />

            <ImageView
                android:id="@+id/loading_icon"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_marginLeft="60dp"
                android:src="@mipmap/loading"
                android:visibility="gone" />

            <TextView
                android:id="@+id/loadstate_tv"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:text="@string/pullup_to_load"
                android:textColor="@color/black"
                android:textSize="16sp" />

            <ImageView
                android:id="@+id/loadstate_iv"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_marginRight="8dp"
                android:layout_toLeftOf="@id/loadstate_tv"
                android:visibility="gone" />
        </RelativeLayout>
    </RelativeLayout>

</RelativeLayout>

refresh_head.net

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/head_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/bar_orange" >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:paddingBottom="10dp"
        android:paddingTop="10dp" >

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true" >

            <ImageView
                android:id="@+id/pull_icon"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_marginLeft="60dp"
                android:background="@mipmap/pull_icon_big" />

            <ImageView
                android:id="@+id/refreshing_icon"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_marginLeft="60dp"
                android:background="@mipmap/refreshing"
                android:visibility="gone" />

            <TextView
                android:id="@+id/state_tv"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:text="@string/pull_to_refresh"
                android:textColor="@color/white"
                android:textSize="16sp" />

            <ImageView
                android:id="@+id/state_iv"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_marginRight="8dp"
                android:layout_toLeftOf="@id/state_tv"
                android:visibility="gone" />
        </RelativeLayout>
    </RelativeLayout>

</RelativeLayout>

相關文章
相關標籤/搜索