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

首頁 > 系統 > Android > 正文

Android實現有視差效果的ListView

2019-12-12 05:07:52
字體:
來源:轉載
供稿:網友

視差效果是什么?

所謂的視差效果在Web設計和移動應用中都非常常見,我們在一些主要的平臺都可以發現它的身影,從Windows Phone到iOS乃至Android。按照維基百科的說法,視差滾動是計算機圖形學中的一種特殊的滾動技術,在此相機移動背景圖像比前景圖像慢,從而引起了視覺深度的假象。

那么到底什么是視差效果呢?一起來看效果圖就知道了:

我們可以看到 ListView HeaderView 會跟隨 ListView 的滑動而變大,HeaderView里的圖片會有縮放效果。這些可以使用屬性動畫來實現。接下來我們就來動手吧!

首先自定義幾個屬性,在之后可以用到:

<?xml version="1.0" encoding="utf-8"?><resources> <declare-styleable name="ZoomListView"> <!-- headerView的高度 -->  <attr name="header_height" format="dimension|reference"></attr>  <!-- headerView的最大高度 --> <attr name="header_max_height" format="dimension|reference"></attr> <!-- headerView里面的圖片最大的伸縮量 -->  <attr name="header_max_scale" format="float"></attr> </declare-styleable></resources>

之后創建 ZoomListView 類,繼承自 ListView

public class ZoomListView extends ListView {  // 最大的伸縮量 private final float defaultHeaderMaxScale = 1.2f; // 頭部最大的高度 private float headerMaxHeight; // 頭部初始高度 private float headerHeight; // 頭部默認初始高度 private float defaultHeaderHeight; // 頭部默認最大的高度 private float defaultHeaderMaxHeight; private ImageView headerView; private ViewGroup.LayoutParams layoutParams; private LinearLayout linearLayout; // 最大的縮放值 private float headerMaxScale; public ZoomListView(Context context) {  this(context, null); } public ZoomListView(Context context, AttributeSet attrs) {  this(context, attrs, 0); } public ZoomListView(Context context, AttributeSet attrs, int defStyleAttr) {  super(context, attrs, defStyleAttr);  defaultHeaderHeight = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 160, context.getResources().getDisplayMetrics());  defaultHeaderMaxHeight = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 240, context.getResources().getDisplayMetrics());  TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ZoomListView);  headerHeight = a.getDimension(R.styleable.ZoomListView_header_height, defaultHeaderHeight);  headerMaxHeight = a.getDimension(R.styleable.ZoomListView_header_max_height, defaultHeaderMaxHeight);  headerMaxScale = a.getFloat(R.styleable.ZoomListView_header_max_scale, defaultHeaderMaxScale);  a.recycle();  initView(); } ...}

到這里都是按部就班式的,設置好自定義屬性的初始值,之后調用 initView() ,那就來看看 initView() 方法:

private void initView() { headerView = new ImageView(getContext()); headerView.setScaleType(ImageView.ScaleType.CENTER_CROP); linearLayout = new LinearLayout(getContext()); linearLayout.addView(headerView); layoutParams = headerView.getLayoutParams(); if (layoutParams == null) {  layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, (int) headerHeight); } else {  layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;  layoutParams.height = (int) headerHeight; } headerView.setLayoutParams(layoutParams); addHeaderView(linearLayout);}public void setDrawableId(int id) { headerView.setImageResource(id);}

可以看出在 initView() 里我們創建了 headerView ,并添加到了ListView的頭部。而 setDrawableId(int id) 就是給 headerView 設置相關圖片的。

下面就是視差效果的主要實現代碼了:

@Overrideprotected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) { if (deltaY < 0 && isTouchEvent) {  if (headerView.getHeight() < headerMaxHeight) {   int newHeight = headerView.getHeight()     + Math.abs(deltaY / 3);   headerView.getLayoutParams().height = newHeight;   headerView.requestLayout();   float temp = 1 + (headerMaxScale - 1f) * (headerView.getHeight() - headerHeight) / (headerMaxHeight - headerHeight);   headerView.animate().scaleX(temp)     .scaleY(temp).setDuration(0).start();  } } return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);}

我們重寫了 overScrollBy() 方法,當 deltaY 小于0時(即 ListView 已經到頂端,但是用戶手勢還是向下拉),去動態地設置 headerView 的高度以及 headerView scale 值。這樣就可以產生 headerView 變高以及圖片放大的效果了。

接下來要考慮的問題就是當用戶松開手指時,要恢復回原來的樣子。所以我們應該在 onTouchEvent(MotionEvent ev) 里去實現相關操作:

@Overridepublic boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) {  case MotionEvent.ACTION_UP:    startAnim();   break; } return super.onTouchEvent(ev);}// 開始執行動畫private void startAnim() { ValueAnimator animator = ValueAnimator.ofFloat(headerView.getHeight(), headerHeight); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {  @Override  public void onAnimationUpdate(ValueAnimator animation) {   float fraction = (float) animation.getAnimatedValue();   headerView.getLayoutParams().height = (int) fraction;   headerView.requestLayout();  } }); animator.setDuration(500); animator.setInterpolator(new LinearInterpolator()); ValueAnimator animator2 = ValueAnimator.ofFloat(headerView.getScaleX(), 1f); animator2.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {  @Override  public void onAnimationUpdate(ValueAnimator animation) {   float fraction = (float) animation.getAnimatedValue();   headerView.setScaleX(fraction);   headerView.setScaleY(fraction);  } }); animator2.setDuration(500); animator2.setInterpolator(new LinearInterpolator()); animator.start(); animator2.start();}

上面的代碼簡單點來說,就是在 ACTION_UP 時,去開始兩個屬性動畫,一個屬性動畫是將 headerView 的高度恢復成原來的值,另一個屬性動畫就是把 headerView 的 scale 重新恢復為1f。相信大家都可以看懂的。

總結

以上就是這篇文章的全部內容了,希望這篇文章的內容對各位Android開發者們能有所幫助,如果有疑問大家可以留言交流。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 夏邑县| 高尔夫| 涡阳县| 深州市| 什邡市| 福鼎市| 广宁县| 衢州市| 西畴县| 伊金霍洛旗| 安化县| 会昌县| 息烽县| 惠州市| 尤溪县| 和平区| 镇巴县| 大冶市| 连云港市| 苏尼特左旗| 金寨县| 花垣县| 迁安市| 平遥县| 固镇县| 河源市| 余江县| 青神县| 皮山县| 宜兰市| 略阳县| 望城县| 阳谷县| 株洲市| 平山县| 德兴市| 博爱县| 福泉市| 广平县| 安达市| 沭阳县|