国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android自定義漸變式炫酷ListView下拉刷新動畫

2019-12-12 03:43:54
字體:
來源:轉載
供稿:網友

本文實例為大家分享了自定義漸變式炫酷動畫的ListView下拉刷新,供大家參考,具體內容如下

主要要點

listview刷新過程中主要有三個步驟當前:狀態為下拉刷新,當前狀態為下拉刷新,當前狀態為放開刷新,當前狀態為正在刷新;主要思路為三個步驟分別對應三個自定義的view;即ibuRefreshFirstStepView,ibuRefreshSecondStepView,ibuRefreshThirdStepView。

效果圖

ibuRefreshFirstStepView代碼,例如:

 private Bitmap initialBitmap; private float mCurrentProgress; private Bitmap scaledBitmap; public ibuRefreshFirstStepView(Context context, AttributeSet attrs,         int defStyle) {  super(context, attrs, defStyle);  init(context); } public ibuRefreshFirstStepView(Context context, AttributeSet attrs) {  super(context, attrs);  init(context); } public ibuRefreshFirstStepView(Context context) {  super(context);  init(context); } private void init(Context context) {  //這個就是那個火箭圖片  initialBitmap = Bitmap.createBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.img_huojian1)); } /**  * 重寫onMeasure方法主要是設置wrap_content時 View的大小  * @param widthMeasureSpec  * @param heightMeasureSpec  */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  //根據設置的寬度來計算高度 設置為符合第二階段娃娃圖片的寬高比例  setMeasuredDimension(measureWidth(widthMeasureSpec),measureWidth(widthMeasureSpec)*initialBitmap.getHeight()/initialBitmap.getWidth()); } /**  * 當wrap_content的時候,寬度即為第二階段娃娃圖片的寬度  * @param widMeasureSpec  * @return  */ private int measureWidth(int widMeasureSpec){  int result = 0;  int size = MeasureSpec.getSize(widMeasureSpec);  int mode = MeasureSpec.getMode(widMeasureSpec);  if (mode == MeasureSpec.EXACTLY){   result = size;  }else{   result = initialBitmap.getWidth();   if (mode == MeasureSpec.AT_MOST){    result = Math.min(result,size);   }  }  return result;  } /**  * 在onLayout里面獲得測量后View的寬高  * @param changed  * @param left  * @param top  * @param right  * @param bottom  */ @Override protected void onLayout(boolean changed, int left, int top, int right,   int bottom) {  super.onLayout(changed, left, top, right, bottom);  // 給火箭圖片進行等比例的縮放  scaledBitmap = Bitmap.createScaledBitmap(initialBitmap,89,110, false); } @Override protected void onDraw(Canvas canvas) {  super.onDraw(canvas);  //這個方法是對畫布進行縮放,從而達到橢圓形圖片的縮放,第一個參數為寬度縮放比例,第二個參數為高度縮放比例,//  canvas.scale(mCurrentProgress, mCurrentProgress, measuredWidth/2, measuredHeight/2);  //將等比例縮放后的橢圓形畫在畫布上面  canvas.drawBitmap(scaledBitmap,90,dip2px(getContext(),80*mCurrentProgress),null); } /**  * 根據手機的分辨率從 dp 的單位 轉成為 px(像素)  */ public static int dip2px(Context context, float dpValue) {  final float scale = context.getResources().getDisplayMetrics().density;  return (int) (dpValue * scale + 0.5f); } /**  * 設置縮放比例,從0到1 0為最小 1為最大  * @param currentProgress  */ public void setCurrentProgress(float currentProgress){  mCurrentProgress = currentProgress; }}

ibuRefreshSecondStepView代碼,例如:

 private Bitmap endBitmap,scaledBitmap; public ibuRefreshSecondStepView(Context context, AttributeSet attrs,         int defStyle) {  super(context, attrs, defStyle);  init(); } public ibuRefreshSecondStepView(Context context, AttributeSet attrs) {  super(context, attrs);  init(); } public ibuRefreshSecondStepView(Context context) {  super(context);  init(); } private void init() {  endBitmap = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.img_huojian2), 89, 110, false); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  setMeasuredDimension(measureWidth(widthMeasureSpec), measureWidth(widthMeasureSpec) * endBitmap.getHeight() / endBitmap.getWidth()); } @Override protected void onLayout(boolean changed, int left, int top, int right,       int bottom) {  super.onLayout(changed, left, top, right, bottom);  scaledBitmap = Bitmap.createScaledBitmap(endBitmap, 89, 110, false); } @Override protected void onDraw(Canvas canvas) {  super.onDraw(canvas);  canvas.drawBitmap(endBitmap, 90, dip2px(getContext(), 80 * 1), null); } /**  * 根據手機的分辨率從 dp 的單位 轉成為 px(像素)  */ public static int dip2px(Context context, float dpValue) {  final float scale = context.getResources().getDisplayMetrics().density;  return (int) (dpValue * scale + 0.5f); } private int measureWidth(int widthMeasureSpec){  int result = 0;  int size = MeasureSpec.getSize(widthMeasureSpec);  int mode = MeasureSpec.getMode(widthMeasureSpec);  if (mode == MeasureSpec.EXACTLY) {   result = size;  }else {   result = endBitmap.getWidth();   if (mode == MeasureSpec.AT_MOST) {    result = Math.min(result, size);   }  }  return result; }}

