Android仿網(wǎng)易一元奪寶客戶端下拉加載動(dòng)畫(huà)效果(一)
上上周寫(xiě)的一個(gè)demo,仿照網(wǎng)易一元奪寶的下拉刷新效果。
原效果是(第一部分)一個(gè)小太陽(yáng)拉下來(lái),然后松開(kāi)回彈上去,
(第二部分)再掉下來(lái)一個(gè)硬幣進(jìn)行中軸旋轉(zhuǎn)。
本文實(shí)現(xiàn)的效果的是第一部分的,效果演示圖如下:
Gif圖看起來(lái)比較卡頓。。。其實(shí)真機(jī)演示效果還是很流暢的。
下面分析實(shí)現(xiàn)過(guò)程:
當(dāng)時(shí)因?yàn)闀r(shí)間有限沒(méi)有寫(xiě)在下拉刷新的組件中,也沒(méi)有封裝成一個(gè)單獨(dú)的組件,只是在主布局后面寫(xiě)了一個(gè)View然后實(shí)現(xiàn)相應(yīng)的操作,進(jìn)行封裝并不難,這里就不花時(shí)間BB了,下面是布局文件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".aty.MainActivity"> <location.haidian.com.wypulltoreflush.view.NGImgView android:id="@+id/ngimg_main" android:layout_width="match_parent" android:layout_height="match_parent"/> <ImageView android:id="@+id/img_main_sun" android:layout_width="50dp" android:layout_height="50dp" android:layout_centerHorizontal="true" android:layout_marginTop="5dp" android:src="@drawable/ic_sun1"/> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="#00123456" android:orientation="vertical"> <RelativeLayout android:layout_width="match_parent" android:layout_height="55dp" android:background="#FF4081"> </RelativeLayout> <View android:layout_width="match_parent" android:layout_height="0.5dp" android:background="@android:color/darker_gray"></View> <location.haidian.com.wypulltoreflush.view.NGReFlashListView android:id="@+id/lv_main" android:layout_width="fill_parent" android:layout_height="0dp" android:layout_weight="1" android:cacheColorHint="#00000000" /> </LinearLayout> </RelativeLayout>
布局文件預(yù)覽:
因?yàn)樵O(shè)置了透明,所以這里在沒(méi)有item的情況下是能看到后面的布局的。
代碼實(shí)現(xiàn):
通過(guò)下拉刷新類NGReFlashListView進(jìn)行事件判斷,然后通過(guò)回調(diào)把相應(yīng)的事件傳遞給NGImageView中改變視圖顯示。
下面是兩個(gè)類的源代碼:
NGReFlashListView類:
package location.haidian.com.wypulltoreflush.view; import android.content.Context; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.AbsListView; import android.widget.AbsListView.OnScrollListener; import android.widget.ListView; import location.haidian.com.wypulltoreflush.R; public class NGReFlashListView extends ListView implements OnScrollListener { private View header; private int headerHeight; private int firstVisibleItem; private int scrollState; private final int NONE = 0; private final int PULL = 1; private final int RELESE = 2; private final int REFLASHING = 3; public NGReFlashListView(Context context) { super(context); initView(context); } public NGReFlashListView(Context context, AttributeSet attrs) { super(context, attrs); initView(context); } public NGReFlashListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initView(context); } /** * @param context */ private void initView(Context context) { LayoutInflater inflater = LayoutInflater.from(context); header = inflater.inflate(R.layout.layout_heard, null); measureView(header); headerHeight = header.getMeasuredHeight(); topPadding(-headerHeight); this.addHeaderView(header); this.setOnScrollListener(this); } /** * @param view */ private void measureView(View view) { ViewGroup.LayoutParams p = view.getLayoutParams(); if (p == null) { p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); } int width = ViewGroup.getChildMeasureSpec(0, 0, p.width); int height; int tempHeight = p.height; if (tempHeight > 0) { height = MeasureSpec.makeMeasureSpec(tempHeight, MeasureSpec.EXACTLY); } else { height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); } view.measure(width, height); } /** * @param topPadding */ private void topPadding(int topPadding) { header.setPadding(header.getPaddingLeft(), topPadding, header.getPaddingRight(), header.getPaddingBottom()); header.invalidate(); } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { this.firstVisibleItem = firstVisibleItem; } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { this.scrollState = scrollState; } boolean isRemark;//初始化標(biāo)識(shí) int startY; int state; @Override public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: if (firstVisibleItem == 0) { onRlvScrollListener.onScrollYChangged(0, 0); isRemark = true; startY = (int) ev.getY(); } break; case MotionEvent.ACTION_MOVE: onMove(ev); break; case MotionEvent.ACTION_UP: if (state == RELESE) { onRlvScrollListener.onScrollYChangged(0, 3); state = REFLASHING; reflashViewByState(); //iReflashListener.onReflash(); } else if (state == PULL) { state = NONE; onRlvScrollListener.onScrollYChangged(0, 0); isRemark = false; reflashViewByState(); } break; } return super.onTouchEvent(ev); } int space; //間距 int topPadding; //headview距離頂端的距離,初始-200 /** * @param ev */ private void onMove(MotionEvent ev) { if (!isRemark) { return; } int tempY = (int) ev.getY(); space = tempY - startY; if (space >= 230) { space = 230; } topPadding = space - headerHeight; onRlvScrollListener.onScrollYChangged(space, state); switch (state) { case NONE: if (space > 0) { state = PULL; reflashViewByState(); } break; case PULL: topPadding(topPadding); if (space == headerHeight + 30 && scrollState == SCROLL_STATE_TOUCH_SCROLL) { state = RELESE; reflashViewByState(); } break; case RELESE: if (space < headerHeight + 30) { state = PULL; reflashViewByState(); } else if (space <= 0) { state = NONE; isRemark = false; reflashViewByState(); } break; } } /** * 控制下拉刷新的圖像文字顯示 */ private void reflashViewByState() { switch (state) { case NONE: //緩慢滑上去 topPadding(-headerHeight); break; case PULL: break; case RELESE: break; case REFLASHING: break; } } /** * 刷新完成 */ public void reflashComplete() { state = NONE; onRlvScrollListener.onScrollYChangged(0, state); isRemark = false; reflashViewByState(); } //繪制背景的接口 public interface OnRlvScrollListener { void onScrollYChangged(int Y, int state); } private OnRlvScrollListener onRlvScrollListener; public void setOnRlvScrollListener(OnRlvScrollListener onRlvScrollListener) { this.onRlvScrollListener = onRlvScrollListener; } }
NGImgView.java
實(shí)現(xiàn)比較簡(jiǎn)單,根據(jù)傳來(lái)的回調(diào)狀態(tài)改變進(jìn)行小太陽(yáng)和兩只球球手以及手臂的繪制就可以了。
package location.haidian.com.wypulltoreflush.view; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.graphics.drawable.BitmapDrawable; import android.util.AttributeSet; import android.util.Log; import android.widget.ImageView; import location.haidian.com.wypulltoreflush.R; /** * Created by nangua on 2016/8/28. */ public class NGImgView extends ImageView implements NGReFlashListView.OnRlvScrollListener { private float scale; private final int NONE = 0; private final int PULL = 1; private final int RELESE = 2; private final int REFLASHING = 3; public int state = 0; private float WITH; //屏幕總寬 private float scrollY; private Bitmap sun0; public float time = 0; public NGImgView(Context context, AttributeSet attrs) { super(context, attrs); initView(); } private void initView() { sun0 = ((BitmapDrawable) getResources().getDrawable(R.drawable.ic_sun0)).getBitmap(); scale = this.getResources().getDisplayMetrics().density; } @Override protected void onDraw(Canvas canvas) { Paint paint = new Paint(); paint.setAntiAlias(true);//抗鋸齒 paint.setColor(Color.parseColor("#C4885A")); Log.d("xiaojingyu","State:" + state); if (state!=3) { time = 0; //重置時(shí)間 //畫(huà)兩只球球手 canvas.drawCircle(WITH / 2 - 40 * scale, 55 * scale, 5 * scale, paint); canvas.drawCircle(WITH / 2 + 40 * scale, 55 * scale, 5 * scale, paint); //畫(huà)笑臉 canvas.drawBitmap(sun0, null, new RectF(WITH / 2 - 50, 55 * scale + scrollY - (scrollY / 230) * 50, WITH / 2 + 50, 55 * scale + scrollY - (scrollY / 230) * 50 + 100), null ); //畫(huà)手臂 paint.setStrokeWidth(1); canvas.drawLine(WITH / 2 - 40 * scale, 55 * scale, WITH / 2 - 50, 55 * scale + scrollY, paint ); canvas.drawLine(WITH / 2 + 40 * scale, 55 * scale, WITH / 2 + 50, 55 * scale + scrollY, paint ); } else if (state == 3) { //1秒鐘拉上去,2秒鐘旋轉(zhuǎn) //第一秒 if (time < 30) { time += 1; //畫(huà)兩只球球手 canvas.drawCircle(WITH / 2 - 40 * scale, 55 * scale, 5 * scale, paint); canvas.drawCircle(WITH / 2 + 40 * scale, 55 * scale, 5 * scale, paint); //畫(huà)笑臉 canvas.drawBitmap(sun0, null, new RectF(WITH / 2 - 50, 55 * scale + 180 - (time / 30) * 230, WITH / 2 + 50, 55 * scale + 280 - (time / 30) * 230), null ); //畫(huà)手臂 paint.setStrokeWidth(1); canvas.drawLine(WITH / 2 - 40 * scale, 55 * scale, WITH / 2 - 50, 55 * scale + 230 - (time / 30) * 230, paint ); canvas.drawLine(WITH / 2 + 40 * scale, 55 * scale, WITH / 2 + 50, 55 * scale + 230 - (time / 30) * 230, paint ); postInvalidateDelayed(1); } else { if (!isBeginMainAnimation) { isBeginMainAnimation = true; iReflashListener.onReflash(); } } } super.onDraw(canvas); } public static boolean isBeginMainAnimation = false; @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); WITH = this.getWidth(); } @Override public void onScrollYChangged(int Y, int state) { this.state = state; switch (state) { case NONE: break; case PULL: //下拉 scrollY = Y; break; case RELESE: break; case REFLASHING: break; } } private IReflashListener iReflashListener; //回調(diào)接口 public void setInterface(IReflashListener iReflashListener) { this.iReflashListener = iReflashListener; } /** * @author Administrator */ public interface IReflashListener { void onReflash(); } }
以上所述是小編給大家介紹的Android仿網(wǎng)易一元奪寶客戶端下拉加載動(dòng)畫(huà)效果(一),希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
- android ListView結(jié)合x(chóng)utils3仿微信實(shí)現(xiàn)下拉加載更多
- Android ListView實(shí)現(xiàn)下拉加載功能
- Android實(shí)現(xiàn)仿慕課網(wǎng)下拉加載動(dòng)畫(huà)
- Android中使用RecyclerView實(shí)現(xiàn)下拉刷新和上拉加載
- Android下拉刷新上拉加載控件(適用于所有View)
- Android RecyclerView實(shí)現(xiàn)下拉刷新和上拉加載
- android開(kāi)發(fā)教程之實(shí)現(xiàn)listview下拉刷新和上拉刷新效果
- Android實(shí)現(xiàn)上拉加載更多以及下拉刷新功能(ListView)
- Android RecyclerView 上拉加載更多及下拉刷新功能的實(shí)現(xiàn)方法
- PullToRefreshListView實(shí)現(xiàn)多條目加載上拉刷新和下拉加載
相關(guān)文章
Android仿抖音主頁(yè)效果實(shí)現(xiàn)代碼
這篇文章主要介紹了Android仿抖音主頁(yè)效果實(shí)現(xiàn),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-12-12Android中AsyncTask異步任務(wù)使用詳細(xì)實(shí)例(一)
AsyncTask是Android提供的輕量級(jí)的異步類,可以直接繼承AsyncTask,在類中實(shí)現(xiàn)異步操作,并提供接口反饋當(dāng)前異步執(zhí)行的程度(可以通過(guò)接口實(shí)現(xiàn)UI進(jìn)度更新),最后反饋執(zhí)行的結(jié)果給UI主線程,通過(guò)本文給大家介紹Android中AsyncTask異步任務(wù)使用詳細(xì)實(shí)例(一),需要的朋友參考下2016-02-02android GridView多選效果的實(shí)例代碼
在使用 GridView的時(shí)候,有時(shí)需要多選上面顯示的類容,比如批量刪除上面顯示的圖片,批量上傳圖片等。這個(gè)時(shí)候我們可以使用層疊圖來(lái)實(shí)現(xiàn),效果如下:2013-06-06Android提高之BLE開(kāi)發(fā)Android手機(jī)搜索iBeacon基站
這篇文章主要介紹了BLE開(kāi)發(fā)Android手機(jī)搜索iBeacon基站,需要的朋友可以參考下2014-08-08Android 實(shí)現(xiàn)圖片生成卷角和圓角縮略圖的方法
本篇文章主要介紹了Android 實(shí)現(xiàn)圖片生成卷角和圓角縮略圖的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-11-11Android使用SoundPool實(shí)現(xiàn)播放音頻
這篇文章主要為大家詳細(xì)介紹了Android使用SoundPool實(shí)現(xiàn)播放音頻,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-05-05android:descendantFocusability方法介紹
開(kāi)發(fā)中很常見(jiàn)的一個(gè)問(wèn)題,項(xiàng)目中的listview不僅僅是簡(jiǎn)單的文字,常常需要自己定義listview,問(wèn)題就出現(xiàn)了,可能會(huì)發(fā)生點(diǎn)擊每一個(gè)item的時(shí)候沒(méi)有反應(yīng),無(wú)法獲取的焦點(diǎn)2012-11-11Android 側(cè)滑抽屜菜單的實(shí)現(xiàn)代碼
這篇文章主要介紹了Android 側(cè)滑抽屜菜單的實(shí)現(xiàn)代碼,本文通過(guò)實(shí)例圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03