最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

仿IOS效果 帶彈簧動畫的ListView

 更新時間:2016年01月08日 09:13:01   作者:于連林520wcf  
這篇文章主要介紹了仿IOS效果,帶彈簧動畫的ListView,感興趣的小伙伴們可以參考一下

最近項目打算做一個界面,類似于dayone首頁的界面效果,dayone 是一款付費應用,目前只有IOS端。作為一個資深懶惰的程序員,奉行的宗旨是絕對不重復造一個輪子。于是乎,去網上找一大堆開源項目,發(fā)現(xiàn)沒有找到合適的,然后,只能硬著頭皮自己來了。先看看效果:


效果圖

其實寫起來也比較簡單,就是控制ListView的頭部和底部的高度就可以了, 如果用RecycleView實現(xiàn)起來也是一樣,只是RecycleView添加頭和尾巴稍微麻煩一點,處理點擊事件也不是很方便,所以就基于ListView去實現(xiàn)了。實現(xiàn)的代碼, 我已經上傳到github上了。

1、使用方法

compile 'com.a520wcf.yllistview:YLListView:1.0.1

2、使用介紹:
1)、布局:
布局注意一個小細節(jié)android:layout_height 最好是match_parent, 否則ListView每次滑動的時候都有可能需要重新計算條目高度,比較耗費CPU;

 <com.a520wcf.yllistview.YLListView 
 android:divider="@android:color/transparent"
 android:id="@+id/listView" 
 android:layout_width="match_parent" 
 android:layout_height="match_parent" />

2)、代碼:

 private YLListView listView;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  listView = (YLListView) findViewById(R.id.listView);
  // 不添加也有默認的頭和底
  View topView=View.inflate(this,R.layout.top,null);
  listView.addHeaderView(topView);
  View bottomView=new View(getApplicationContext());
  listView.addFooterView(bottomView);

  // 頂部和底部也可以固定最終的高度 不固定就使用布局本身的高度
  listView.setFinalBottomHeight(100);
  listView.setFinalTopHeight(100);

  listView.setAdapter(new DemoAdapter());

  //YLListView默認有頭和底 處理點擊事件位置注意減去
  listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
   @Override
   public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    position=position-listView.getHeaderViewsCount();
   }
  });
 }


3、源碼介紹
其實這個項目里面只有一個類,大家不需要依賴,直接把這個類復制到項目中就可以了,來看看源碼:

package com.a520wcf.yllistview;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.animation.DecelerateInterpolator;
import android.widget.AbsListView;
import android.widget.ListView;
import android.widget.Scroller;

public class YLListView extends ListView implements AbsListView.OnScrollListener {
 private Scroller mScroller; // used for scroll back
 private float mLastY = -1;

 private int mScrollBack;
 private final static int SCROLLBACK_HEADER = 0;
 private final static int SCROLLBACK_FOOTER = 1;

 private final static int SCROLL_DURATION = 400; // scroll back duration
 private final static float OFFSET_RADIO = 1.8f;
 // total list items, used to detect is at the bottom of ListView.
 private int mTotalItemCount;
 private View mHeaderView; // 頂部圖片
 private View mFooterView; // 底部圖片
 private int finalTopHeight;
 private int finalBottomHeight;

 public YLListView(Context context) {
  super(context);
  initWithContext(context);
 }

 public YLListView(Context context, AttributeSet attrs) {
  super(context, attrs);
  initWithContext(context);
 }

 public YLListView(Context context, AttributeSet attrs, int defStyle) {
  super(context, attrs, defStyle);
  initWithContext(context);
 }

 private void initWithContext(Context context) {
  mScroller = new Scroller(context, new DecelerateInterpolator());
  super.setOnScrollListener(this);

  this.getViewTreeObserver().addOnGlobalLayoutListener(
    new OnGlobalLayoutListener() {
     @Override
     public void onGlobalLayout() {
      if(mHeaderView==null){
       View view=new View(getContext());
       addHeaderView(view);
      }
      if(mFooterView==null){
       View view=new View(getContext());
       addFooterView(view);
      }
      getViewTreeObserver()
        .removeGlobalOnLayoutListener(this);
     }
    });
 }

