Android仿微信朋友圈的查看圖片ImageView,縮放返弹,移動锈玉,回彈,下滑退出

點擊小圖片轉(zhuǎn)到圖片查看的頁面在Android開發(fā)中很常用到义起,抱著學(xué)習(xí)和分享的心態(tài)拉背,在這里寫下自己自定義的一個ImageView,可以實現(xiàn)類似微信朋友圈中查看圖片的功能和效果默终。

主要功能需求:

1.自由縮放椅棺,有最大和最小的縮放限制
2.若圖片沒充滿整個ImageView,則縮放過程將圖片居中
3.根據(jù)當前縮放的狀態(tài)齐蔽,雙擊放大兩倍或縮小到原來
4.當圖片尺寸超過ImageView所能展示两疚,圖片可以移動
5.移動以及縮放過程中,圖片不可脫離ImageView邊緣
6.縮放到離開ImageView邊緣含滴,自動回彈
7.沒有縮放狀態(tài)下诱渤,下滑圖片,背景色逐漸透明谈况,達到一段距離可以退出
8.若設(shè)置了退出動畫勺美,那么將圖片縮回到原來打開的位置递胧。

實現(xiàn)方式:

我們在這可以通過繼承ImageView,自己寫一個TouchImageView來實現(xiàn)赡茸,功能核心的實現(xiàn)涉及到Touch事件缎脾,因此需要重寫它的onTouchEvent方法,進行相應(yīng)處理坛掠。宏觀上說赊锚,就是點擊小圖片,然后進到新的Activiy屉栓,該Activity創(chuàng)建這個TouchImageView舷蒲,布局代碼和Activity代碼不再給出,可以根據(jù)需要自由使用友多。

對圖片的移動牲平、縮放、位置等的控制域滥,我們用Matrix這個類來實現(xiàn)纵柿,這是一個功能強大的類,這里簡單的介紹一下:

在這個功能里启绰,用的比較多的是它的這幾個方法昂儒,網(wǎng)上有很多解釋,這里簡單解釋一下委可,新手更容易理解渊跋。

首先介紹一下Matrix內(nèi)部的一個3x3矩陣,它用一個float[9]的數(shù)組來表示着倾,這里我們需要常用Matrix.getValues(float[] values)的方法來獲取最新的數(shù)組數(shù)據(jù)拾酝,從而知道現(xiàn)在圖片的放大倍數(shù)和坐標位置等。如(values[MTRANS_X],values[MTRANS_Y])表示圖片左上角的位移情況卡者,可以當做是當前這個點的坐標蒿囤,(0,0)時沒經(jīng)過位移,在左上角崇决。

Matrix.postScale(float sx, float sy)
Matrix.postScale(float sx, float sy, float px, float py)

這兩個方法是用來進行縮放材诽,第二個方法的后兩個參數(shù)是放大的中心點。每調(diào)用一次postScale恒傻,都是與之前的倍數(shù)相乘得到最終的放大倍數(shù)脸侥,如sx*Values[Matrix.MSCALE_X] ,所以在移動過程每次進入ACTION_MOVE體碌冶,先初始化一下matrix,確保是上一次操作后的prematrix涝缝,這樣得到的放大倍數(shù)才是正確的扑庞。這些地方讀代碼會理解更完整一點譬重。另外,需要提一下的是罐氨,postScale會產(chǎn)生一定的位移臀规,如果同時你要用postTranslate進行一些特定移動的話,可能需要消除postScale位移的影響栅隐,否則最終可能移動的位置不是你想要的塔嬉,我在代碼中也有體現(xiàn)這點。

Matrix.postTranslate(float dx, float dy)

這個方法進行圖片的位移租悄,dx和dy是相對現(xiàn)在位置的位移距離谨究,根據(jù)Android中的坐標表示,dx正值表示向右移泣棋,dy正值表示向下移胶哲。

另外給出一張簡單流程圖,希望有用潭辈。

程序代碼:

下面貼出完整代碼鸯屿,有點長

public class TouchImageView extends ImageView{
    
    //圖片的尺寸
    private float imgHeight = 0;
    private float imgWidth = 0;
    
    private Context context;
    
    //View的尺寸
    private int viewHeight = 0;
    private int viewWidth = 0;
    
    //圖片的縮放最大值
    private float maxHeight;
    private float maxWidth;
    private float minHeight;
    private float minWidth;
    
    //移動前兩指直接的距離
    private double beginDistance;
    private boolean isOnePointer = true;
    
    //下滑退出的控制變量
    private boolean canQuit = false;
    private boolean tryQuit = false;
    
    //圖片縮放時居中過程產(chǎn)生的位移量
    private float tempdy = 0;
    private float tempdx = 0;
    
    //兩指的中點坐標,用于設(shè)置縮放的中心點
    private float xMid,yMid; 
    //第一根手指按下的初始坐標
    private float xDown,yDown;
    
    //目前操作的Matrix對象
    private Matrix matrix = new Matrix();
    //上一次操作的Matrix對象
    private Matrix preMatrix = new Matrix();
    
    private boolean isMovePic = false;
    private boolean isZoomPic = false;
    
    //退出時需要縮放到的位置
    private int preWidth = 0;
    private int preHeight = 0;
    private int xLocation = -1;
    private int yLocation = -1;
    
    public TouchImageView(Context context) {
        super(context);
    }

    public TouchImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        setBackgroundColor(Color.BLACK);
        setScaleType(ScaleType.FIT_CENTER); //在沒有獲得View尺寸來進行initBitmap前把敢,先通過這個進行居中顯示
    }
    
    GestureDetector gestureDetector = new GestureDetector(getContext(), new GestureDetector.SimpleOnGestureListener() {
        
        @Override
        public boolean onSingleTapConfirmed(MotionEvent e) {//單擊事件
            return super.onSingleTapConfirmed(e);
        }

        @Override
        public boolean onDoubleTap(MotionEvent e) {//雙擊事件
            doubleClickZoom();
            return super.onDoubleTap(e);
        }
    });
    
    /**
     * 設(shè)置TouchImageView的尺寸寄摆,在onCreate階段展示圖片,需要手動設(shè)置
     * @param h
     * @param w
     */
    public void setViewSize(int h, int w){
        System.out.println("setViewSize");
        viewHeight = h;
        viewWidth = w;
        //獲得View尺寸后初始化圖片
        initBitmap();
        
    }
    
    //初始化圖片
    public void initBitmap(){ 
        System.out.println("initBitmap");
        preMatrix.reset(); //必須有修赞,否則會受上一張圖片的影響

        //縮放到寬與控件平齊
        float scaleX = (float) viewWidth / imgWidth;
        float scaleY = (float) viewHeight / imgHeight;
        float defaultScale = scaleX < scaleY ? scaleX : scaleY;
        preMatrix.postScale(defaultScale, defaultScale);
        //平移到居中
        float tranY = (viewHeight - imgHeight*defaultScale)/2;
        preMatrix.postTranslate(0, tranY);
        
        //獲取最大最小縮放尺寸
        maxHeight = imgHeight * defaultScale * 3;
        maxWidth = imgWidth * defaultScale * 3;
        minHeight = imgHeight* defaultScale / 2;
        minWidth = imgWidth * defaultScale / 2;     
        setScaleType(ScaleType.MATRIX);
        setImageMatrix(preMatrix);
    }
    
    
    @Override
    public void setImageBitmap(Bitmap bm){  //先執(zhí)行這個方法婶恼,再執(zhí)行initBitmap 
        super.setImageBitmap(bm);   
        imgWidth = bm.getWidth();
        imgHeight = bm.getHeight();
        System.out.println("setImageBitmap: imgWidth="+imgWidth);
        System.out.println("setImageBitmap: TimgHeightH="+imgHeight);
        if(viewHeight!=0 && viewWidth!=0) {
            initBitmap();
        } else{
            viewHeight = getHeight();
            viewWidth = getWidth();
            if(viewHeight!=0 && viewWidth!=0){
                initBitmap();
            }
        }
    }
    
    @Override
    public boolean onTouchEvent(MotionEvent event){
        gestureDetector.onTouchEvent(event);
        switch(event.getAction() & MotionEvent.ACTION_MASK){
        case MotionEvent.ACTION_DOWN:
            matrix.set(preMatrix); //時序問題,doubleClickZoom方法中設(shè)置該項時榔组,前面會通過ACTION_UP將preMatrix設(shè)置成matrix熙尉,故提前設(shè)置該項
            xDown = event.getX();
            yDown = event.getY();
            break;
        case MotionEvent.ACTION_POINTER_DOWN:
            isOnePointer = false;
            if(!isMovePic){         // 第二根手指放下時可能已經(jīng)進入了移動模式,已經(jīng)進入移動模式則不激發(fā)縮放模式
                isZoomPic = true;
            }
            if(event.getPointerCount() == 2) {  // 兩根手指才進行測量與計算距離搓扯,避免縮放過程中第三根手指放下激發(fā)重新測量
                float downX1 = event.getX(0);
                float downX2 = event.getX(1);
                float downY1 = event.getY(0);
                float downY2 = event.getY(1);
                float xDistance = Math.abs(downX1-downX2);
                float yDistance = Math.abs(downY1-downY2);
                xMid = (downX1+downX2)/2;
                yMid = (downY1+downY2)/2;
                beginDistance = Math.sqrt(xDistance * xDistance + yDistance * yDistance);
            }
            break;  
        case MotionEvent.ACTION_MOVE:
            if(event.getPointerCount() == 1) {
                if(!isZoomPic) {
                    float moveX = event.getX();
                    float moveY = event.getY();
                    if(Math.abs(moveX - xDown)>10 || Math.abs(moveY - yDown)>10){
                        isZoomPic = false;
                        isMovePic = true;
                    }                   
                }
                isOnePointer = true;
            } 
            else if(event.getPointerCount() == 2){
                if(!isMovePic){
                    isZoomPic = true;
                    isMovePic = false;                      
                }
                isOnePointer = false;
            } 
            else {
                isZoomPic = false;
                isMovePic = false;
                isOnePointer = false;
            }
            if(isZoomPic && !isOnePointer) { //雙指縮放圖片
                matrix.set(preMatrix);
                float moveX1 = event.getX(0);
                float moveX2 = event.getX(1);
                float moveY1 = event.getY(0);
                float moveY2 = event.getY(1);
                float xDistance2 = Math.abs(moveX1-moveX2);
                float yDistance2 = Math.abs(moveY1-moveY2);
                //移動后兩指間的距離
                double moveDistance = Math.sqrt(xDistance2 * xDistance2 + yDistance2 * yDistance2);                     
                float zoomScale = (float) ((float)moveDistance / beginDistance);
                matrix.postScale(zoomScale, zoomScale,xMid,yMid);               
                float[] values =  new float[9];             
                //縮放最大最小的限制
                limitZoomSize(values);
                //放大或縮小時检痰,若高或?qū)挍]有填充完控件則過程需要居中
                placeXCenter(values);
                placeYCenter(values);
                
                //檢查圖片邊緣有沒離開邊界,返回需要移動的位移量
                float dx = checkXBorder(values, 0);
                float dy = checkYBorder(values, 0);
                matrix.postTranslate(dx, dy);   
                setImageMatrix(matrix);             
            } 
            if(isMovePic && isOnePointer){ //單手指移動圖片
                matrix.set(preMatrix);
                float moveX = event.getX();
                float moveY = event.getY();
                //計算位移量
                float dy = moveY - yDown;
                float dx = moveX - xDown;
                float[] values =  new float[9];
                quitViewPicture(values,dx,dy);
                //檢查圖片邊緣有沒離開邊界锨推,返回需要移動的位移量   
                dx = checkXBorder(values, dx);
                dy = checkYBorder(values, dy);          
                matrix.postTranslate(dx, dy);
                setImageMatrix(matrix);
            }
            break;
        case MotionEvent.ACTION_UP:
            float[] values =  new float[9]; 
            if(tryQuit) {
                checkQuit(values);
            } else {
                //縮小離開屏幕邊緣時铅歼,松手自動放大到屏幕邊緣
                autoMatchParent(values);
            }
            preMatrix.set(matrix);  
            isOnePointer = true;
            isMovePic = false;  
            isZoomPic = false;
            //將前面居中過程產(chǎn)生的位移量置0
            tempdy = 0;
            tempdx = 0;             
            tryQuit = false;
            break;
        }
        return true;
    }
    
    
    //下滑退出操作,松手時是否達到可以退出的條件(位移量)
    public void checkQuit(float[] values) {     
        matrix.getValues(values);
        if(canQuit) {
            if(preWidth != 0 && preHeight != 0 && xLocation != -1 && yLocation != -1) {
                setBackgroundColor(Color.argb(0, 0, 0, 0));
                float toScale;
                if(preWidth > preHeight) {
                    toScale = preWidth / (values[Matrix.MSCALE_X]*imgWidth);
                } else {
                    toScale = preHeight / (values[Matrix.MSCALE_Y]*imgHeight);
                }
                matrix.getValues(values);
                float dx = xLocation - values[Matrix.MTRANS_X];
                float dy = yLocation - values[Matrix.MTRANS_Y];
                setMyAnimation(dx,dy,toScale,toScale);
            }
            else {
                AcManager.getAcManager().popActivity((Activity)context);
            }
            
        } 
        else {
            float scale = getWidth()/(values[Matrix.MSCALE_X] * imgWidth);
            matrix.postScale(scale,scale);
            placeXCenter(values);
            placeYCenter(values);
            setImageMatrix(matrix);
        }
    }
    
    //當圖片未縮放狀態(tài)時换可,向下滑可以退出圖片瀏覽
    public void quitViewPicture(float[] values, float dx, float dy){
        matrix.getValues(values);
        float beforeZoom = values[Matrix.MTRANS_Y];
        if((imgWidth * values[Matrix.MSCALE_X] <= getWidth()) && (imgHeight * values[Matrix.MSCALE_Y] <= getHeight()) ) {
            if(dy > 0) {
                if(dy>5) { //防止雙擊放大時被認為是想退出
                    tryQuit = true;
                }
                // 設(shè)置背景色透明程度
                int alpha = 255- (int) ((255 * dy)/getHeight());
                setBackgroundColor(Color.argb(alpha, 0, 0, 0));
                //float scale = values[Matrix.MSCALE_X] - dy * values[Matrix.MSCALE_X] / getHeight(); //目標縮放尺寸
                float scale = 1 - dy  / getHeight(); //需要Post的縮放尺寸          
                matrix.postScale(scale, scale);
                matrix.getValues(values);
                float dyZoom = beforeZoom - values[Matrix.MTRANS_Y]; //縮小過程會產(chǎn)生一定回縮的位移
                float dxZoom = getWidth()/2 -imgWidth * values[Matrix.MSCALE_X]/2 ;
                matrix.postTranslate(dx + dxZoom, dy + dyZoom);     
                //placeXCenter(values);
                if(dy > 200) {
                    canQuit = true;
                } else {
                    canQuit = false;
                }
            }
        }
    }
    
    //雙擊放大一倍
    public void doubleClickZoom(){
        matrix.set(preMatrix);
        float[] values = new float[9];
        matrix.getValues(values);
        float currentWidth = values[Matrix.MSCALE_X] * imgWidth;
        if(currentWidth > getWidth()+ 5) {
            float scale = getWidth()/currentWidth;
            matrix.postScale(scale,scale);
            placeXCenter(values);
            placeYCenter(values);
            setImageMatrix(matrix);
            preMatrix.set(matrix);
        } else {            
            matrix.postScale(2.0f,2.0f);
            matrix.getValues(values);
            float dx = getWidth()/2 - (imgWidth*values[Matrix.MSCALE_X]/2 + values[Matrix.MTRANS_X]);
            float dy = getHeight()/2 - (imgHeight*values[Matrix.MSCALE_Y]/2 + values[Matrix.MTRANS_Y]);
            matrix.postTranslate(dx, dy);
            setImageMatrix(matrix);
            preMatrix.set(matrix);
        }
    }
    
    //縮小離開屏幕邊緣時椎椰,松手自動放大到屏幕邊緣
    public void autoMatchParent(float[] values) {
        matrix.getValues(values);
        float currentHeight = values[Matrix.MSCALE_Y] * imgHeight;
        float currentWidth = values[Matrix.MSCALE_X] * imgWidth;
        if(currentHeight < (getHeight()-5) && currentWidth < (getWidth()-5)) {
            float scale = getWidth()/currentWidth;
            matrix.postScale(scale,scale);
            placeXCenter(values);
            placeYCenter(values);
            setImageMatrix(matrix);
        }
    }
    
    //縮放最大最小的限制
    public void limitZoomSize(float[] values) {
        matrix.getValues(values);
        if(values[Matrix.MSCALE_Y] * imgHeight > maxHeight || values[Matrix.MSCALE_X] * imgWidth > maxWidth) { 
            float scaleX = maxWidth / (imgWidth*values[Matrix.MSCALE_X]);
            float scaleY = maxHeight / (imgHeight*values[Matrix.MSCALE_Y]);
            matrix.postScale(scaleX, scaleY,xMid,yMid); 
        } else if(values[Matrix.MSCALE_Y] * imgHeight < minHeight || values[Matrix.MSCALE_X] * imgWidth < minWidth) {
            float scaleX = minWidth / (imgWidth*values[Matrix.MSCALE_X]);
            float scaleY = minHeight / (imgHeight*values[Matrix.MSCALE_Y]);
            matrix.postScale(scaleX, scaleY,xMid,yMid);
        }
    }
    
    //X方向上縮放過程中若未充滿控件寬度,那么居中縮放
    public void placeXCenter(float[] values){
        //獲得最新的values
        matrix.getValues(values);
        //圖片橫向能完全顯示時沾鳄,需要居中
        if(imgWidth*values[Matrix.MSCALE_X] < getWidth() + 1) {
            System.out.println("placeXCenter:橫向正在居中");
            float dx = getWidth()/2 - (imgWidth*values[Matrix.MSCALE_X]/2 + values[Matrix.MTRANS_X]);
            tempdx = dx;
            matrix.postTranslate(dx, 0);
        }
        else {                                              
            matrix.postTranslate(tempdx, 0);    //圖像的橫向向從未充滿屏幕到充滿屏幕過程中慨飘,由于居中會產(chǎn)生的一定位移tempdx,需要補上,否則會跳變            
        }
    }
    
    //Y方向上縮放過程中若未充滿控件寬度瓤的,那么居中縮放
    public void placeYCenter(float[] values){
        //獲得最新的values
        matrix.getValues(values);
        //圖片縱向能完全顯示時休弃,需要居中
        if(imgHeight*values[Matrix.MSCALE_Y] < getHeight() + 1) {
            System.out.println("placeYCenter:縱向正在居中");
            float dy = getHeight()/2 - (imgHeight*values[Matrix.MSCALE_Y]/2 + values[Matrix.MTRANS_Y]);
            tempdy = dy;
            matrix.postTranslate(0, dy);                
        } else {    
            matrix.postTranslate(0, tempdy);    //圖像的縱向從未充滿屏幕到充滿屏幕過程中,由于居中會產(chǎn)生的一定位移tempdy圈膏,需要補上塔猾,否則會跳變
        }
    }
    
    //X方向上的邊緣檢測
    public float checkXBorder(float[] values, float dx) {
        //獲得最新的values
        matrix.getValues(values);
        if(imgWidth*values[Matrix.MSCALE_X] < getWidth()){ //圖片寬度小于控件寬度時,不移動
            dx = 0;
        }
        else if(values[Matrix.MTRANS_X]+dx>0) { //圖片右移后若離開控件左邊緣稽坤,那么將圖片移動對齊到左邊緣
            dx = -values[Matrix.MTRANS_X];
        } 
        else if(imgWidth*values[Matrix.MSCALE_X]+values[Matrix.MTRANS_X]+ dx< getWidth()){ //圖片左移后若離開控件右邊緣丈甸,那么將圖片移動對齊到右邊緣
            dx = - imgWidth*values[Matrix.MSCALE_X] + getWidth() - values[Matrix.MTRANS_X];
        }
        return dx;
    }
    
    //Y方向上的邊緣檢測
    public float checkYBorder(float[] values, float dy) {       
        //獲得最新的values
        matrix.getValues(values);
        if(imgHeight*values[Matrix.MSCALE_Y] < getHeight()){ //圖片高度小于控件寬度時,不移動
            dy = 0;
        }
        else if(values[Matrix.MTRANS_Y]+dy>0) { //圖片下移后若離開控件上邊緣尿褪,那么將圖片移動對齊到上邊緣
            dy = -values[Matrix.MTRANS_Y];
        } 
        else if(imgHeight * values[Matrix.MSCALE_Y] + values[Matrix.MTRANS_Y] + dy < getHeight()){ //圖片上移后若離開控件下邊緣睦擂,那么將圖片移動對齊到下邊緣
            dy = - imgHeight*values[Matrix.MSCALE_Y] + getHeight() - values[Matrix.MTRANS_Y];
        }
        return dy;
    }

    /**
     * 設(shè)置退出動畫需要縮放到的位置 , 需要設(shè)置才有這個效果
     * @param x 相對屏幕的絕對位置坐標x
     * @param y 相對屏幕的絕對位置坐標y
     * @param height
     * @param width
     */
    public void setQuitAnimation(int x, int y, int height, int width) {
        preWidth = width;
        preHeight = height;
        xLocation = x;
        yLocation = y;
    }
        
    public void setMyAnimation (float toTranslateX, float toTranslateY, float toScaleX, float toScaleY) {
        
        PropertyValuesHolder translateX = PropertyValuesHolder.ofFloat("translateX", 0.0f,toTranslateX);
        PropertyValuesHolder translateY = PropertyValuesHolder.ofFloat("translateY", 0.0f,toTranslateY);
        PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1.0f,toScaleX);
        PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 1.0f,toScaleY);
        ValueAnimator animator = ValueAnimator.ofPropertyValuesHolder(translateX,translateY,scaleX,scaleY);
        animator.addUpdateListener ( new MyAnimatorListener ( getImageMatrix() ) );
        animator.setDuration ( 150 );
        animator.setInterpolator ( new LinearInterpolator () );
        animator.setStartDelay ( 0 );
        animator.start ();
        animator.addListener(new AnimatorListener(){

            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                AcManager.getAcManager().popActivity((Activity)context);
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
            
        });
    }
    
    class MyAnimatorListener implements AnimatorUpdateListener {
        private Matrix mMatrix;
        
        public MyAnimatorListener(Matrix matrix) {
                mMatrix = new Matrix(matrix);
            }
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            float dx =  (float) animation.getAnimatedValue("translateX"); 
            float dy =  (float) animation.getAnimatedValue("translateY"); 
            float scaleX =  (float) animation.getAnimatedValue("scaleX"); 
            float scaleY =  (float) animation.getAnimatedValue("scaleY"); 
            Matrix matrix = new Matrix(mMatrix);
            float[] values = new float[9];
            matrix.getValues(values);
            float beforeX = values[Matrix.MTRANS_X];
            float beforeY = values[Matrix.MTRANS_Y];
            matrix.postScale(scaleX,scaleY);
            matrix.getValues(values);
            matrix.postTranslate(beforeX - values[Matrix.MTRANS_X] , beforeY - values[Matrix.MTRANS_Y]);
            matrix.postTranslate(dx, dy);
            setImageMatrix(matrix);
        }
        
    }
    
    /**
     * 獲取當前圖片的高
     * @return
     */
    public float getCurrentImageHeight(){
        float[] values = new float[9];
        matrix.getValues(values);
        return imgHeight*values[Matrix.MSCALE_Y];   
    }
    
    /**
     * 獲取當前圖片的寬
     * @return
     */
    public float getCurrentImageWidth(){
        float[] values = new float[9];
        matrix.getValues(values);
        return imgWidth*values[Matrix.MSCALE_X];    
    }

}

