Newer
Older
dxcgt / app / src / main / java / com / smartdot / cgt / view / FlingView.java
wangxitong on 6 Apr 2021 7 KB first commit
package com.smartdot.cgt.view;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.Transformation;

/**
 * 图片浏览View
 */
public class FlingView extends View implements OnGestureListener {
    public abstract class OnIndexChange {
        public abstract void onIndexChanged(int nowIndex);
    }

    private OnIndexChange onIndexChange;

    private Bitmap bitmap;

    private Bitmap nBitmap;

    private Bitmap fBitmap;

    private int OffsetX = 0;

    private int OffsetY = 0;

    private int position = 0;

    int mLastFlingX = 0;

    boolean OffsetRight = false;

    private Bitmap[] bitmaps;

    public OnIndexChange getOnIndexChange() {
        return onIndexChange;
    }

    public void setOnIndexChange(OnIndexChange onIndexChange) {
        this.onIndexChange = onIndexChange;
    }

    public int getPosition() {
        return position;
    }

    public void setPosition(int position) {
        if (this.position != position) {
            this.position = position;
            bitmap = getBitmap(position);
            if (position < bitmaps.length - 1) {
                nBitmap = getBitmap(position + 1);
            }
            if (position > 0) {
                fBitmap = getBitmap(position - 1);
            }
            invalidate();
        }
    }

    public Bitmap[] getBitmaps() {
        return bitmaps;
    }

    public void setBitmaps(Bitmap[] bitmaps) {
        this.bitmaps = bitmaps;
        bitmap = getBitmap(position);
        if (position < bitmaps.length - 1) {
            nBitmap = getBitmap(position + 1);
        }
        if (position > 0) {
            fBitmap = getBitmap(position - 1);
        }
        invalidate();
    }

    public FlingView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public void draw(Canvas canvas) {
        Paint p = new Paint();
        canvas.drawColor(Color.BLACK);
        if (OffsetX < 0) {
            if (nBitmap != null) {
                Rect rectTemp = new Rect(this.getWidth() + 15 + OffsetX,
                        0,
                        this.getWidth() + 15 + OffsetX + this.getWidth(),
                        nBitmap.getHeight()* this.getWidth()/nBitmap.getWidth());
                canvas.drawBitmap(nBitmap, null, rectTemp, p);
            }
        } else if (OffsetX > 0) {
            if (fBitmap != null) {
                Rect rectTemp = new Rect(-this.getWidth() - 15 + OffsetX,
                        0,
                        -this.getWidth() - 15 + OffsetX + this.getWidth(),
                        fBitmap.getHeight() * this.getWidth()/fBitmap.getWidth());
                canvas.drawBitmap(fBitmap, null, rectTemp, p);
            }
        }
        if (bitmap != null) {
            Rect rectTemp = new Rect(OffsetX,
                    OffsetY,
                    OffsetX + this.getWidth(),
                    OffsetY + bitmap.getHeight()*this.getWidth()/bitmap.getWidth());
            canvas.drawBitmap(bitmap, null, rectTemp, p);
        }
    }

    public void handleScroll(int deltaX) {
        if (deltaX > 0) {
            OffsetX -= -deltaX;
        } else {
            OffsetX += deltaX;
        }
        invalidate();
    }

    // 标记为可以切换到下一张
    boolean flag = false;

    // 标记为需要向右滑动
    boolean flag1 = false;

    // 标记为需要向左滑动
    boolean flag2 = false;

    private GestureDetector myGesture = new GestureDetector(this);

    class MyAnimation extends Animation {

        private int temp;

        @Override
        public void initialize(int width, int height, int parentWidth, int parentHeight) {
            temp = OffsetX;
            super.initialize(width, height, parentWidth, parentHeight);
            setDuration(500);
            setFillAfter(true);
            setInterpolator(new LinearInterpolator());
        }

        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            // Log.i("bb", "OffsetX==>"+OffsetX);
            // 需要滑动图片时根据方向来变换OffsetX大小
            if (flag) {
                if (temp > 0) {
                    OffsetX = (int) ((FlingView.this.getWidth() + 15 - temp) * interpolatedTime + temp);
                } else {
                    OffsetX = (int) ((-FlingView.this.getWidth() - 15 - temp) * interpolatedTime + temp);
                }
                // 不需要变换的情况
            } else {
                OffsetX = (int) (temp * (1 - interpolatedTime));
            }

            invalidate();
        }
    }

    // 动画结束后需要做一些工作
    @Override
    protected void onAnimationEnd() {
        if (flag1) {
            nBitmap = bitmap;
            bitmap = fBitmap;
            fBitmap = null;
            position = position - 1;
        } else if (flag2) {
            fBitmap = bitmap;
            bitmap = nBitmap;
            nBitmap = null;
            position = position + 1;
        }
        flag1 = false;
        flag2 = false;
        OffsetX = 0;
        if (fBitmap == null && OffsetX == 0) {
            if (position > 0) {
                fBitmap = getBitmap(position - 1);
            }

        } else if (nBitmap == null && OffsetX == 0) {
            if (position < bitmaps.length - 1) {
                nBitmap = getBitmap(position + 1);
            }
        }
        clearAnimation();
        flag = false;
        if (onIndexChange != null) {
            onIndexChange.onIndexChanged(position);
        }
    }

    public void startFling(int paramFloat1) {
        if (OffsetX > this.getWidth() / 3) {
            if (fBitmap != null) {
                flag = true;
                flag1 = true;
            }
        } else if (OffsetX < -this.getWidth() / 3) {
            if (nBitmap != null) {
                flag = true;
                flag2 = true;
            }
        }
        // 开始动画效果
        startAnimation(new MyAnimation());
        invalidate();

    }

    /**
     * 获得当前位置的图片
     * 
     * @param currentPos
     * @return
     */
    public Bitmap getBitmap(int currentPos) {
        if (currentPos > bitmaps.length - 1) {
            return null;
        }
        Bitmap currBitmap = bitmaps[currentPos];
        OffsetX = 0;
        OffsetY = 0;

        return currBitmap;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        switch (event.getAction()) {
        case MotionEvent.ACTION_UP:
            this.startFling(0);
            break;
        }
        myGesture.onTouchEvent(event);
        return true;
    }

    @Override
    public boolean onDown(MotionEvent e) {
        return false;
    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        this.startFling((int) -velocityX);
        return true;
    }

    @Override
    public void onLongPress(MotionEvent e) {
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        this.handleScroll(-1 * (int) distanceX);
        return true;
    }

    @Override
    public void onShowPress(MotionEvent e) {
    }

    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        return false;
    }
}