 @Override
 public boolean onTouchEvent(MotionEvent ev) {
  if (mLastY == -1) {
   mLastY = ev.getRawY();
  }
  switch (ev.getAction()) {
   case MotionEvent.ACTION_DOWN:
    mLastY = ev.getRawY();
    break;
   case MotionEvent.ACTION_MOVE:
    final float deltaY = ev.getRawY() - mLastY;
    mLastY = ev.getRawY();
    if (getFirstVisiblePosition() == 0 && (mHeaderView.getHeight() > finalTopHeight || deltaY > 0)
      && mHeaderView.getTop() >= 0) {
     // the first item is showing, header has shown or pull down.
     updateHeaderHeight(deltaY / OFFSET_RADIO);
    } else if (getLastVisiblePosition() == mTotalItemCount - 1
      && (getFootHeight() >finalBottomHeight || deltaY < 0)) {
     updateFooterHeight(-deltaY / OFFSET_RADIO);
    }
    break;
   default:
    mLastY = -1; // reset
    if (getFirstVisiblePosition() == 0 && getHeaderHeight() > finalTopHeight) {
     resetHeaderHeight();
    }
    if (getLastVisiblePosition() == mTotalItemCount - 1 ){
      if(getFootHeight() > finalBottomHeight) {
       resetFooterHeight();
      }
    }
    break;
  }
  return super.onTouchEvent(ev);
 }

 /**
  * 重置底部高度
  */
 private void resetFooterHeight() {
  int bottomHeight = getFootHeight();
  if (bottomHeight > finalBottomHeight) {
   mScrollBack = SCROLLBACK_FOOTER;
   mScroller.startScroll(0, bottomHeight, 0, -bottomHeight+finalBottomHeight,
     SCROLL_DURATION);
   invalidate();
  }
 }
 // 計算滑動 當invalidate()后 系統(tǒng)會自動調用
 @Override
 public void computeScroll() {
  if (mScroller.computeScrollOffset()) {
   if (mScrollBack == SCROLLBACK_HEADER) {
    setHeaderHeight(mScroller.getCurrY());
   } else {
    setFooterViewHeight(mScroller.getCurrY());
   }
   postInvalidate();
  }
  super.computeScroll();
 }
 // 設置頂部高度
 private void setHeaderHeight(int height) {
  LayoutParams layoutParams = (LayoutParams) mHeaderView.getLayoutParams();
  layoutParams.height = height;
  mHeaderView.setLayoutParams(layoutParams);
 }
 // 設置底部高度
 private void setFooterViewHeight(int height) {
  LayoutParams layoutParams =
    (LayoutParams) mFooterView.getLayoutParams();
  layoutParams.height =height;
  mFooterView.setLayoutParams(layoutParams);
 }
 // 獲取頂部高度
 public int getHeaderHeight() {
  AbsListView.LayoutParams layoutParams =
    (AbsListView.LayoutParams) mHeaderView.getLayoutParams();
  return layoutParams.height;
 }
 // 獲取底部高度
 public int getFootHeight() {
  AbsListView.LayoutParams layoutParams =
    (AbsListView.LayoutParams) mFooterView.getLayoutParams();
  return layoutParams.height;
 }

 private void resetHeaderHeight() {
  int height = getHeaderHeight();
  if (height == 0) // not visible.
   return;
  mScrollBack = SCROLLBACK_HEADER;
  mScroller.startScroll(0, height, 0, finalTopHeight - height,
    SCROLL_DURATION);
  invalidate();
 }

 /**
  * 設置頂部高度 如果不設置高度,默認就是布局本身的高度
  * @param height 頂部高度
  */
 public void setFinalTopHeight(int height) {
  this.finalTopHeight = height;
 }
 /**
  * 設置底部高度 如果不設置高度,默認就是布局本身的高度
  * @param height 底部高度
  */
 public void setFinalBottomHeight(int height){
  this.finalBottomHeight=height;
 }
 @Override
 public void addHeaderView(View v) {
  mHeaderView = v;
  super.addHeaderView(mHeaderView);
  mHeaderView.getViewTreeObserver().addOnGlobalLayoutListener(
    new OnGlobalLayoutListener() {
     @Override
     public void onGlobalLayout() {
      if(finalTopHeight==0) {
       finalTopHeight = mHeaderView.getMeasuredHeight();
      }
      setHeaderHeight(finalTopHeight);
      getViewTreeObserver()
        .removeGlobalOnLayoutListener(this);
     }
    });
 }

 @Override
 public void addFooterView(View v) {
  mFooterView = v;
  super.addFooterView(mFooterView);

  mFooterView.getViewTreeObserver().addOnGlobalLayoutListener(
    new OnGlobalLayoutListener() {
     @Override
     public void onGlobalLayout() {
      if(finalBottomHeight==0) {
       finalBottomHeight = mFooterView.getMeasuredHeight();
      }
      setFooterViewHeight(finalBottomHeight);
      getViewTreeObserver()
        .removeGlobalOnLayoutListener(this);
     }
    });
 }

 private OnScrollListener mScrollListener; // user's scroll listener

 @Override
 public void setOnScrollListener(OnScrollListener l) {
  mScrollListener = l;
 }

 @Override
 public void onScrollStateChanged(AbsListView view, int scrollState) {
  if (mScrollListener != null) {
   mScrollListener.onScrollStateChanged(view, scrollState);
  }
 }

