您好,登錄后才能下訂單哦!
說到下拉刷新,相信大家都不陌生,現在基本上每個項目都會用到。我們公司的項目一直都是使用SwipeRefreshLayout,官方的Material Design風格,好用少Bug。現在下拉刷新大概有下面幾種實現方式:一種是直接包在ListView或者RecyclerView的頭部,有的則是像SwipeRefreshLayout一樣,包在視圖的最外層,個人建議使用包在最外層的做法,可拓展性比較強。下面用包在最外層的方法實現京東和天貓的下拉刷新。
1.使用框架Android-Ultra-Pull-To-Refresh
https://github.com/liaohuqiu/android-Ultra-Pull-To-Refresh
大家有興趣的可以去看一下這個下拉刷新框架,可拓展性非常強,兼容各種View的下拉刷新事件。
2.京東下拉刷新
先看看京東的下拉刷新動畫:
從上圖可以看出,就是一個動畫,當然截圖有點卡,首先,我們解壓手機京東的app,得到上面的圖片:
先看看頭部刷新的布局怎么實現:
jd_refresh_header_view.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content"> <FrameLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toLeftOf="@+id/layout_tx"> <ImageView android:id="@+id/iv_man" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/a2a" /> <ImageView android:id="@+id/iv_goods" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="right|center" android:src="@drawable/a29" /> </FrameLayout> <LinearLayout android:id="@+id/layout_tx" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:layout_marginLeft="5dp" android:gravity="center_vertical" android:orientation="vertical" android:padding="5dp"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="讓購物更便捷" android:textSize="14sp" /> <TextView android:id="@+id/tv_remain" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="5dp" android:text="松開刷新" android:textSize="12sp" /> </LinearLayout> </RelativeLayout>
咱們再看看android-Ultra-Pull-To-Refresh這個框架:
package in.srain.cube.views.ptr; import in.srain.cube.views.ptr.indicator.PtrIndicator; /** * */ public interface PtrUIHandler { /** * When the content view has reached top and refresh has been completed, view will be reset. * * @param frame */ public void onUIReset(PtrFrameLayout frame); /** * prepare for loading * * @param frame */ public void onUIRefreshPrepare(PtrFrameLayout frame); /** * perform refreshing UI */ public void onUIRefreshBegin(PtrFrameLayout frame); /** * perform UI after refresh */ public void onUIRefreshComplete(PtrFrameLayout frame); public void onUIPositionChange(PtrFrameLayout frame, boolean isUnderTouch, byte status, PtrIndicator ptrIndicator); }
這是一個下拉刷新事件處理接口,包括準備刷新,開始刷新,刷新完成和刷新改變等事件的處理,直接上代碼:
JdRefreshHeader.java
package com.jackie.pulltorefresh.jd; import android.content.Context; import android.graphics.drawable.AnimationDrawable; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; import com.jackie.pulltorefresh.R; import in.srain.cube.views.ptr.PtrFrameLayout; import in.srain.cube.views.ptr.PtrUIHandler; import in.srain.cube.views.ptr.indicator.PtrIndicator; /** * 下拉刷新HeaderView */ public class JdRefreshHeader extends FrameLayout implements PtrUIHandler { /** * 提醒文本 */ private TextView mTvRemind; /** * 快遞員logo */ private ImageView mIvMan; /** * 商品logo */ private ImageView mIvGoods; /** * 狀態識別 */ private int mState; /** * 重置 * 準備刷新 * 開始刷新 * 結束刷新 */ public static final int STATE_RESET = -1; public static final int STATE_PREPARE = 0; public static final int STATE_BEGIN = 1; public static final int STATE_FINISH = 2; public static final int MARGIN_RIGHT = 100; /** * 動畫 */ private AnimationDrawable mAnimationDrawable; public JdRefreshHeader(Context context) { this(context, null); } public JdRefreshHeader(Context context, AttributeSet attrs) { this(context, attrs, 0); } public JdRefreshHeader(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initView(); } /** * 初始化view */ private void initView() { View view = LayoutInflater.from(getContext()).inflate(R.layout.jd_refresh_header_view, this, false); mTvRemind = (TextView) view.findViewById(R.id.tv_remain); mIvMan = (ImageView) view.findViewById(R.id.iv_man); mIvGoods = (ImageView) view.findViewById(R.id.iv_goods); addView(view); } @Override public void onUIReset(PtrFrameLayout frame) { mState = STATE_RESET; } @Override public void onUIRefreshPrepare(PtrFrameLayout frame) { mState = STATE_PREPARE; } @Override public void onUIRefreshBegin(PtrFrameLayout frame) { mState = STATE_BEGIN; //隱藏商品logo,開啟跑步動畫 mIvGoods.setVisibility(View.GONE); mIvMan.setBackgroundResource(R.drawable.runningman); mAnimationDrawable = (AnimationDrawable) mIvMan.getBackground(); if (!mAnimationDrawable.isRunning()) { mAnimationDrawable.start(); } } @Override public void onUIRefreshComplete(PtrFrameLayout frame) { mState = STATE_FINISH; mIvGoods.setVisibility(View.VISIBLE); //停止動畫 if (mAnimationDrawable.isRunning()) { mAnimationDrawable.stop(); } mIvMan.setBackgroundResource(R.drawable.a2a); } @Override public void onUIPositionChange(PtrFrameLayout frame, boolean isUnderTouch, byte status, PtrIndicator ptrIndicator) { //處理提醒字體 switch (mState) { case STATE_PREPARE: //logo設置 mIvMan.setAlpha(ptrIndicator.getCurrentPercent()); mIvGoods.setAlpha(ptrIndicator.getCurrentPercent()); LayoutParams params = (LayoutParams) mIvMan.getLayoutParams(); if (ptrIndicator.getCurrentPercent() <= 1) { mIvMan.setScaleX(ptrIndicator.getCurrentPercent()); mIvMan.setScaleY(ptrIndicator.getCurrentPercent()); mIvGoods.setScaleX(ptrIndicator.getCurrentPercent()); mIvGoods.setScaleY(ptrIndicator.getCurrentPercent()); int marginRight = (int) (MARGIN_RIGHT - MARGIN_RIGHT * ptrIndicator.getCurrentPercent()); params.setMargins(0, 0, marginRight, 0); mIvMan.setLayoutParams(params); } if (ptrIndicator.getCurrentPercent() < 1.2) { mTvRemind.setText("下拉刷新..."); } else { mTvRemind.setText("松開刷新..."); } break; case STATE_BEGIN: mTvRemind.setText("更新中..."); break; case STATE_FINISH: mTvRemind.setText("加載完成..."); break; } } }
創建一個成員變量mState,用于保存下拉刷新的時候,每一個狀態,然后根據保存好的狀態在UIPositionChange的接口中,對UI進行相應的修改,保存每個狀態文本的提示,在下拉的過程中,通過UIPositionChange的回調,獲取PtrIndicator中,可以獲取下拉的百分比,根據這個百分比我們可以做很多東西,例如京東的快遞小哥從遠處跑過來拿商品,以及快遞小哥與商品之間的大小,都可以根據這個PtrIndicator百分比進行設置其大小的比例,跑過來這個過程我使用的方法是利用marginRight進行設置兩者之間的距離,當達到下拉刷新的臨界點時,快遞小哥跟商品之間的margin為0,達到了快遞小哥獲取商品的效果,然后當刷新的時候,隱藏商品,使用之前所提供的三張圖片進行效應的切換,也就是動畫:
<?xml version="1.0" encoding="utf-8"?> <animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false"> <item android:drawable="@drawable/a2b" android:duration="70" /> <item android:drawable="@drawable/a2c" android:duration="70" /> <item android:drawable="@drawable/a2d" android:duration="70" /> </animation-list>
效果圖如下:
3.天貓下拉刷新
天貓的更簡單,毫無動畫可言,說白了就是個GIF,大家可以去下載個apk,解壓后能得到其gif。原理跟之前的是一樣,但這里我使用的是fresco進行加載gif,方法有很多,大家感興趣的可以去試試。
TmallRefreshHeader.java
package com.jackie.pulltorefresh.tmall; import android.content.Context; import android.net.Uri; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.widget.FrameLayout; import android.widget.TextView; import com.facebook.drawee.backends.pipeline.Fresco; import com.facebook.drawee.interfaces.DraweeController; import com.facebook.drawee.view.SimpleDraweeView; import com.jackie.pulltorefresh.R; import in.srain.cube.views.ptr.PtrFrameLayout; import in.srain.cube.views.ptr.PtrUIHandler; import in.srain.cube.views.ptr.indicator.PtrIndicator; /** * 下拉刷新HeaderView */ public class TmallRefreshHeader extends FrameLayout implements PtrUIHandler { /** * 提醒文本 */ private TextView mTvRemind; /** * 狀態識別 */ private int mState; /** * 重置 * 準備刷新 * 開始刷新 * 結束刷新 */ public static final int STATE_RESET = -1; public static final int STATE_PREPARE = 0; public static final int STATE_BEGIN = 1; public static final int STATE_FINISH = 2; public TmallRefreshHeader(Context context) { this(context, null); } public TmallRefreshHeader(Context context, AttributeSet attrs) { this(context, attrs, 0); } public TmallRefreshHeader(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initView(); } /** * 初始化view */ private void initView() { View view = LayoutInflater.from(getContext()).inflate(R.layout.tmall_refresh_header_view, this, false); mTvRemind = (TextView) view.findViewById(R.id.tv_remind); SimpleDraweeView sdv = (SimpleDraweeView) view.findViewById(R.id.tm_logo); DraweeController draweeController = Fresco.newDraweeControllerBuilder() .setAutoPlayAnimations(true) //設置uri,加載本地的gif資源 .setUri(Uri.parse("res://" + getContext().getPackageName() + "/" + R.drawable.tm_mui_bike))//設置uri .build(); sdv.setController(draweeController); addView(view); } @Override public void onUIReset(PtrFrameLayout frame) { mState = STATE_RESET; } @Override public void onUIRefreshPrepare(PtrFrameLayout frame) { mState = STATE_PREPARE; } @Override public void onUIRefreshBegin(PtrFrameLayout frame) { mState = STATE_BEGIN; } @Override public void onUIRefreshComplete(PtrFrameLayout frame) { mState = STATE_FINISH; } @Override public void onUIPositionChange(PtrFrameLayout frame, boolean isUnderTouch, byte status, PtrIndicator ptrIndicator) { //處理提醒字體 switch (mState) { case STATE_PREPARE: if (ptrIndicator.getCurrentPercent() < 1) { mTvRemind.setText("下拉刷新"); } else { mTvRemind.setText("松開立即刷新"); } break; case STATE_BEGIN: mTvRemind.setText("正在刷新..."); break; case STATE_FINISH: mTvRemind.setText("加載完成..."); break; } } }
效果圖如下:
最后附上github地址:
https://github.com/shineflower/JdTmallPullToRefresh
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。