圖片退出動畫

然后如果要在onCreate里設(shè)置圖片的話,由于此時是獲得的ImageView的尺寸是0茫多,所以要在Activity的onCreate中用ViewTreeObserver來獲取尺寸:

ViewTreeObserver viewTreeObserver = pic.getViewTreeObserver();  
        viewTreeObserver.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {  
  
                    @Override  
                    public void onGlobalLayout() {  
                        pic.setViewSize(pic.getHeight(),pic.getWidth());
                    }  
        });

如果要設(shè)置下滑退出祈匙,縮回到原來小圖片位置的動畫,需要在Activity中設(shè)置此項:

//xLocation和yLocation是原來的小圖片相對于屏幕的坐標
//preHeight和preWidth是小圖片的高和寬
pic.setQuitAnimation(xLocation, yLocation, preHeight, preWidth);

由于傳入的是相對屏幕的坐標天揖,所以TouchImageView的大小也要是整個屏幕夺欲,這樣動畫才會跑到正確的位置。在TouchImageView對應(yīng)的Activity中設(shè)置:

getWindow().setFlags(WindowManager.LayoutParams. FLAG_FULLSCREEN , WindowManager.LayoutParams. FLAG_FULLSCREEN); 

另外今膊,需要把TouchImageView對應(yīng)的Activity的背景色設(shè)置為透明些阅,在AndroidManifest.xml文件中對該Activity設(shè)置:

android:theme="@android:style/Theme.Translucent.NoTitleBar"

最后最后,其實代碼中已經(jīng)有比較多的注釋了斑唬,大家可以看看市埋。希望通過寫文章,能加深自己的理解以及發(fā)現(xiàn)自己的錯誤恕刘,在學(xué)習(xí)的道路上不斷前行缤谎。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市褐着,隨后出現(xiàn)的幾起案子坷澡,更是在濱河造成了極大的恐慌,老刑警劉巖含蓉,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件频敛,死亡現(xiàn)場離奇詭異,居然都是意外死亡馅扣,警方通過查閱死者的電腦和手機斟赚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來差油,“玉大人拗军,你說我怎么就攤上這事。” “怎么了发侵?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵侈咕,是天一觀的道長。 經(jīng)常有香客問我器紧,道長,這世上最難降的妖魔是什么楼眷? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任铲汪,我火速辦了婚禮,結(jié)果婚禮上罐柳,老公的妹妹穿的比我還像新娘掌腰。我一直安慰自己,他們只是感情好张吉,可當我...
    茶點故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布齿梁。 她就那樣靜靜地躺著,像睡著了一般肮蛹。 火紅的嫁衣襯著肌膚如雪勺择。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天伦忠,我揣著相機與錄音省核,去河邊找鬼。 笑死昆码,一個胖子當著我的面吹牛气忠,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播赋咽,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼旧噪,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了脓匿?” 一聲冷哼從身側(cè)響起淘钟,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎亦镶,沒想到半個月后日月,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡缤骨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年爱咬,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片绊起。...
    茶點故事閱讀 40,872評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡精拟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蜂绎,我是刑警寧澤栅表,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站师枣,受9級特大地震影響怪瓶,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜践美,卻給世界環(huán)境...
    茶點故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一洗贰、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧陨倡,春花似錦敛滋、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至杂曲,卻和暖如春庶艾,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背擎勘。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工落竹, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人货抄。 一個月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓述召,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蟹地。 傳聞我的和親對象是個殘疾皇子积暖,可洞房花燭夜當晚...
    茶點故事閱讀 45,876評論 2 361

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,331評論 25 707
  • 手勢圖片控件 PinchImageView 點擊圖片框架 photoView packagecom.example...
    Ztufu閱讀 734評論 0 1
  • 基礎(chǔ)儲備 在 ImageView 中有一個成員變量mDrawMatrix,這個變量是Matrix(矩陣)類型,我們...
    Lstone閱讀 3,150評論 0 5
  • CSDN博客 img cquwentao android matrix 最全方法詳解與進階(完整篇) 發(fā)表于201...
    北風(fēng)知我意閱讀 4,825評論 0 0
  • 如果突然失去目前的工作或者主要收入來源,你還能靠什么生存下去怪与? 如果失去目前的工作 1.我可以很快找到一份待遇相當...
    梓毓爸閱讀 205評論 0 1