ibuRefreshThirdStepView代碼,例如:

 private Bitmap endBitmap,scaledBitmap; public ibuRefreshThirdStepView(Context context, AttributeSet attrs,         int defStyle) {  super(context, attrs, defStyle);  init(); } public ibuRefreshThirdStepView(Context context, AttributeSet attrs) {  super(context, attrs);  init(); } public ibuRefreshThirdStepView(Context context) {  super(context);  init(); } private void init() {  endBitmap = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.img_huojian3), 89, 170, false); } @Override protected void onDraw(Canvas canvas) {  super.onDraw(canvas);  canvas.drawBitmap(endBitmap, 90, dip2px(getContext(), 40 * 1), null); } /**  * 根據手機的分辨率從 dp 的單位 轉成為 px(像素)  */ public static int dip2px(Context context, float dpValue) {  final float scale = context.getResources().getDisplayMetrics().density;  return (int) (dpValue * scale + 0.5f); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  setMeasuredDimension(measureWidth(widthMeasureSpec), measureWidth(widthMeasureSpec)*endBitmap.getHeight()/endBitmap.getWidth()); } private int measureWidth(int widthMeasureSpec){  int result = 0;  int size = MeasureSpec.getSize(widthMeasureSpec);  int mode = MeasureSpec.getMode(widthMeasureSpec);  if (mode == MeasureSpec.EXACTLY) {   result = size;  }else {   result = endBitmap.getWidth();   if (mode == MeasureSpec.AT_MOST) {    result = Math.min(result, size);   }  }  return result; }

代碼塊

