文章出處

APP實用開發之定制自己的下拉刷新頭:

下拉刷新,幾乎是每個 Android 應用都會需要的功能。 android-Ultra-Pull-To-Refresh (以下簡稱 UltraPTR )便是一個強大的 Andriod 下拉刷新框架。
主要特點:
(1).繼承于 ViewGroup, Content 可以包含任何 View。
(2).簡潔完善的 Header 抽象,方便進行拓展,構建符合需求的頭部。

GitHub
2. 總體設計
UltraPTR 總體設計比較簡單清晰。
首先抽象出了兩個接口,功能接口和 UI 接口。
PtrHandler 代表下拉刷新的功能接口,包含刷新功能回調方法以及判斷是否可以下拉的方法。用戶實現此接口來進行數據刷新工作。
PtrUIHandler 代表下拉刷新的 UI 接口,包含準備下拉,下拉中,下拉完成,重置以及下拉過程中的位置變化等回調方法。通常情況下, Header 需要實現此接口,來處理下拉刷新過程中頭部 UI 的變化。
整個項目圍繞核心類 PtrFrameLayout。 PtrFrameLayout 代表了一個下拉刷新的自定義控件。
PtrFrameLayout 繼承自 ViewGroup,有且只能有兩個子 View,頭部 Header 和內容 Content。通常情況下 Header 會實現 PtrUIHandler 接口, Content 可以為任意的 View。
和所有的自定義控件一樣, PtrFrameLayout 通過重寫 onFinishInflate, onMeasure, onLayout 來確定控件大小和位置。通過重寫 dispatchTouchEvent 來確定控件的下拉行為。

依賴

compile 'in.srain.cube:ultra-ptr:1.0.11'

定制
您可以添加PtrUIHandler到PtrFrameLayout以實現任何您想要的UI效果。

public  interface  PtrUIHandler {    / * *      *當內容視圖已達到頂部并且刷新已完成時,將重置視圖。     *      * @param frame * / public void onUIReset( PtrFrameLayout frame);         / * *      *準備加載     *      * @param frame * / public void onUIRefreshPrepare( PtrFrameLayout frame);         / * *      *執行刷新UI * / public void onUIRefreshBegin( PtrFrameLayout frame);         / * *      *刷新后執行UI * / public void onUIRefreshComplete( PtrFrameLayout frame);         public  void  onUIPositionChange(PtrFrameLayout  frame,boolean  isUnderTouch,byte  status,int  oldPosition,int  currentPosition,float  oldPercent,float  currentPercent);}}

栗子講解

這里寫圖片描述
PtrClassicDefaultHeader 實現了 PtrUIHandler 接口。
經典樣式的 Header 實現,可以作為我們實現自定義 Header 的參考,以下是具體實現。

@Overridepublic void onUIReset(PtrFrameLayout frame) {    resetView();    mShouldShowLastUpdate = true;    tryUpdateLastUpdateTime();}private void resetView() {    hideRotateView();    mProgressBar.setVisibility(INVISIBLE);}private void hideRotateView() {    mRotateView.clearAnimation();    mRotateView.setVisibility(INVISIBLE);}

重置 View,隱藏忙碌進度條,隱藏箭頭 View,更新最后刷新時間。

@Overridepublic void onUIRefreshPrepare(PtrFrameLayout frame) {    mShouldShowLastUpdate = true;    tryUpdateLastUpdateTime();    mLastUpdateTimeUpdater.start();    mProgressBar.setVisibility(INVISIBLE);    mRotateView.setVisibility(VISIBLE);    mTitleTextView.setVisibility(VISIBLE);    if (frame.isPullToRefresh()) {        mTitleTextView.setText(getResources().getString(R.string.cube_ptr_pull_down_to_refresh));    } else {        mTitleTextView.setText(getResources().getString(R.string.cube_ptr_pull_down));    }}

準備刷新,隱藏忙碌進度條,顯示箭頭 View,顯示文字,如果是下拉刷新,顯示“下拉刷新”,如果是釋放刷新,顯示“下拉”。

@Overridepublic void onUIRefreshBegin(PtrFrameLayout frame) {    mShouldShowLastUpdate = false;    hideRotateView();    mProgressBar.setVisibility(VISIBLE);    mTitleTextView.setVisibility(VISIBLE);    mTitleTextView.setText(R.string.cube_ptr_refreshing);    tryUpdateLastUpdateTime();    mLastUpdateTimeUpdater.stop();}

