溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Android仿京東、天貓下拉刷新效果

發(fā)布時(shí)間:2020-10-12 17:35:16 來(lái)源:腳本之家 閱讀:548 作者:shineflowers 欄目:移動(dòng)開(kāi)發(fā)

說(shuō)到下拉刷新,相信大家都不陌生,現(xiàn)在基本上每個(gè)項(xiàng)目都會(huì)用到。我們公司的項(xiàng)目一直都是使用SwipeRefreshLayout,官方的Material Design風(fēng)格,好用少Bug?,F(xiàn)在下拉刷新大概有下面幾種實(shí)現(xiàn)方式:一種是直接包在ListView或者RecyclerView的頭部,有的則是像SwipeRefreshLayout一樣,包在視圖的最外層,個(gè)人建議使用包在最外層的做法,可拓展性比較強(qiáng)。下面用包在最外層的方法實(shí)現(xiàn)京東和天貓的下拉刷新。

1.使用框架Android-Ultra-Pull-To-Refresh

https://github.com/liaohuqiu/android-Ultra-Pull-To-Refresh

大家有興趣的可以去看一下這個(gè)下拉刷新框架,可拓展性非常強(qiáng),兼容各種View的下拉刷新事件。

2.京東下拉刷新

先看看京東的下拉刷新動(dòng)畫(huà):

Android仿京東、天貓下拉刷新效果

從上圖可以看出,就是一個(gè)動(dòng)畫(huà),當(dāng)然截圖有點(diǎn)卡,首先,我們解壓手機(jī)京東的app,得到上面的圖片:

Android仿京東、天貓下拉刷新效果

先看看頭部刷新的布局怎么實(shí)現(xiàn):
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="讓購(gòu)物更便捷" 
   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="松開(kāi)刷新" 
   android:textSize="12sp" /> 
 </LinearLayout> 
</RelativeLayout> 


咱們?cè)倏纯碼ndroid-Ultra-Pull-To-Refresh這個(gè)框架:

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); 
} 

這是一個(gè)下拉刷新事件處理接口,包括準(zhǔn)備刷新,開(kāi)始刷新,刷新完成和刷新改變等事件的處理,直接上代碼:
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; 
 
 /** 
  * 狀態(tài)識(shí)別 
  */ 
 private int mState; 
 
 /** 
  * 重置 
  * 準(zhǔn)備刷新 
  * 開(kāi)始刷新 
  * 結(jié)束刷新 
  */ 
 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; 
 
 /** 
  * 動(dòng)畫(huà) 
  */ 
 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,開(kāi)啟跑步動(dòng)畫(huà) 
  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); 
  //停止動(dòng)畫(huà) 
  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設(shè)置 
    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("松開(kāi)刷新..."); 
    } 
    break; 
   case STATE_BEGIN: 
    mTvRemind.setText("更新中..."); 
    break; 
   case STATE_FINISH: 
    mTvRemind.setText("加載完成..."); 
    break; 
  } 
 } 
} 

創(chuàng)建一個(gè)成員變量mState,用于保存下拉刷新的時(shí)候,每一個(gè)狀態(tài),然后根據(jù)保存好的狀態(tài)在UIPositionChange的接口中,對(duì)UI進(jìn)行相應(yīng)的修改,保存每個(gè)狀態(tài)文本的提示,在下拉的過(guò)程中,通過(guò)UIPositionChange的回調(diào),獲取PtrIndicator中,可以獲取下拉的百分比,根據(jù)這個(gè)百分比我們可以做很多東西,例如京東的快遞小哥從遠(yuǎn)處跑過(guò)來(lái)拿商品,以及快遞小哥與商品之間的大小,都可以根據(jù)這個(gè)PtrIndicator百分比進(jìn)行設(shè)置其大小的比例,跑過(guò)來(lái)這個(gè)過(guò)程我使用的方法是利用marginRight進(jìn)行設(shè)置兩者之間的距離,當(dāng)達(dá)到下拉刷新的臨界點(diǎn)時(shí),快遞小哥跟商品之間的margin為0,達(dá)到了快遞小哥獲取商品的效果,然后當(dāng)刷新的時(shí)候,隱藏商品,使用之前所提供的三張圖片進(jìn)行效應(yīng)的切換,也就是動(dòng)畫(huà):

<?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> 

效果圖如下:

Android仿京東、天貓下拉刷新效果

3.天貓下拉刷新

天貓的更簡(jiǎn)單,毫無(wú)動(dòng)畫(huà)可言,說(shuō)白了就是個(gè)GIF,大家可以去下載個(gè)apk,解壓后能得到其gif。原理跟之前的是一樣,但這里我使用的是fresco進(jìn)行加載gif,方法有很多,大家感興趣的可以去試試。

Android仿京東、天貓下拉刷新效果

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; 
 
 
 /** 
  * 狀態(tài)識(shí)別 
  */ 
 private int mState; 
 
 /** 
  * 重置 
  * 準(zhǔn)備刷新 
  * 開(kāi)始刷新 
  * 結(jié)束刷新 
  */ 
 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) 
    //設(shè)置uri,加載本地的gif資源 
    .setUri(Uri.parse("res://" + getContext().getPackageName() + "/" + R.drawable.tm_mui_bike))//設(shè)置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("松開(kāi)立即刷新"); 
    } 
    break; 
   case STATE_BEGIN: 
    mTvRemind.setText("正在刷新..."); 
    break; 
   case STATE_FINISH: 
    mTvRemind.setText("加載完成..."); 
    break; 
  } 
 } 
} 

效果圖如下:

Android仿京東、天貓下拉刷新效果

最后附上github地址:
https://github.com/shineflower/JdTmallPullToRefresh

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI