Android下拉圖片變大的ScrollView
阿新 • • 發佈:2019-01-29
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);
}
}
}