開始刷新,隱藏箭頭 View,顯示忙碌進度條,顯示文字,顯示“加載中…”,更新最后刷新時間。

@Overridepublic void onUIRefreshComplete(PtrFrameLayout frame) {    hideRotateView();    mProgressBar.setVisibility(INVISIBLE);    mTitleTextView.setVisibility(VISIBLE);    mTitleTextView.setText(getResources().getString(R.string.cube_ptr_refresh_complete));    // update last update time    SharedPreferences sharedPreferences = getContext().getSharedPreferences(KEY_SharedPreferences, 0);    if (!TextUtils.isEmpty(mLastUpdateTimeKey)) {        mLastUpdateTime = new Date().getTime();        sharedPreferences.edit().putLong(mLastUpdateTimeKey, mLastUpdateTime).commit();    }}

刷新結束,隱藏箭頭 View,隱藏忙碌進度條,顯示文字,顯示“更新完成”,寫入最后刷新時間。

@Overridepublic void onUIPositionChange(PtrFrameLayout frame, boolean isUnderTouch, byte status, int lastPos, int currentPos, float oldPercent, float currentPercent) {    final int mOffsetToRefresh = frame.getOffsetToRefresh();    if (currentPos < mOffsetToRefresh && lastPos >= mOffsetToRefresh) {        if (isUnderTouch && status == PtrFrameLayout.PTR_STATUS_PREPARE) {            crossRotateLineFromBottomUnderTouch(frame);            if (mRotateView != null) {                mRotateView.clearAnimation();                mRotateView.startAnimation(mReverseFlipAnimation);            }        }    } else if (currentPos > mOffsetToRefresh && lastPos <= mOffsetToRefresh) {        if (isUnderTouch && status == PtrFrameLayout.PTR_STATUS_PREPARE) {            crossRotateLineFromTopUnderTouch(frame);            if (mRotateView != null) {                mRotateView.clearAnimation();                mRotateView.startAnimation(mFlipAnimation);            }        }    }}

下拉過程中位置變化回調。
在拖動情況下,當下拉距離從 小于刷新高度到大于刷新高度 時,箭頭 View 從向下,變成向上,同時改變文字顯示。
當下拉距離從 大于刷新高度到小于刷新高度 時,箭頭 View 從向上,變為向下,同時改變文字顯示。

回調

ptrFrame.setPtrHandler(new PtrHandler() {    @Override    public void onRefreshBegin(PtrFrameLayout frame) {        frame.postDelayed(new Runnable() {            @Override            public void run() {                ptrFrame.refreshComplete();            }        }, 1800);    }    @Override    public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) {        return PtrDefaultHandler.checkContentCanBePulledDown(frame, content, header);    }});

案例2

這里寫圖片描述
首先我們要自己定義需要的頭部布沮喎?/kf/yidong/wp/" target="_blank" class="keylink">WPC9wPg0KPHByZSBjbGFzcz0="brush:java;">