IbuListView 代碼,例如:

 private static final int DONE = 0; private static final int PULL_TO_REFRESH = 1; private static final int RELEASE_TO_REFRESH = 2; private static final int REFRESHING = 3; private static final int RATIO = 3; private RelativeLayout headerView; private int headerViewHeight; private float startY; private float offsetY; private TextView tv_pull_to_refresh; private OnMeiTuanRefreshListener mOnRefreshListener; private int state; private int mFirstVisibleItem; private boolean isRecord; private boolean isEnd; private boolean isRefreable; private FrameLayout mAnimContainer;// private Animation animation; private SimpleDateFormat format; private ibuRefreshFirstStepView mFirstView; private ibuRefreshSecondStepView mSecondView; private AnimationDrawable secondAnim; private ibuRefreshThirdStepView mThirdView; private AnimationDrawable thirdAnim; public IbuListView(Context context) {  super(context);  init(context); } public IbuListView(Context context, AttributeSet attrs) {  super(context, attrs);  init(context); } public IbuListView(Context context, AttributeSet attrs, int defStyleAttr) {  super(context, attrs, defStyleAttr);  init(context); } public interface OnMeiTuanRefreshListener{  void onRefresh(); } /**  * 回調接口,想實現下拉刷新的listview實現此接口  * @param onRefreshListener  */ public void setOnMeiTuanRefreshListener(OnMeiTuanRefreshListener onRefreshListener){  mOnRefreshListener = onRefreshListener;  isRefreable = true; } /**  * 刷新完畢,從主線程發送過來,并且改變headerView的狀態和文字動畫信息  */ public void setOnRefreshComplete(){  //一定要將isEnd設置為true,以便于下次的下拉刷新  isEnd = true;  state = DONE;  changeHeaderByState(state); } private ImageView imageViewBack,imageView_B; private void init(Context context) {  setOverScrollMode(View.OVER_SCROLL_NEVER);  setOnScrollListener(this);  headerView = (RelativeLayout) LayoutInflater.from(context).inflate(R.layout.ibu_item, null, false);  imageViewBack= (ImageView) headerView.findViewById(R.id.icon_back);  imageView_B= (ImageView) headerView.findViewById(R.id.image_b);  mFirstView = (ibuRefreshFirstStepView) headerView.findViewById(R.id.first_view);  tv_pull_to_refresh = (TextView) headerView.findViewById(R.id.tv_pull_to_refresh);  mSecondView = (ibuRefreshSecondStepView) headerView.findViewById(R.id.second_view);  mThirdView = (ibuRefreshThirdStepView) headerView.findViewById(R.id.third_view);  measureView(headerView);  addHeaderView(headerView);  headerViewHeight = headerView.getMeasuredHeight();  headerView.setPadding(0, -headerViewHeight, 0, 0);  Log.i("zhangqi","headerViewHeight="+headerViewHeight);  state = DONE;  isEnd = true;  isRefreable = false; } @Override public void onScrollStateChanged(AbsListView absListView, int i) { } @Override public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) {  mFirstVisibleItem = firstVisibleItem; } @Override public boolean onTouchEvent(MotionEvent ev) {  if (isEnd) {//如果現在時結束的狀態,即刷新完畢了,可以再次刷新了,在onRefreshComplete中設置   if (isRefreable) {//如果現在是可刷新狀態 在setOnMeiTuanListener中設置為true    switch (ev.getAction()){     //用戶按下    case MotionEvent.ACTION_DOWN:     //如果當前是在listview頂部并且沒有記錄y坐標     if (mFirstVisibleItem == 0 && !isRecord) {      //將isRecord置為true,說明現在已記錄y坐標      isRecord = true;      //將當前y坐標賦值給startY起始y坐標      startY = ev.getY();     }     imageView_B.setVisibility(VISIBLE);     break;    //用戶滑動    case MotionEvent.ACTION_MOVE:     //再次得到y坐標,用來和startY相減來計算offsetY位移值     float tempY = ev.getY();     //再起判斷一下是否為listview頂部并且沒有記錄y坐標     if (mFirstVisibleItem == 0 && !isRecord) {      isRecord = true;      startY = tempY;     }     //如果當前狀態不是正在刷新的狀態,并且已經記錄了y坐標     if (state!=REFRESHING && isRecord ) {      //計算y的偏移量      offsetY = tempY - startY;      //計算當前滑動的高度      float currentHeight = (-headerViewHeight+offsetY/3);      //用當前滑動的高度和頭部headerView的總高度進行比 計算出當前滑動的百分比 0到1      float currentProgress = 1+currentHeight/headerViewHeight;      //如果當前百分比大于1了,將其設置為1,目的是讓第一個狀態的橢圓不再繼續變大      if (currentProgress>=1) {       currentProgress = 1;      }      //如果當前的狀態是放開刷新,并且已經記錄y坐標      if (state == RELEASE_TO_REFRESH && isRecord) {       setSelection(0);       //如果當前滑動的距離小于headerView的總高度       if (-headerViewHeight+offsetY/RATIO<0) {        //將狀態置為下拉刷新狀態        state = PULL_TO_REFRESH;        //根據狀態改變headerView,主要是更新動畫和文字等信息        changeHeaderByState(state);        //如果當前y的位移值小于0,即為headerView隱藏了       }else if (offsetY<=0) {        //將狀態變為done        state = DONE;        //根據狀態改變headerView,主要是更新動畫和文字等信息        changeHeaderByState(state);       }      }      //如果當前狀態為下拉刷新并且已經記錄y坐標      if (state == PULL_TO_REFRESH && isRecord) {       setSelection(0);       //如果下拉距離大于等于headerView的總高度       if (-headerViewHeight+offsetY/RATIO>=0) {        //將狀態變為放開刷新        state = RELEASE_TO_REFRESH;        //根據狀態改變headerView,主要是更新動畫和文字等信息        changeHeaderByState(state);        //如果當前y的位移值小于0,即為headerView隱藏了       }else if (offsetY<=0) {        //將狀態變為done        state = DONE;        //根據狀態改變headerView,主要是更新動畫和文字等信息        changeHeaderByState(state);       }      }      //如果當前狀態為done并且已經記錄y坐標      if (state == DONE && isRecord) {       //如果位移值大于0       if (offsetY>=0) {        //將狀態改為下拉刷新狀態        state = PULL_TO_REFRESH;       }      }      //如果為下拉刷新狀態      if (state == PULL_TO_REFRESH) {       //則改變headerView的padding來實現下拉的效果       headerView.setPadding(0,(int)(-headerViewHeight+offsetY/RATIO) ,0,0);       //給第一個狀態的View設置當前進度值       mFirstView.setCurrentProgress(currentProgress);       //重畫       mFirstView.postInvalidate();      }      //如果為放開刷新狀態      if (state == RELEASE_TO_REFRESH) {       //改變headerView的padding值       headerView.setPadding(0,(int)(-headerViewHeight+offsetY/RATIO) ,0, 0);       //給第一個狀態的View設置當前進度值       mFirstView.setCurrentProgress(currentProgress);       //重畫       mFirstView.postInvalidate();      }     }     break;    //當用戶手指抬起時    case MotionEvent.ACTION_UP:     //如果當前狀態為下拉刷新狀態     if (state == PULL_TO_REFRESH) {      //平滑的隱藏headerView      this.smoothScrollBy((int)(-headerViewHeight+offsetY/RATIO)+headerViewHeight, 500);      //根據狀態改變headerView      changeHeaderByState(state);     }     //如果當前狀態為放開刷新     if (state == RELEASE_TO_REFRESH) {      //平滑的滑到正好顯示headerView      this.smoothScrollBy((int)(-headerViewHeight+offsetY/RATIO), 500);      //將當前狀態設置為正在刷新      state = REFRESHING;      //回調接口的onRefresh方法      mOnRefreshListener.onRefresh();      //根據狀態改變headerView      changeHeaderByState(state);     }     //這一套手勢執行完,一定別忘了將記錄y坐標的isRecord改為false,以便于下一次手勢的執行     isRecord = false;     break;    }   }  }  return super.onTouchEvent(ev); } private Animation animation; /**  * 根據狀態改變headerView的動畫和文字顯示  * @param state  */ private void changeHeaderByState(int state){  switch (state) {  case DONE://如果的隱藏的狀態   //設置headerView的padding為隱藏   headerView.setPadding(0, -headerViewHeight, 0, 0);   //第一狀態的view顯示出來   mFirstView.setVisibility(View.VISIBLE);   imageView_B.setVisibility(VISIBLE);   tv_pull_to_refresh.setText("下拉刷新");   //第二狀態的view隱藏起來   mSecondView.setVisibility(View.GONE);   //停止第二狀態的動畫   secondAnim.stop();   //第三狀態的view隱藏起來   mThirdView.setVisibility(View.GONE);   //停止第三狀態的動畫   thirdAnim.stop();   break;  case RELEASE_TO_REFRESH://當前狀態為放開刷新   //文字顯示為放開刷新   tv_pull_to_refresh.setText("放開刷新");   //第一狀態view隱藏起來   mFirstView.setVisibility(View.GONE);   //第二狀態view顯示出來   mSecondView.setVisibility(View.VISIBLE);   //播放第二狀態的動畫  secondAnim.start();   //第三狀態view隱藏起來   mThirdView.setVisibility(View.GONE);   //停止第三狀態的動畫  thirdAnim.stop();   break;  case PULL_TO_REFRESH://當前狀態為下拉刷新   imageView_B.setVisibility(VISIBLE);   //設置文字為下拉刷新   tv_pull_to_refresh.setText("下拉刷新");   //第一狀態view顯示出來   mFirstView.setVisibility(View.VISIBLE);   //第二狀態view隱藏起來   mSecondView.setVisibility(View.GONE);   //第二狀態動畫停止   secondAnim.stop();   //第三狀態view隱藏起來   mThirdView.setVisibility(View.GONE);   //第三狀態動畫停止   thirdAnim.stop();   break;  case REFRESHING://當前狀態為正在刷新   //文字設置為正在刷新   tv_pull_to_refresh.setText("正在刷新");   //第一狀態view隱藏起來   mFirstView.setVisibility(View.GONE);   //第三狀態view顯示出來   mThirdView.setVisibility(View.VISIBLE);   //第二狀態view隱藏起來   mSecondView.setVisibility(View.GONE);   //停止第二狀態動畫   secondAnim.stop();   //啟動第三狀態view   thirdAnim.start();   imageView_B.setVisibility(GONE);    animation = new TranslateAnimation(0, 0, 0, 600);   animation.setDuration(3000);   imageViewBack.setAnimation(animation);   break;  default:   break;  } } private void measureView(View child) {  ViewGroup.LayoutParams p = child.getLayoutParams();  if (p == null) {   p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,     ViewGroup.LayoutParams.WRAP_CONTENT);  }  int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, p.width);  int lpHeight = p.height;  int childHeightSpec;  if (lpHeight > 0) {   childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight,     MeasureSpec.EXACTLY);  } else {   childHeightSpec = MeasureSpec.makeMeasureSpec(0,     MeasureSpec.UNSPECIFIED);  }  child.measure(childWidthSpec, childHeightSpec); }}

github代碼:

項目代碼下載(https://github.com/molu0007/IBU_ListView)

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 克山县| 浦北县| 屏边| 双柏县| 望江县| 池州市| 叶城县| 什邡市| 鹤峰县| 南充市| 偏关县| 全南县| 天门市| 大方县| 台湾省| 东丽区| 张家川| 土默特左旗| 湟中县| 佛学| 晋宁县| 清新县| 鹤壁市| 绥芬河市| 九台市| 肥乡县| 靖安县| 通州区| 巍山| 大兴区| 平湖市| 金沙县| 绥江县| 玉树县| 新余市| 文成县| 舞钢市| 兴宁市| 色达县| 方山县| 社旗县|