 @Override
 public void onScroll(AbsListView view, int firstVisibleItem,
       int visibleItemCount, int totalItemCount) {
  // send to user's listener
  mTotalItemCount = totalItemCount;
  if (mScrollListener != null) {
   mScrollListener.onScroll(view, firstVisibleItem, visibleItemCount,
     totalItemCount);
  }
 }

 private void updateHeaderHeight(float delta) {
  setHeaderHeight((int) (getHeaderHeight()+delta));
  setSelection(0); // scroll to top each time
 }

 private void updateFooterHeight(float delta) {
  setFooterViewHeight((int) (getFootHeight()+delta));

 }
}

以上就是本文的全部內容,希望對大家的學習有所幫助。

相關文章

  • iOS UISearchController的使用方法

    iOS UISearchController的使用方法

    本文主要介紹了iOS UISearchController的使用方法,具有很好的參考價值,下面跟著小編一起來看下吧
    2017-02-02
  • iOS用AutoLayout實現(xiàn)分頁滾動功能

    iOS用AutoLayout實現(xiàn)分頁滾動功能

    這篇文章主要給大家介紹了關于iOS用AutoLayout實現(xiàn)分頁滾動功能的相關資料,文中通過示例代碼介紹的非常詳細,對各位iOS開發(fā)者們具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-06-06
  • iOS實現(xiàn)比例拼圖的方法示例

    iOS實現(xiàn)比例拼圖的方法示例

    這篇文章主要給大家介紹了關于iOS實現(xiàn)比例拼圖的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者開發(fā)iOS具有一定的參考學習價值,需要的朋友可以參考借鑒,下面隨著小編來一起學習學習吧
    2018-07-07
  • IOS本地日志記錄解決方案

    IOS本地日志記錄解決方案

    我們在項目中日志記錄這塊也算是比較重要的,有時候用戶程序出什么問題,光靠服務器的日志還不能準確的找到問題。本文詳細介紹了IOS本地日志記錄解決方案。下面跟著小編一起來看下吧
    2017-03-03
  • iOS 10撥打系統(tǒng)電話彈出框延遲出現(xiàn)問題的解決

    iOS 10撥打系統(tǒng)電話彈出框延遲出現(xiàn)問題的解決

    iOS10的到來,帶來了條幅和鎖屏界面的重新設計,美觀又好看,再加上抬腕喚醒功能,查看需要的信息確實更便捷了,還能快捷回復一些通知,十分輕松,但同樣有問題,下面這篇文章主要給大家介紹了關于iOS 10撥打系統(tǒng)電話彈出框延遲出現(xiàn)問題的解決方法,需要的朋友可以參考下。
    2017-10-10
  • 安裝win10+黑蘋果雙系統(tǒng)零基礎教程(圖文)

    安裝win10+黑蘋果雙系統(tǒng)零基礎教程(圖文)

    這篇文章主要介紹了安裝win10+黑蘋果雙系統(tǒng)零基礎教程(圖文),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2020-01-01
  • Objective-C 宏定義詳細介紹

    Objective-C 宏定義詳細介紹

    這篇文章主要介紹了Objective-C 宏定義詳細介紹的相關資料,這樣開發(fā)起來,更有效率,更好,更簡潔,需要的朋友可以參考下
    2016-10-10
  • IOS property屬性詳細介紹使用注意事項

    IOS property屬性詳細介紹使用注意事項

    這篇文章主要介紹了IOS property屬性詳細介紹使用注意事項的相關資料,需要的朋友可以參考下
    2017-02-02
  • iOS 8使用UIBlurEffect實現(xiàn)毛玻璃特效

    iOS 8使用UIBlurEffect實現(xiàn)毛玻璃特效

    這篇文章主要為大家詳細介紹了iOS 8使用UIBlurEffect類和UIVisualEffectView類實現(xiàn)毛玻璃特效,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-05-05
  • iOS 讀取URL圖片并存儲到本地的實例

    iOS 讀取URL圖片并存儲到本地的實例

    下面小編就為大家?guī)硪黄猧OS 讀取URL圖片并存儲到本地的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2017-12-12

最新評論

富阳市| 临猗县| 马公市| 米脂县| 沁阳市| 慈利县| 凤山市| 科尔| 迁西县| 连城县| 凌云县| 吐鲁番市| 奈曼旗| 逊克县| 当阳市| 永州市| 武穴市| 株洲市| 汝阳县| 册亨县| 鲁甸县| 济南市| 盐边县| 通许县| 安溪县| 武穴市| 朔州市| 库车县| 美姑县| 扬中市| 晋中市| 南召县| 子洲县| 随州市| 西藏| 新营市| 鄂州市| 华宁县| 太仓市| 九江县| 呼和浩特市|