public class WindmillHeader extends FrameLayout implements PtrUIHandler {    private LayoutInflater inflater;    // 下拉刷新視圖(頭部視圖)    private ViewGroup headView;    // 下拉刷新文字    private TextView tvHeadTitle;    // 下拉圖標    private ImageView ivWindmill;    // 下拉刷新時間    private TextView tvHeadTime;    /** 保存上一次的刷新時間. */    private String lastRefreshTime = null; //動畫    private WindmillDrawable drawable;    public WindmillHeader(Context context) {        this(context, null);    }    public WindmillHeader(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public WindmillHeader(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init(context);    }    /**     * 初始化     *     * @param context     */    private void init(Context context) {        inflater = LayoutInflater.from(context);        /**         * 頭部         */        headView = (ViewGroup) inflater.inflate(R.layout.windmill_header, this, true);        ivWindmill = (ImageView) headView.findViewById(R.id.iv_windmill);        tvHeadTitle = (TextView) headView.findViewById(R.id.tv_head_title);        tvHeadTime= (TextView) findViewById(R.id.tv_head_time);        drawable = new WindmillDrawable(context, ivWindmill);        ivWindmill.setImageDrawable(drawable);    }    @Override    public void onUIReset(PtrFrameLayout ptrFrameLayout) {        tvHeadTitle.setText("下拉刷新");        drawable.stop();    }    @Override    public void onUIRefreshPrepare(PtrFrameLayout ptrFrameLayout) {        tvHeadTitle.setText("下拉刷新");        if(lastRefreshTime==null){            lastRefreshTime = TimeUtils.getCurrentTimeInString();            tvHeadTime.setText("當前刷新時間:" + lastRefreshTime);        }else{            tvHeadTime.setText("上次刷新時間:" + lastRefreshTime);        }    }    @Override    public void onUIRefreshBegin(PtrFrameLayout ptrFrameLayout) {        tvHeadTitle.setText("正在刷新");        tvHeadTime.setText("本次刷新時間:" + lastRefreshTime);        drawable.start();    }    @Override    public void onUIRefreshComplete(PtrFrameLayout ptrFrameLayout) {        ivWindmill.clearAnimation();        tvHeadTitle.setText("刷新完成");        tvHeadTime.setText("本次刷新時間:" + lastRefreshTime);    }    @Override    public void onUIPositionChange(PtrFrameLayout frame, boolean isUnderTouch, byte status, int lastPos, int currentPos, float oldPercent, float currentPercent) {        if (isUnderTouch && status == PtrFrameLayout.PTR_STATUS_PREPARE) {            drawable.postRotation(currentPos - lastPos);            invalidate();        }        final int mOffsetToRefresh = frame.getOffsetToRefresh();        if (currentPos < mOffsetToRefresh && lastPos >= mOffsetToRefresh) {            if (isUnderTouch && status == PtrFrameLayout.PTR_STATUS_PREPARE) {                tvHeadTitle.setText("下拉刷新");                if(lastRefreshTime==null){                    lastRefreshTime = TimeUtils.getCurrentTimeInString();                    tvHeadTime.setText("當前刷新時間:" + lastRefreshTime);                }else{                    tvHeadTime.setText("上次刷新時間:" + lastRefreshTime);                }            }        } else if (currentPos > mOffsetToRefresh && lastPos <= mOffsetToRefresh) {            if (isUnderTouch && status == PtrFrameLayout.PTR_STATUS_PREPARE) {                tvHeadTitle.setText("松開刷新");                tvHeadTime.setText("上次刷新時間:" + lastRefreshTime);                lastRefreshTime = TimeUtils.getCurrentTimeInString();            }        }    }}
private WindmillHeader header;private void initView() { ptr= (PtrFrameLayout) findViewById(R.id.ptr_main); //創建自定義頭部UI header = new WindmillHeader(this); /* 設置刷新頭部view */ ptr.setHeaderView(header); //設置回調 ptr.addPtrUIHandler(header); ptr.disableWhenHorizontalMove(true); ptr.setPtrHandler(new PtrDefaultHandler() { @Override public void onRefreshBegin(final PtrFrameLayout frame) { new Handler().postDelayed(new Runnable() { @Override public void run() { // ptr.refreshComplete(); getdata(); } }, 3000); } @Override public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) { return PtrDefaultHandler.checkContentCanBePulledDown(frame, content, header); } });  /* 延時100秒,自動刷新 */ ptr.postDelayed(new Runnable() { @Override public void run() { ptr.autoRefresh(false); } }, 100);}

案例3

public class WindmillHeader extends FrameLayout implements PtrUIHandler {    private LayoutInflater inflater;    // 下拉刷新視圖(頭部視圖)    private ViewGroup headView;    // 下拉刷新文字    private TextView tvHeadTitle;    // 下拉圖標    private ImageView ivWindmill;    private WindmillDrawable drawable;    public WindmillHeader(Context context) {        this(context, null);    }    public WindmillHeader(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public WindmillHeader(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init(context);    }    /**     * 初始化     *     * @param context     */    private void init(Context context) {        inflater = LayoutInflater.from(context);        /**         * 頭部         */        headView = (ViewGroup) inflater.inflate(R.layout.windmill_header, this, true);        ivWindmill = (ImageView) headView.findViewById(R.id.iv_windmill);        tvHeadTitle = (TextView) headView.findViewById(R.id.tv_head_title);        drawable = new WindmillDrawable(context, ivWindmill);        ivWindmill.setImageDrawable(drawable);    }    @Override    public void onUIReset(PtrFrameLayout ptrFrameLayout) {        tvHeadTitle.setText("下拉刷新");        drawable.stop();    }    @Override    public void onUIRefreshPrepare(PtrFrameLayout ptrFrameLayout) {        tvHeadTitle.setText("下拉刷新");    }    @Override    public void onUIRefreshBegin(PtrFrameLayout ptrFrameLayout) {        tvHeadTitle.setText("正在刷新");        drawable.start();    }    @Override    public void onUIRefreshComplete(PtrFrameLayout ptrFrameLayout) {        ivWindmill.clearAnimation();        tvHeadTitle.setText("刷新完成");    }    @Override    public void onUIPositionChange(PtrFrameLayout frame, boolean isUnderTouch, byte status, int lastPos, int currentPos, float oldPercent, float currentPercent) {        if (isUnderTouch && status == PtrFrameLayout.PTR_STATUS_PREPARE) {            drawable.postRotation(currentPos - lastPos);            invalidate();        }        final int mOffsetToRefresh = frame.getOffsetToRefresh();        if (currentPos < mOffsetToRefresh && lastPos >= mOffsetToRefresh) {            if (isUnderTouch && status == PtrFrameLayout.PTR_STATUS_PREPARE) {                tvHeadTitle.setText("下拉刷新");            }        } else if (currentPos > mOffsetToRefresh && lastPos <= mOffsetToRefresh) {            if (isUnderTouch && status == PtrFrameLayout.PTR_STATUS_PREPARE) {                tvHeadTitle.setText("松開刷新");            }        }    }}
public class WindmillDrawable extends Drawable implements Animatable {    private static final String TAG = WindmillDrawable.class.getSimpleName();    private Resources resources;    private Bitmap windmill;    private Matrix matrix;    private View parent;    private Animation animation;    private boolean isFirstDraw = true;    private boolean isAnimating;    public WindmillDrawable(Context context, View parent) {        resources = context.getResources();        windmill = BitmapFactory.decodeResource(resources, R.drawable.windmill);        matrix = new Matrix();        this.parent = parent;        animation = new RotateAnimation(360, 0, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);        animation.setInterpolator(new LinearInterpolator());        animation.setDuration(800);        animation.setRepeatMode(Animation.RESTART);        animation.setRepeatCount(Animation.INFINITE);        animation.setFillAfter(true);    }    @Override    public void draw(Canvas canvas) {        if (isFirstDraw) {            isFirstDraw = false;            matrix.setTranslate((getBounds().width() - windmill.getWidth()) / 2, (getBounds().height() - windmill.getHeight()) / 2);        }        Paint p = new Paint();        canvas.drawBitmap(windmill, matrix, p);    }    @Override    public void setAlpha(int alpha) {    }    @Override    public void setColorFilter(ColorFilter cf) {    }    @Override    public int getOpacity() {        return 0;    }    public void postRotation(int degree) {        matrix.postRotate(degree, getBounds().exactCenterX(), getBounds().exactCenterY());        invalidateSelf();    }    @Override    public void start() {        parent.startAnimation(animation);        isAnimating = true;    }    @Override    public void stop() {        parent.clearAnimation();        isAnimating = false;    }    @Override    public boolean isRunning() {        return isAnimating;    }
 */public class ContentGridViewFragment extends Fragment {    private GridView gvMain;    private BaseAdapter adapter;    private PtrClassicFrameLayout ptr;    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container,                             Bundle savedInstanceState) {        View v = inflater.inflate(R.layout.fragment_content_grid_view, container, false);        initView(v);        return v;    }    private void initView(View v) {        gvMain = (GridView) v.findViewById(R.id.gv_main);        ptr = (PtrClassicFrameLayout) v.findViewById(R.id.ptr_main);        ptr.setPtrHandler(new PtrDefaultHandler() {            @Override            public void onRefreshBegin(PtrFrameLayout ptrFrameLayout) {                getData();                ptr.refreshComplete();            }        });        new Handler().postDelayed(new Runnable() {            @Override            public void run() {                ptr.autoRefresh();            }        }, 100);    }    private void getData() {        adapter = new GradViewAdapter(getActivity(), Constants.SMALL_IMAGE_URLS);        gvMain.setAdapter(adapter);    }}Contact GitHub API Training Shop Blog About

看文倉www.kanwencang.com網友整理上傳,為您提供最全的知識大全,期待您的分享,轉載請注明出處。
歡迎轉載:http://www.kanwencang.com/bangong/20170301/108835.html

文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()