Java簡略數組排序(冒泡法)。本站提示廣大學習愛好者:(Java簡略數組排序(冒泡法))文章只能為提供參考,不一定能成為您想要的結果。以下是Java簡略數組排序(冒泡法)正文
文章將在原有基本之上做了一些擴大功效:
1.圖片的慣性滑動
2.圖片縮放小於正常比例時,松手會主動回彈成正常比例
3.圖片縮縮小於最年夜比例時,松手會主動回彈成最年夜比例
完成圖片的縮放,平移,雙擊縮放等根本功效的代碼以下,每行代碼我都做了具體的正文
public class ZoomImageView extends ImageView implements ScaleGestureDetector.OnScaleGestureListener,
View.OnTouchListener , ViewTreeObserver.OnGlobalLayoutListener{
/**
* 縮撒手勢的監測
*/
private ScaleGestureDetector mScaleGestureDetector;
/**
* 監聽手勢
*/
private GestureDetector mGestureDetector;
/**
* 對圖片停止縮放平移的Matrix
*/
private Matrix mScaleMatrix;
/**
* 第一次加載圖片時調劑圖片縮放比例,使圖片的寬或許高充斥屏幕
*/
private boolean mFirst;
/**
* 圖片的初始化比例
*/
private float mInitScale;
/**
* 圖片的最年夜比例
*/
private float mMaxScale;
/**
* 雙擊圖片縮小的比例
*/
private float mMidScale;
/**
* 能否正在主動縮小或許減少
*/
private boolean isAutoScale;
//-----------------------------------------------
/**
* 上一次觸控點的數目
*/
private int mLastPointerCount;
/**
* 能否可以拖動
*/
private boolean isCanDrag;
/**
* 上一次滑動的x和y坐標
*/
private float mLastX;
private float mLastY;
/**
* 可滑動的臨界值
*/
private int mTouchSlop;
/**
* 能否用檢討閣下界限
*/
private boolean isCheckLeftAndRight;
/**
* 能否用檢討高低界限
*/
private boolean isCheckTopAndBottom;
public ZoomImageView(Context context) {
this(context, null, 0);
}
public ZoomImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ZoomImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//必定要將圖片的ScaleType設置成Matrix類型的
setScaleType(ScaleType.MATRIX);
//初始化縮撒手勢監聽器
mScaleGestureDetector = new ScaleGestureDetector(context,this);
//初始化矩陣
mScaleMatrix = new Matrix();
setOnTouchListener(this);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
//初始化手勢檢測器,監聽雙擊事宜
mGestureDetector = new GestureDetector(context,new GestureDetector.SimpleOnGestureListener(){
@Override
public boolean onDoubleTap(MotionEvent e) {
//假如是正在主動縮放,則直接前往,不停止處置
if (isAutoScale) return true;
//獲得點擊的坐標
float x = e.getX();
float y = e.getY();
//假如以後圖片的縮放值小於指定的雙擊縮放值
if (getScale() < mMidScale){
//停止主動縮小
post(new AutoScaleRunnable(mMidScale,x,y));
}else{
//以後圖片的縮放值年夜於初試縮放值,則主動減少
post(new AutoScaleRunnable(mInitScale,x,y));
}
return true;
}
});
}
/**
* 當view添加到window時挪用,早於onGlobalLayout,是以可以在這裡注冊監聽器
*/
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
getViewTreeObserver().addOnGlobalLayoutListener(this);
}
/**
* 當view從window上移除時挪用,是以可以在這裡移除監聽器
*/
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
/**
* 當結構樹產生變更時會挪用此辦法,我們可以在此辦法中取得控件的寬和高
*/
@Override
public void onGlobalLayout() {
//只要當第一次加載圖片的時刻才會停止初始化,用一個變量mFirst掌握
if (!mFirst){
mFirst = true;
//獲得控件的寬和高
int width = getWidth();
int height = getHeight();
//獲得以後ImageView中加載的圖片
Drawable d = getDrawable();
if(d == null){//假如沒有圖片,則直接前往
return;
}
//獲得以後圖片的寬和高,圖片的寬和高紛歧定等於控件的寬和高
//是以我們須要將圖片的寬和高與控件寬和高停止斷定
//將圖片完全的顯示在屏幕中
int dw = d.getIntrinsicWidth();
int dh = d.getIntrinsicHeight();
//我們界說一個暫時變量,依據圖片與控件的寬高比例,來肯定這個終究縮放值
float scale = 1.0f;
//假如圖片寬度年夜於控件寬度,圖片高度小於控件高度
if (dw>width && dh<height){
//我們須要將圖片寬度減少,減少至控件的寬度
//至於為何要如許盤算,我們可以如許想
//我們挪用matrix.postScale(scale,scale)時,寬和高都要乘以scale的
//以後我們的圖片寬度是dw,dw*scale=dw*(width/dw)=width,如許就等於控件寬度了
//我們的高度同時也乘以scale,如許可以或許包管圖片的寬高比不轉變,圖片不變形
scale = width * 1.0f / dw;
}
//假如圖片的寬度小於控件寬度,圖片高度年夜於控件高度
if (dw<width && dh>height){
//我們就應當將圖片的高度減少,減少至控件的高度,盤算辦法同上
scale = height * 1.0f / dh;
}
//假如圖片的寬度小於控件寬度,高度小於控件高度時,我們應當將圖片縮小
//好比圖片寬度是控件寬度的1/2 ,圖片高度是控件高度的1/4
//假如我們將圖片縮小4倍,則圖片的高度是和控件高度一樣了,然則圖片寬度就超越控件寬度了
//是以我們應當選擇一個最小值,那就是將圖片縮小2倍,此時圖片寬度等於控件寬度
//同理,假如圖片寬度年夜於控件寬度,圖片高度年夜於控件高度,我們應當將圖片減少
//減少的倍數也應當為誰人最小值
if ((dw < width && dh < height) || (dw > width && dh > height)){
scale = Math.min(width * 1.0f / dw , height * 1.0f / dh);
}
//我們還應當對圖片停止平移操作,將圖片挪動到屏幕的居中地位
//控件寬度的一半減去圖片寬度的一半即為圖片須要程度挪動的間隔
//高度同理,年夜家可以畫個圖看一看
int dx = width/2 - dw/2;
int dy = height/2 - dh/2;
//對圖片停止平移,dx和dy分離表現程度和豎直挪動的間隔
mScaleMatrix.postTranslate(dx, dy);
//對圖片停止縮放,scale為縮放的比例,後兩個參數為縮放的中間點
mScaleMatrix.postScale(scale, scale, width / 2, height / 2);
//將矩陣感化於我們的圖片上,圖片真正獲得了平移和縮放
setImageMatrix(mScaleMatrix);
//初始化一下我們的幾個縮放的界限值
mInitScale = scale;
//最年夜比例為初始比例的4倍
mMaxScale = mInitScale * 4;
//雙擊縮小比例為初始化比例的2倍
mMidScale = mInitScale * 2;
}
}
/**
* 取得圖片以後的縮放比例值
*/
private float getScale(){
//Matrix為一個3*3的矩陣,一共9個值
float[] values = new float[9];
//將Matrix的9個值映照到values數組中
mScaleMatrix.getValues(values);
//拿到Matrix中的MSCALE_X的值,這個值為圖片寬度的縮放比例,由於圖片高度
//的縮放比例和寬度的縮放比例分歧,我們取一個便可以了
//我們還可以 return values[Matrix.MSCALE_Y];
return values[Matrix.MSCALE_X];
}
/**
* 取得縮放後圖片的高低閣下坐標和寬高
*/
private RectF getMatrixRectF(){
//取得當錢圖片的矩陣
Matrix matrix = mScaleMatrix;
//創立一個浮點類型的矩形
RectF rectF = new RectF();
//獲得以後的圖片
Drawable d = getDrawable();
if (d != null){
//使這個矩形的寬和高同以後圖片分歧
rectF.set(0,0,d.getIntrinsicWidth(),d.getIntrinsicHeight());
//將矩陣映照到矩形下面,以後我們可以經由過程獲得到矩陣的高低閣下坐標和寬高
//來獲得縮放後圖片的高低閣下坐標和寬高
matrix.mapRect(rectF);
}
return rectF;
}
/**
* 當縮放時檢討界限而且使圖片居中
*/
private void checkBorderAndCenterWhenScale(){
if (getDrawable() == null){
return;
}
//初始化程度和豎直偏向的偏移量
float deltaX = 0.0f;
float deltaY = 0.0f;
//獲得控件的寬和高
int width = getWidth();
int height = getHeight();
//拿到以後圖片對應的矩陣
RectF rectF = getMatrixRectF();
//假如以後圖片的寬度年夜於控件寬度,以後圖片處於縮小狀況
if (rectF.width() >= width){
//假如圖片右邊坐標是年夜於0的,解釋圖片右邊離控件右邊有必定間隔,
//右邊會湧現一個小白邊
if (rectF.left > 0){
//我們將圖片向右邊挪動
deltaX = -rectF.left;
}
//假如圖片左邊坐標小於控件寬度,解釋圖片左邊離控件左邊有必定間隔,
//左邊會湧現一個小白邊
if (rectF.right <width){
//我們將圖片向左邊挪動
deltaX = width - rectF.right;
}
}
//下面是調劑寬度,這是調劑高度
if (rectF.height() >= height){
//假如下面湧現小白邊,則向上挪動
if (rectF.top > 0){
deltaY = -rectF.top;
}
//假如上面湧現小白邊,則向下挪動
if (rectF.bottom < height){
deltaY = height - rectF.bottom;
}
}
//假如圖片的寬度小於控件的寬度,我們要對圖片做一個程度的居中
if (rectF.width() < width){
deltaX = width/2f - rectF.right + rectF.width()/2f;
}
//假如圖片的高度小於控件的高度,我們要對圖片做一個豎直偏向的居中
if (rectF.height() < height){
deltaY = height/2f - rectF.bottom + rectF.height()/2f;
}
//將平移的偏移量感化到矩陣上
mScaleMatrix.postTranslate(deltaX, deltaY);
}
/**
* 平移時檢討高低閣下界限
*/
private void checkBorderWhenTranslate() {
//取得縮放後圖片的響應矩形
RectF rectF = getMatrixRectF();
//初始化程度和豎直偏向的偏移量
float deltaX = 0.0f;
float deltaY = 0.0f;
//獲得控件的寬度
int width = getWidth();
//獲得控件的高度
int height = getHeight();
//假如是須要檢討左和左邊界
if (isCheckLeftAndRight){
//假如右邊湧現的白邊
if (rectF.left > 0){
//向左偏移
deltaX = -rectF.left;
}
//假如左邊湧現的白邊
if (rectF.right < width){
//向右偏移
deltaX = width - rectF.right;
}
}
//假如是須要檢討上和下界限
if (isCheckTopAndBottom){
//假如下面湧現白邊
if (rectF.top > 0){
//向上偏移
deltaY = -rectF.top;
}
//假如上面湧現白邊
if (rectF.bottom < height){
//向下偏移
deltaY = height - rectF.bottom;
}
}
mScaleMatrix.postTranslate(deltaX,deltaY);
}
/**
* 主動縮小減少,主動縮放的道理是應用View.postDelay()辦法,每隔16ms挪用一次
* run辦法,給人視覺上構成一種動畫的後果
*/
private class AutoScaleRunnable implements Runnable{
//縮小或許減少的目的比例
private float mTargetScale;
//能夠是BIGGER,也能夠是SMALLER
private float tempScale;
//縮小減少的中間點
private float x;
private float y;
//比1略微年夜一點,用於縮小
private final float BIGGER = 1.07f;
//比1略微小一點,用於減少
private final float SMALLER = 0.93f;
//結構辦法,將目的比例,縮放中間點傳入,而且斷定是要縮小照樣減少
public AutoScaleRunnable(float targetScale , float x , float y){
this.mTargetScale = targetScale;
this.x = x;
this.y = y;
//假如以後縮放比例小於目的比例,解釋要主動縮小
if (getScale() < mTargetScale){
//設置為Bigger
tempScale = BIGGER;
}
//假如以後縮放比例年夜於目的比例,解釋要主動減少
if (getScale() > mTargetScale){
//設置為Smaller
tempScale = SMALLER;
}
}
@Override
public void run() {
//這裡縮放的比例異常小,只是略微比1年夜一點或許比1小一點的倍數
//然則當每16ms都縮小或許減少一點點的時刻,動畫後果就出來了
mScaleMatrix.postScale(tempScale, tempScale, x, y);
//每次將矩陣感化到圖片之前,都檢討一下界限
checkBorderAndCenterWhenScale();
//將矩陣感化到圖片上
setImageMatrix(mScaleMatrix);
//獲得以後圖片的縮放值
float currentScale = getScale();
//假如以後想要縮小,而且以後縮放值小於目的縮放值
//或許 以後想要減少,而且以後縮放值年夜於目的縮放值
if ((tempScale > 1.0f) && currentScale < mTargetScale
||(tempScale < 1.0f) && currentScale > mTargetScale){
//每隔16ms就挪用一次run辦法
postDelayed(this,16);
}else {
//current*scale=current*(mTargetScale/currentScale)=mTargetScale
//包管圖片終究的縮放值和目的縮放值分歧
float scale = mTargetScale / currentScale;
mScaleMatrix.postScale(scale, scale, x, y);
checkBorderAndCenterWhenScale();
setImageMatrix(mScaleMatrix);
//主動縮放停止,置為false
isAutoScale = false;
}
}
}
/**
* 這個是OnScaleGestureListener中的辦法,在這個辦法中我們可以對圖片停止縮小減少
*/
@Override
public boolean onScale(ScaleGestureDetector detector) {
//當我們兩個手指停止離開操作時,解釋我們想要縮小,這個scaleFactor是一個略微年夜於1的數值
//當我們兩個手指停止閉合操作時,解釋我們想要減少,這個scaleFactor是一個略微小於1的數值
float scaleFactor = detector.getScaleFactor();
//取得我們圖片以後的縮放值
float scale = getScale();
//假如以後沒有圖片,則直接前往
if (getDrawable() == null){
return true;
}
//假如scaleFactor年夜於1,解釋想縮小,以後的縮放比例乘以scaleFactor以後小於
//最年夜的縮放比例時,許可縮小
//假如scaleFactor小於1,解釋想減少,以後的縮放比例乘以scaleFactor以後年夜於
//最小的縮放比例時,許可減少
if ((scaleFactor > 1.0f && scale * scaleFactor < mMaxScale)
|| scaleFactor < 1.0f && scale * scaleFactor > mInitScale){
//界限掌握,假如以後縮放比例乘以scaleFactor以後年夜於了最年夜的縮放比例
if (scale * scaleFactor > mMaxScale + 0.01f){
//則將scaleFactor設置成mMaxScale/scale
//當再停止matrix.postScale時
//scale*scaleFactor=scale*(mMaxScale/scale)=mMaxScale
//最初圖片就會縮小至mMaxScale縮放比例的年夜小
scaleFactor = mMaxScale / scale;
}
//界限掌握,假如以後縮放比例乘以scaleFactor以後小於了最小的縮放比例
//我們不許可再減少
if (scale * scaleFactor < mInitScale + 0.01f){
//盤算辦法同上
scaleFactor = mInitScale / scale;
}
//前兩個參數是縮放的比例,是一個略微年夜於1或許略微小於1的數,構成一個跟著手指縮小
//或許減少的後果
//detector.getFocusX()和detector.getFocusY()獲得的是多點觸控的中點
//如許就可以完成我們在圖片的某一處部分縮小的後果
mScaleMatrix.postScale(scaleFactor, scaleFactor, detector.getFocusX(), detector.getFocusY());
//由於圖片的縮放點不是圖片的中間點了,所以圖片會湧現偏移的景象,所以停止一次界限的檢討和居中操作
checkBorderAndCenterWhenScale();
//將矩陣感化到圖片上
setImageMatrix(mScaleMatrix);
}
return true;
}
/**
* 必定要前往true
*/
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
return true;
}
@Override
public void onScaleEnd(ScaleGestureDetector detector) {
}
@Override
public boolean onTouch(View v, MotionEvent event) {
//當雙擊操作時,不許可挪動圖片,直接前往true
if (mGestureDetector.onTouchEvent(event)){
return true;
}
//將事宜傳遞給ScaleGestureDetector
mScaleGestureDetector.onTouchEvent(event);
//用於存儲多點觸控發生的坐標
float x = 0.0f;
float y = 0.0f;
//獲得多點觸控的個數
int pointerCount = event.getPointerCount();
//將一切觸控點的坐標累加起來
for(int i=0 ; i<pointerCount ; i++){
x += event.getX(i);
y += event.getY(i);
}
//取均勻值,獲得的就是多點觸控後發生的誰人點的坐標
x /= pointerCount;
y /= pointerCount;
//假如觸控點的數目變了,則置為弗成滑動
if (mLastPointerCount != pointerCount){
isCanDrag = false;
mLastX = x;
mLastY = y;
}
mLastPointerCount = pointerCount;
RectF rectF = getMatrixRectF();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
isCanDrag = false;
//當圖片處於縮小狀況時,制止ViewPager攔阻事宜,將事宜傳遞給圖片,停止拖動
if (rectF.width() > getWidth() + 0.01f || rectF.height() > getHeight() + 0.01f){
if (getParent() instanceof ViewPager){
getParent().requestDisallowInterceptTouchEvent(true);
}
}
break;
case MotionEvent.ACTION_MOVE:
//當圖片處於縮小狀況時,制止ViewPager攔阻事宜,將事宜傳遞給圖片,停止拖動
if (rectF.width() > getWidth() + 0.01f || rectF.height() > getHeight() + 0.01f){
if (getParent() instanceof ViewPager){
getParent().requestDisallowInterceptTouchEvent(true);
}
}
//獲得程度和豎直偏向的偏移量
float dx = x - mLastX;
float dy = y - mLastY;
//假如以後是弗成滑動的狀況,斷定一下能否是滑動的操作
if (!isCanDrag){
isCanDrag = isMoveAction(dx,dy);
}
//假如可滑動
if (isCanDrag){
if (getDrawable() != null){
isCheckLeftAndRight = true;
isCheckTopAndBottom = true;
//假如圖片寬度小於控件寬度
if (rectF.width() < getWidth()){
//閣下弗成滑動
dx = 0;
//閣下弗成滑動,也就不消檢討閣下的界限了
isCheckLeftAndRight = false;
}
//假如圖片的高度小於控件的高度
if (rectF.height() < getHeight()){
//高低弗成滑動
dy = 0;
//高低弗成滑動,也就不消檢討高低界限了
isCheckTopAndBottom = false;
}
}
mScaleMatrix.postTranslate(dx,dy);
//當平移時,檢討高低閣下界限
checkBorderWhenTranslate();
setImageMatrix(mScaleMatrix);
}
mLastX = x;
mLastY = y;
break;
case MotionEvent.ACTION_UP:
//當手指抬起時,將mLastPointerCount置0,停滯滑動
mLastPointerCount = 0;
break;
case MotionEvent.ACTION_CANCEL:
break;
}
return true;
}
/**
* 斷定能否是挪動的操作
*/
private boolean isMoveAction(float dx , float dy){
//勾股定理,斷定斜邊能否年夜於可滑動的一個臨界值
return Math.sqrt(dx*dx + dy*dy) > mTouchSlop;
}
}
完成圖片減少後,松手回彈的後果
完成這個功效很簡略,我們先添加一個mMinScale作為可減少到的最小值,我們指定為初試比例的1/4
/**
* 最小縮放比例
*/
private float mMinScale;
//在onGlobalLayout中停止初始化
@Override
public void onGlobalLayout() {
...
//最小縮放比例為初試比例的1/4倍
mMinScale = mInitScale / 4;
...
}
//在onScale中,修正以下代碼
@Override
public boolean onScale(ScaleGestureDetector detector) {
...
if ((scaleFactor > 1.0f && scale * scaleFactor < mMaxScale)
|| scaleFactor < 1.0f && scale * scaleFactor > mMinScale){
//界限掌握,假如以後縮放比例乘以scaleFactor以後小於了最小的縮放比例
//我們不許可再減少
if (scale * scaleFactor < mMinScale + 0.01f){
scaleFactor = mMinScale / scale;
}
...
}
如許我們的圖片最小便可以縮放到初始化比例的1/4年夜小了,然後我們還須要添加一個松手後回彈至初試化年夜小的動畫後果,然後我們須要在onTouch的ACTION_UP中添加以下代碼
@Override
public boolean onTouch(View v, MotionEvent event) {
...
case MotionEvent.ACTION_UP:
//當手指抬起時,將mLastPointerCount置0,停滯滑動
mLastPointerCount = 0;
//假如以後圖片年夜小小於初始化年夜小
if (getScale() < mInitScale){
//主動縮小至初始化年夜小
post(new AutoScaleRunnable(mInitScale,getWidth()/2,getHeight()/2));
}
break;
...
}
如今我們看一下後果
完成圖片縮小後,松手回彈後果
這個功效完成起來和下面誰人功效根本分歧,年夜家可以先試著本身寫一下。
同理,我們須要先界說一個mMaxOverScale作為縮小到最年夜值後,還能持續縮小到的值。
/**
* 最年夜溢出值
*/
private float mMaxOverScale;
//在onGlobalLayout中停止初始化
@Override
public void onGlobalLayout() {
...
//最年夜溢出值為最年夜值的5倍,可以隨便調
mMaxOverScale = mMaxScale * 5;
...
}
//在onScale中,修正以下代碼
@Override
public boolean onScale(ScaleGestureDetector detector) {
...
if ((scaleFactor > 1.0f && scale * scaleFactor < mMaxOverScale)
|| scaleFactor < 1.0f && scale * scaleFactor > mMinScale){
if (scale * scaleFactor > mMaxOverScale + 0.01f){
scaleFactor = mMaxOverScale / scale;
}
...
}
如許當我們圖片縮小至最年夜比例後還可以持續縮小,然後我們異樣須要在onTouch中的ACTION_UP中添加主動減少的功效
case MotionEvent.ACTION_UP:
//當手指抬起時,將mLastPointerCount置0,停滯滑動
mLastPointerCount = 0;
//假如以後圖片年夜小小於初始化年夜小
if (getScale() < mInitScale){
//主動縮小至初始化年夜小
post(new AutoScaleRunnable(mInitScale,getWidth()/2,getHeight()/2));
}
//假如以後圖片年夜小年夜於最年夜值
if (getScale() > mMaxScale){
//主動減少至最年夜值
post(new AutoScaleRunnable(mMaxScale,getWidth()/2,getHeight()/2));
}
break;
然後我們看一下後果
完成圖片的慣性滑動
要完成圖片的慣性滑動,我們須要借助VelocityTracker來幫我們檢測當我們手指分開圖片時的一個速度,然後依據這個速度和圖片的地位來挪用Scroller的fling辦法來盤算慣性滑動進程中的x和y的坐標
@Override
public boolean onTouch(View v, MotionEvent event) {
...
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
//初始化速度檢測器
mVelocityTracker = VelocityTracker.obtain();
if (mVelocityTracker != null){
//將以後的事宜添加到檢測器中
mVelocityTracker.addMovement(event);
}
//當手指再次點擊到圖片時,停滯圖片的慣性滑動
if (mFlingRunnable != null){
mFlingRunnable.cancelFling();
mFlingRunnable = null;
}
...
}
...
case MotionEvent.ACTION_MOVE:
...
//假如可滑動
if (isCanDrag){
if (getDrawable() != null){
if (mVelocityTracker != null){
//將以後事宜添加到檢測器中
mVelocityTracker.addMovement(event);
}
...
}
...
case MotionEvent.ACTION_UP:
//當手指抬起時,將mLastPointerCount置0,停滯滑動
mLastPointerCount = 0;
//假如以後圖片年夜小小於初始化年夜小
if (getScale() < mInitScale){
//主動縮小至初始化年夜小
post(new AutoScaleRunnable(mInitScale,getWidth()/2,getHeight()/2));
}
//假如以後圖片年夜小年夜於最年夜值
if (getScale() > mMaxScale){
//主動減少至最年夜值
post(new AutoScaleRunnable(mMaxScale,getWidth()/2,getHeight()/2));
}
if (isCanDrag){//假如以後可以滑動
if (mVelocityTracker != null){
//將以後事宜添加到檢測器中
mVelocityTracker.addMovement(event);
//盤算以後的速度
mVelocityTracker.computeCurrentVelocity(1000);
//獲得以後x偏向速度
final float vX = mVelocityTracker.getXVelocity();
//獲得以後y偏向的速度
final float vY = mVelocityTracker.getYVelocity();
mFlingRunnable = new FlingRunnable(getContext());
//挪用fling辦法,傳入控件寬高和以後x和y軸偏向的速度
//這裡獲得的vX和vY和scroller須要的velocityX和velocityY的負號正好相反
//所以傳入一個負值
mFlingRunnable.fling(getWidth(),getHeight(),(int)-vX,(int)-vY);
//履行run辦法
post(mFlingRunnable);
}
}
break;
case MotionEvent.ACTION_CANCEL:
//釋放速度檢測器
if (mVelocityTracker != null){
mVelocityTracker.recycle();
mVelocityTracker = null;
}
break;
/**
* 慣性滑動
*/
private class FlingRunnable implements Runnable{
private Scroller mScroller;
private int mCurrentX , mCurrentY;
public FlingRunnable(Context context){
mScroller = new Scroller(context);
}
public void cancelFling(){
mScroller.forceFinished(true);
}
/**
* 這個辦法重要是從onTouch中或獲得以後滑動的程度和豎直偏向的速度
* 挪用scroller.fling辦法,這個辦法外部可以或許主動盤算慣性滑動
* 的x和y的變更率,依據這個變更率我們便可以對圖片停止平移了
*/
public void fling(int viewWidth , int viewHeight , int velocityX ,
int velocityY){
RectF rectF = getMatrixRectF();
if (rectF == null){
return;
}
//startX為以後圖片右邊界的x坐標
final int startX = Math.round(-rectF.left);
final int minX , maxX , minY , maxY;
//假如圖片寬度年夜於控件寬度
if (rectF.width() > viewWidth){
//這是一個滑動規模[minX,maxX],概況見下圖
minX = 0;
maxX = Math.round(rectF.width() - viewWidth);
}else{
//假如圖片寬度小於控件寬度,則不許可滑動
minX = maxX = startX;
}
//假如圖片高度年夜於控件高度,同理
final int startY = Math.round(-rectF.top);
if (rectF.height() > viewHeight){
minY = 0;
maxY = Math.round(rectF.height() - viewHeight);
}else{
minY = maxY = startY;
}
mCurrentX = startX;
mCurrentY = startY;
if (startX != maxX || startY != maxY){
//挪用fling辦法,然後我們可以經由過程挪用getCurX和getCurY來取得以後的x和y坐標
//這個坐標的盤算是模仿一個慣性滑動來盤算出來的,我們依據這個x和y的變更可以模仿
//出圖片的慣性滑動
mScroller.fling(startX,startY,velocityX,velocityY,minX,maxX,minY,maxY);
}
}
關於startX,minX,maxX做一個說明
我們從圖中可以看出,以後圖片可滑動的一個區間就是右邊多出來的那塊區間,所以minX和maxX代表的是區間的最小值和最年夜值,startX就是屏幕右邊界的坐標值,我們可以想象成是startX在區間[minX,maxX]的挪動。Y軸偏向同理。
如今我們看一下後果
以上就是本文的全體內容,願望對年夜家進修Android軟件編程有所贊助。