Android仿QQ好友詳情頁(yè)下拉頂部圖片縮放效果
今天已經(jīng)是這個(gè)星期連續(xù)加班的第四天了,趁著現(xiàn)在后臺(tái)在處理邏輯問(wèn)題,將前幾天寫的一個(gè)小例子整理下來(lái)。
效果圖

效果分析
1 向下滑動(dòng),頭部的圖片隨著手指滑動(dòng)不斷變大
2 向上滑動(dòng),不斷的向上移動(dòng)圖片,直到圖片不可見(jiàn)
3 當(dāng)頂部圖片不可見(jiàn)時(shí),向上滑動(dòng),滑動(dòng)ListView
實(shí)現(xiàn)思路
1 由于這個(gè)View分上下兩部分,垂直排列,可以通過(guò)繼承LinearLayout實(shí)現(xiàn)::自定義一個(gè)DragImageView,該View繼承LinearLayout
public DragImageView(Context context, AttributeSet attrs) {
super(context, attrs);
// 默認(rèn)該View垂直排列
setOrientation(LinearLayout.VERTICAL);
// 用于配合處理該View的慣性滑動(dòng)
mScroller = new OverScroller(context);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
mMaximumVelocity = ViewConfiguration.get(context)
.getScaledMaximumFlingVelocity();
mMinimumVelocity = ViewConfiguration.get(context)
.getScaledMinimumFlingVelocity();
}
2 onMeasure中設(shè)置內(nèi)容視圖的高度
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
LayoutParams params = (LayoutParams) getChildAt(1).getLayoutParams();
// 頭部可以全部隱藏,所以內(nèi)容視圖的高度即為該控件的高度
params.height = getMeasuredHeight();
}
3 設(shè)置ImageView的ScaleType屬性
@Override
protected void onFinishInflate() {
super.onFinishInflate();
imageView = (ImageView) getChildAt(0);
// 隨著手指滑動(dòng),圖片不斷放大(寬高都大于或者等于ImageView的大?。⒕又酗@示:
// 根據(jù)上邊的分析,CENTER_CROP:可以使用均衡的縮放圖像(保持圖像原始比例),使圖片的兩個(gè)坐標(biāo)(寬、高)都大于等于 相應(yīng)的視圖坐標(biāo)(負(fù)的內(nèi)邊距),圖像則位于視圖的中央
imageView.setScaleType(ScaleType.CENTER_CROP);
listView = (ListView) getChildAt(1);
}
4 事件攔截
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
downX = (int) ev.getX();
downY = (int) ev.getY();
}
if (ev.getAction() == MotionEvent.ACTION_MOVE) {
int currentX = (int) ev.getX();
int currentY = (int) ev.getY();
// 確保是垂直滑動(dòng)
if (Math.abs(currentY - downY) > Math.abs(currentX - downX)) {
View childView = listView.getChildAt(listView
.getFirstVisiblePosition());
// 有兩種情況需要攔截:
// 1 圖片沒(méi)有完全隱藏
// 2 圖片完全隱藏,但是向下滑動(dòng),并且ListView滑動(dòng)到頂部
if (getScrollY() != imageHeight
|| (getScrollY() == imageHeight && currentY - downY > 0
&& childView != null && childView.getTop() == 0)) {
initVelocityTrackerIfNotExists();
mVelocityTracker.addMovement(ev);
return true;
}
}
}
if (ev.getAction() == MotionEvent.ACTION_UP) {
recycleVelocityTracker();
}
return super.onInterceptTouchEvent(ev);
}
5 onTouchEvent的ACTION_MOVE處理
if (ev.getAction() == MotionEvent.ACTION_MOVE) {
int currentX = (int) ev.getX();
int currentY = (int) ev.getY();
int deltyX = currentX - downX;
int deltyY = currentY - downY;
if (Math.abs(deltyY) > Math.abs(deltyX)) {
if (deltyY > 0) {
if (getScrollY() > 0) {
if (getScrollY() - deltyY < 0) {
scrollBy(0, -getScrollY());
return true;
}
// 當(dāng)圖片沒(méi)有完全顯示,并且向下滑動(dòng)時(shí),繼續(xù)整個(gè)view使圖片可見(jiàn)
scrollBy(0, -deltyY);
} else {
// 當(dāng)圖片完全顯示,并且向下滑動(dòng)時(shí),則不斷的放大圖片(通過(guò)改變ImageView)的高度
LayoutParams layoutParams = (LayoutParams) getChildAt(0)
.getLayoutParams();
layoutParams.height = layoutParams.height + deltyY / 2;
getChildAt(0).setLayoutParams(layoutParams);
}
} else {
// 當(dāng)圖片還處于放大狀態(tài),并且向上滑動(dòng)時(shí),繼續(xù)不斷的縮小圖片的高度,使圖片縮小
if (getChildAt(1).getTop() > imageHeight) {
LayoutParams layoutParams = (LayoutParams) getChildAt(0)
.getLayoutParams();
layoutParams.height = layoutParams.height + deltyY / 2;
getChildAt(0).setLayoutParams(layoutParams);
} else {
// 當(dāng)圖片處于正常狀態(tài),并且向上滑動(dòng)時(shí),移動(dòng)整個(gè)View,縮小圖片的可見(jiàn)范圍
if (getScrollY() - deltyY > imageHeight) {
scrollBy(0, imageHeight - getScrollY());
return true;
}
scrollBy(0, -deltyY);
}
}
downY = currentY;
downX = currentX;
return true;
}
}
5 onTouchEvent的ACTION_UP處理
if (ev.getAction() == MotionEvent.ACTION_UP) {
// 當(dāng)圖片處于放大狀態(tài)時(shí)松手,使圖片緩慢的縮回到原來(lái)的狀態(tài)
if (getChildAt(1).getTop() > imageHeight) {
isAnimating = true;
ValueAnimator valueAnimator = ValueAnimator.ofInt(getChildAt(1)
.getTop(), imageHeight);
valueAnimator.setDuration(300);
valueAnimator.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int value = (Integer) animation.getAnimatedValue();
LayoutParams layoutParams = (LayoutParams) getChildAt(0)
.getLayoutParams();
layoutParams.height = value;
getChildAt(0).setLayoutParams(layoutParams);
}
});
valueAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
isAnimating = false;
}
});
valueAnimator.start();
}
// 當(dāng)現(xiàn)在圖片處于正常狀態(tài),并且圖片沒(méi)有完全隱藏,并且松手時(shí)滑動(dòng)的速度大于可慣性滑動(dòng)的最小值,讓View產(chǎn)生慣性滑動(dòng)效果
if (getChildAt(1).getTop() == imageHeight
&& getScrollY() != imageHeight) {
mVelocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
int velocityY = (int) mVelocityTracker.getYVelocity();
if (Math.abs(velocityY) > mMinimumVelocity) {
fling(-velocityY);
}
recycleVelocityTracker();
}
總結(jié)
這里主要有兩個(gè)學(xué)習(xí)的點(diǎn)
1 圖片縮放的處理,事件的攔截
2 View的慣性滑動(dòng):主要是結(jié)合OverScroller的使用
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android控件實(shí)現(xiàn)圖片縮放功能
- Android實(shí)現(xiàn)手指觸控圖片縮放功能
- Android點(diǎn)擊WebView實(shí)現(xiàn)圖片縮放及滑動(dòng)瀏覽效果
- Android 自定義imageview實(shí)現(xiàn)圖片縮放實(shí)例詳解
- Android實(shí)現(xiàn)ImageView圖片縮放和拖動(dòng)
- Android 圖片縮放實(shí)例詳解
- Android應(yīng)用中實(shí)現(xiàn)手勢(shì)控制圖片縮放的完全攻略
- android 多點(diǎn)觸摸圖片縮放的具體實(shí)現(xiàn)方法
- Android 圖片縮放與旋轉(zhuǎn)的實(shí)現(xiàn)詳解
- Android實(shí)現(xiàn)圖片雙指縮放
相關(guān)文章
Android實(shí)現(xiàn)檢測(cè)實(shí)體按鍵事件并屏蔽
這篇文章主要介紹了Android實(shí)現(xiàn)檢測(cè)實(shí)體按鍵事件并屏蔽 ,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08
詳談OnTouchListener與OnGestureListener的區(qū)別
下面小編就為大家?guī)?lái)一篇詳談OnTouchListener與OnGestureListener的區(qū)別。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-04-04
Android實(shí)現(xiàn)文字動(dòng)態(tài)高亮讀取進(jìn)度效果
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)文字動(dòng)態(tài)高亮讀取進(jìn)度效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-05-05
Android自定義View實(shí)現(xiàn)柱狀波形圖的繪制
柱狀波形圖是一種常見(jiàn)的圖形。一個(gè)個(gè)柱子按順序排列,構(gòu)成一個(gè)波形圖。本文將利用Android自定義View實(shí)現(xiàn)柱狀波形圖的繪制,需要的可以參考一下2022-08-08
Android?Flutter實(shí)現(xiàn)彈簧動(dòng)畫交互的示例詳解
物理模擬可以讓應(yīng)用程序的交互感覺(jué)逼真和互動(dòng),本文章實(shí)現(xiàn)了演示了如何使用彈簧模擬將小部件從拖動(dòng)的點(diǎn)移回中心,感興趣的可以了解一下2023-04-04
Android屏幕旋轉(zhuǎn) 處理Activity與AsyncTask的最佳解決方案
運(yùn)行時(shí)變更就是設(shè)備在運(yùn)行時(shí)發(fā)生變化(例如屏幕旋轉(zhuǎn)、鍵盤可用性及語(yǔ)言)。發(fā)生這些變化,Android會(huì)重啟Activity,這時(shí)就需要保存activity的狀態(tài)及與activity相關(guān)的任務(wù),以便恢復(fù)activity的狀態(tài)。為此,google提供了三種解決方案,本文將對(duì)這三種方案進(jìn)行逐一介紹。2016-12-12
Android中使用Camera類編寫手機(jī)拍照App的實(shí)例教程
這篇文章主要介紹了Android中使用Camera類編寫手機(jī)拍照App的實(shí)例教程,整理了Camera調(diào)用硬件進(jìn)行拍照的一些常用方法,需要的朋友可以參考下2016-04-04
Fragment跳轉(zhuǎn)時(shí)傳遞參數(shù)及結(jié)果回傳的方法(推薦)
今天總結(jié)一下Fragment間的參數(shù)傳遞及結(jié)果返回的方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下2017-01-01

