亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > iOS > 正文

仿IOS效果 帶彈簧動畫的ListView

2020-07-26 03:30:15
字體:
來源:轉載
供稿:網友

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


效果圖

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

1、使用方法

compile 'com.a520wcf.yllistview:YLListView:1.0.1

2、使用介紹:
1)、布局:
布局注意一個小細節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()后 系統會自動調用 @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)); }}

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

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美壮男野外gaytube| 日韩在线观看免费av| 中文字幕欧美日韩va免费视频| 欧美激情精品久久久久久变态| 伊人青青综合网站| 92裸体在线视频网站| 91精品久久久久| 欧美成年人在线观看| 国产精品99久久久久久人| 国产综合视频在线观看| 日韩大陆欧美高清视频区| 国产亚洲视频在线观看| 亚洲国产成人精品女人久久久| 亚洲精品国精品久久99热一| 欧美高清视频在线播放| 中文字幕欧美视频在线| 欧美综合在线观看| 欧亚精品在线观看| 91日韩在线播放| 亚洲国产精品成人一区二区| 欧美黄色www| 久久国产精品久久国产精品| 亚洲自拍小视频| 久操成人在线视频| 国模精品系列视频| 色偷偷亚洲男人天堂| 欧美日韩国产限制| 中文字幕欧美专区| 国产主播在线一区| 亚洲国产精品一区二区久| 亚洲天堂第一页| 中文字幕精品www乱入免费视频| 国产精品永久免费在线| 日韩亚洲成人av在线| 亚洲国产精品高清久久久| 欧美夫妻性生活xx| 欧美日韩一区二区在线| 26uuu另类亚洲欧美日本一| 国产欧美va欧美va香蕉在| 国产精品久久久久久av福利软件| 欧美激情按摩在线| 国产精品中文字幕久久久| 亚洲欧美日韩网| 日韩精品视频免费专区在线播放| 久久久久久久久久亚洲| 亚洲精品720p| 亚洲成色www8888| 一区二区三区高清国产| 国产精品视频一区国模私拍| 国产亚洲成精品久久| 亚洲91av视频| 国产日韩欧美中文在线播放| 亚洲最大av网站| 91在线中文字幕| 成人欧美一区二区三区在线湿哒哒| 91精品国产91久久久久久吃药| 国产香蕉精品视频一区二区三区| 精品五月天久久| 亚洲欧美日韩天堂| 亚洲欧美日韩直播| 欧美黑人极品猛少妇色xxxxx| 欧美视频裸体精品| 国内精品久久久久久影视8| 日韩精品高清在线观看| 亚洲免费视频在线观看| 日韩电影在线观看永久视频免费网站| 成人免费福利在线| 成年无码av片在线| 欧美日本亚洲视频| 国产精品一区二区久久精品| 久久久99免费视频| 欧美成人中文字幕在线| 亚洲欧美色婷婷| 亚洲精品乱码久久久久久按摩观| 亚洲a成v人在线观看| 久久全球大尺度高清视频| 欧美日韩国产成人在线观看| 日韩av片永久免费网站| 日韩视频免费大全中文字幕| 久久久久久久久电影| 国产一区二区黄| 97免费视频在线| 黑人精品xxx一区一二区| 国产精品一区久久| 在线观看日韩www视频免费| 26uuu另类亚洲欧美日本老年| 欧美黑人狂野猛交老妇| 伊人精品在线观看| 国产999在线| 成人激情视频在线播放| 91免费的视频在线播放| 亚洲一区二区中文字幕| 欧美中文在线观看| 欧美—级高清免费播放| 国内精品久久久久影院优| 精品久久久久久中文字幕| 播播国产欧美激情| 欧美尺度大的性做爰视频| 亚洲视频在线观看| 九九热在线精品视频| 国产亚洲欧美日韩精品| 国产一区二区三区网站| 欧美黄色小视频| 在线午夜精品自拍| 日韩成人xxxx| 亚洲精品国产拍免费91在线| 国产精品久久久久久影视| 在线观看欧美成人| 超在线视频97| 亚洲成av人影院在线观看| 97涩涩爰在线观看亚洲| 欧美一区二区色| 亚洲国产婷婷香蕉久久久久久| 亚洲97在线观看| 亚洲色图18p| 欧美精品久久久久| 日韩欧美在线视频观看| 亚洲a在线播放| 欧美激情视频播放| www欧美日韩| 欧美丝袜一区二区| 亚洲国产精品热久久| 亚洲一区二区黄| 国产日韩欧美在线视频观看| 国产精品久久9| 日韩欧美国产中文字幕| 亚洲欧美制服综合另类| 欧美又大又硬又粗bbbbb| 中文字幕亚洲欧美日韩高清| 久久中文精品视频| 国产精品色午夜在线观看| 国产z一区二区三区| 亚洲japanese制服美女| www日韩中文字幕在线看| 欧美精品情趣视频| 久久精品电影一区二区| 欧美在线一区二区视频| 国产精品午夜国产小视频| 欧美一级淫片videoshd| 欧美乱妇高清无乱码| 91av在线影院| www.亚洲天堂| 日韩av免费在线看| 亚洲天堂日韩电影| 亚洲精品国产拍免费91在线| 日韩小视频网址| 久久亚洲精品一区二区| 国产69精品久久久久99| 国产精品影院在线观看| 91久久在线播放| 亚洲电影免费观看高清完整版| 国产热re99久久6国产精品| 日韩中文字幕第一页| 日韩精品视频免费在线观看| 午夜精品一区二区三区在线| 久久影院资源站| 国产精品白嫩美女在线观看| 欧美日韩中文字幕在线| 欧美成人免费全部观看天天性色| 久久青草精品视频免费观看| 成人欧美一区二区三区在线| 亚洲自拍另类欧美丝袜| 91在线观看欧美日韩| 亚洲国产精品国自产拍av秋霞|