1. 程式人生 > >Android下拉圖片變大的ScrollView

Android下拉圖片變大的ScrollView

1、效果圖

效果圖

2、實現簡介

1、佈局結構

(1)、專案結構
程式碼結構圖
(2)、程式碼結構
gitosc程式碼結構連結
一個主Activity,一個PullToZoomScrollView(即自定義的ScrollView),還有一個工具類(可以忽略)
(3)、佈局結構
gitosc佈局結構連結
主佈局:分為兩塊,一個為TopBar,即標題欄(這個不用說了),另外一個是自定義的ScrollView,即PullToZoomScrollView。既然是ScrollView,它也是ViewGroop,所以它內部也可以包含多個佈局。
PullToZoomScrollView佈局:也包含兩塊,一個是上面要下拉可以變大的佈局(即含背景圖的佈局),一個就是下面的文字顯示佈局。我這裡是分別寫兩個layout佈局,在主佈局裡include進去的。

3、實現程式碼

主要介紹PullToZoomScrollView程式碼

程式碼連結:gitos程式碼連結
覺得下面程式碼不好看的,可以點上面的連結去開源中國的git裡程式碼展示頁面看。程式碼裡註釋很詳細

package app.jiyi.com.pulltozoomscrollview;

import android.animation.ObjectAnimator;
import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import
android.util.TypedValue; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.LinearLayout; import android.widget.ScrollView; /** * Created by JIYI on 2015/8/10. */ public class PullToZoomScrollView extends ScrollView
{
private boolean isonce;//載入該View的佈局時是否是第一次載入,是第一次就讓其實現OnMeasure裡的程式碼 private LinearLayout mParentView;//佈局的父佈局,ScrollView內部只能有一個根ViewGroup,就是此View private ViewGroup mTopView;//這個是帶背景的上半部分的View,下半部分的View用不到的 private int mScreenHeight;//整個手機螢幕的高度,這是為了初始化該View時設定mTopView用的 private int mTopViewHeight;//這個就是mTopView的高度 private int mCurrentOffset=0;//當前右側滾條頂點的偏移量。ScrollView右側是有滾動條的,當下拉時, //滾動條向上滑,當向下滑動時,滾動條向下滑動。 private ObjectAnimator oa;//這個是物件動畫,這個在本View裡很簡單,也很獨立,就在這裡申明一下,後面有兩個方法 //兩個方法是:setT(int t),reset()兩個方法用到,其他都和它無關了。 /** * 初始化獲取高度值,並記錄 * @param context * @param attrs */ public PullToZoomScrollView(Context context, AttributeSet attrs) { super(context, attrs); this.setOverScrollMode(View.OVER_SCROLL_NEVER); WindowManager wm= (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE); DisplayMetrics metrics=new DisplayMetrics(); wm.getDefaultDisplay().getMetrics(metrics); mScreenHeight=metrics.heightPixels; mTopViewHeight=mScreenHeight/2-(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 90, context.getResources().getDisplayMetrics()); } /** * 將記錄的值設定到控制元件上,並只讓控制元件設定一次 * @param widthMeasureSpec * @param heightMeasureSpec */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); if(!isonce) { mParentView = (LinearLayout) this.getChildAt(0); mTopView = (ViewGroup) mParentView.getChildAt(0); mTopView.getLayoutParams().height = mTopViewHeight; isonce=true; } } private float startY=0;//向下拉動要放大,手指向下滑時,點選的第一個點的Y座標 private boolean isBig;//是否正在向下拉放大上半部分View private boolean isTouchOne;//是否是一次連續的MOVE,預設為false, //在MoVe時,如果發現滑動標籤位移量為0,則獲取此時的Y座標,作為起始座標,然後置為true,為了在連續的Move中只獲取一次起始座標 //當Up彈起時,一次觸控移動完成,將isTouchOne置為false private float distance=0;//向下滑動到釋放的高度差 @Override public boolean onTouchEvent(MotionEvent ev) { int action =ev.getAction(); switch (action){ case MotionEvent.ACTION_DOWN: break; case MotionEvent.ACTION_MOVE: if(mCurrentOffset<=0){ if(!isTouchOne){ startY=ev.getY(); isTouchOne=true; } distance=ev.getY()-startY; if(distance>0){ isBig=true; setT((int)-distance/4); } } break; case MotionEvent.ACTION_UP: if(isBig) { reset(); isBig=false; } isTouchOne=false; break; } return super.onTouchEvent(ev); } /** * 物件動畫要有的設定方法 * @param t */ public void setT(int t) { scrollTo(0, 0); if (t < 0) { mTopView.getLayoutParams().height = mTopViewHeight-t; mTopView.requestLayout(); } } /** * 主要用於釋放手指後的回彈效果 */ private void reset() { if (oa != null && oa.isRunning()) { return; } oa = ObjectAnimator.ofInt(this, "t", (int)-distance / 4, 0); oa.setDuration(150); oa.start(); } /** * 這個是設定向上滑動時,上半部分View滑動速度讓其小於下半部分 * @param l * @param t * @param oldl * @param oldt */ @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); mCurrentOffset = t;//右邊滑動標籤相對於頂端的偏移量 //當手勢上滑,則右側滾動條下滑,下滑的高度小於TopView的高度,則讓TopView的上滑速度小於DownView的上滑速度 //DownView的上滑速度是滾動條的速度,也就是滾動的距離是右側滾動條的距離 //則TopView的速度要小,只需要將右側滾動條的偏移量也就是t縮小一定倍數就行了。我這裡除以2速度減小1倍 if (t <= mTopViewHeight&&t>=0&&!isBig) { mTopView.setTranslationY(t / 2);//使得TopView滑動的速度小於滾輪滾動的速度 } if(isBig){ scrollTo(0,0); } } }

4、Demo下載