Android 圖片平移隨記 GuidePagerDemo

Pm需求:單張背景圖做平移,至圖片的最左移動至最右邊,ImageView本身沒有什么變化,類似Android的桌面單張長圖的模式。

想法:

  • 需要達(dá)成需求,等比縮放后圖的寬度一定要大于屏幕寬度,否則就沒有效果
  • 畫一個保存圖片區(qū)域的矩形 , 再利用矩陣對矩形的Translate進(jìn)行變換
  • 利用ValueAnimator做成動畫效果即可

//應(yīng)該用如下方法才是創(chuàng)建Matrix對象
Matrix matrix = new Matrix ( mImage.getImageMatrix () );

一、先將XML中的ImageView的scaleType設(shè)置成matrix

使用RectF畫出需要存放圖片的矩形區(qū)域
// 存放圖片區(qū)域的矩形
RectF rectF = new RectF(img.getDrawable().getBounds());
// 圖片寬高
float dw = rectF.width();
float dh = rectF.height();
// 控件寬高
int width = imgBg.getWidth();
int height = imgBg.getHeight();
//初始化矩陣值
imgBg.setImageMatrix(new Matrix());
//獲取矩陣
Matrix matrix = imgBg.getImageMatrix();
//縮放比例
float value = height / dh;
// 縮放變換,按照比例放大,使圖片高度等于控件高度
matrix.postScale(value, value);
// 矩陣縮放映射到存放圖片區(qū)域的矩形
matrix.mapRect(rectF);
// 移動圖片到坐標(biāo)原點
matrix.postTranslate(0, 0);
// 將變換應(yīng)用到圖片
imgBg.setImageMatrix(matrix);

注意:

  • postTranslate是指在setScale后平移(preTranslate是在setScale前),他們參數(shù)是平移的距離,而不是平移目的地的坐標(biāo)。

二、設(shè)置位移動畫

位移動畫的移動距離為圖片對當(dāng)前屏幕縮放后的真實寬度減去屏幕(或者當(dāng)前場景下ImageView寬度)

setTranslateAnimation(imgBg, -(dw * value - screenWidth), 0);

動畫的添加:

public void setTranslateAnimation(final ImageView imgBg, float translateX, float translateY) {
    Matrix matrix = imgBg.getImageMatrix();
    float[] startMatrixValue = new float[9];
    float[] endMatrixValue = new float[9];
    // 獲取矩陣的初始值
    matrix.getValues(startMatrixValue);
    // 對矩陣進(jìn)行變換
    matrix.postTranslate(translateX, translateY);
    // 獲取變換后的值
    matrix.getValues(endMatrixValue);
    ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
    animator.addUpdateListener(new TransXAnimatorListener(imgBg, startMatrixValue, endMatrixValue));
    animator.setDuration(4000);
    animator.setTarget(imgBg);
    // 設(shè)置插值器 LinearInterpolator為勻速效果
    animator.setInterpolator(new LinearInterpolator());
    animator.start();
}

三、設(shè)置好初始狀態(tài)的矩陣和最終狀態(tài)的矩陣及變換動畫

class TransXAnimatorListener implements ValueAnimator.AnimatorUpdateListener {

    private float[] mStartMatrixValue;
    private float[] mEndMatrixValue;
    private float[] mInterpolateMatrixValue; // 矩陣變換動畫過程中間值
    private Matrix mMatrix;
    private ImageView imgBg;

    public TransXAnimatorListener(final ImageView imgBg, float[] startMatrixValue, float[] endMatrixValue) {
        this.mStartMatrixValue = startMatrixValue;
        this.mEndMatrixValue = endMatrixValue;
        this.imgBg = imgBg;
        mInterpolateMatrixValue = new float[9];
        mMatrix = imgBg.getImageMatrix();
    }

    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        float animatedValue = (float) animation.getAnimatedValue();
        // 根據(jù)動畫當(dāng)前進(jìn)度設(shè)置矩陣的值
        for (int i = 0; i < 9; i++) {
            mInterpolateMatrixValue[i] = mStartMatrixValue[i]
                    + (mEndMatrixValue[i] - mStartMatrixValue[i]) * animatedValue;
        }
        mMatrix.setValues(mInterpolateMatrixValue);
        imgBg.setImageMatrix(mMatrix);
        // setImageMatrix() 不一定會調(diào)用invalidate(),此處手動調(diào)用即可,
        // 或者為了避免重復(fù)繪制也可以參考setImageMatrix()源碼進(jìn)行改進(jìn)
        imgBg.invalidate();
    }
}

此處onAnimationUpdate方法內(nèi)矩陣變換參考:
籬開羅 - 自定義可旋轉(zhuǎn)、平移、縮放的ImageView 中的 [動畫技巧]

四、后續(xù)優(yōu)化

測試過程中放一些分辨率高的圖片的時候發(fā)現(xiàn)出現(xiàn)卡頓,使用bitmap壓縮的話在壓縮過程中會出現(xiàn)短時間的空白屏

  • 這里使用Fresco的SimpleDraweeView進(jìn)行替換當(dāng)前的ImageView
  • 添加Viewpager和Indicator效果,完成需求

也有使用過Glide去加載并簡化,不過效果會有些問題,還需要再度完善,新手一枚還需要多多練習(xí)。

Demo已放在上Github,如有需要的盆友可以看一下,互相交流~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容