有弹性的ScrollView

我是个新手,虽然说现在这已经算是过时的效果,但是我还是要学会到底是怎么实现的,于是我把我之前看到的,别人实现的半成品,拿过来搞懂了之后,复写了一遍,然后添加了可以左右弹性移动的部分。然后添加了几个getter/setter

import android.content.Context;
import android.graphics.Rect;
import android.view.MotionEvent;
import android.view.View;
import android.util.AttributeSet;
import android.widget.ScrollView;
import android.view.animation.TranslateAnimation;

public class BoundBackScrollView extends ScrollView {

    /**
     * original child
     * the content view to be moved
     */
    private View contentView;

    /**
     * used to save content view's left/right/top/bottom values
     */
    private Rect rect = new Rect();

    /**
     * move factor(if you move 100xp then the content view
     * will move 50xp, if you change the move factor to 1f
     * then will move 100xp)
     */
    private float MoveFactor = 0.5f;

    /**
     * animation duration
     * the length of time bound back animation
     */
    private int AnimDuration = 300;

    /**
     * is content view moved
     */
    private boolean IsMoved = false;

    /**
     * the start position
     */
    private float startY;
    private float startX;

    /**
     * bound mode
     */
    public enum BOUND_MODE{
        UPDOWN,
        LEFTRIGHT,
        BOTH
    }

    /**
     * default mode
     */
    private BOUND_MODE boundMode = BOUND_MODE.UPDOWN;


    public BoundBackScrollView(Context context) {
        super(context);
    }

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

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        if (getChildCount() > 0) {
            contentView = getChildAt(0);
        }
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        if (contentView == null)
            return;
        rect.set(contentView.getLeft(), contentView.getTop(),
                contentView.getRight(), contentView.getBottom());
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {

        if (contentView == null) {
            return super.dispatchTouchEvent(ev);
        }

        boolean isTouchOutOfThis = ev.getX() >= this.getWidth()
                || ev.getX() <= 0
                || ev.getY() >= this.getHeight()
                || ev.getY() <= 0;

        if (isTouchOutOfThis) {
            if (IsMoved) {
                boundBack();
            }
            return true;
        }

        int action = ev.getAction();
        switch (action) {

            case MotionEvent.ACTION_DOWN:
                startX = ev.getX();
                startY = ev.getY();
                break;

            case MotionEvent.ACTION_MOVE: //会被循环调用


                int deltaY = (int) (ev.getY() - startY);
                int deltaX = (int) (ev.getX() - startX);
                boolean shouldMove = deltaY > 0 || deltaX > 0;

                if (shouldMove) {
                    int offsetY = (int) (deltaY * MoveFactor);
                    int offsetX = (int) (deltaX * MoveFactor);
                    if(boundMode == BOUND_MODE.UPDOWN)
                    {
                        contentView.layout(rect.left, rect.top + offsetY,
                                rect.right, rect.bottom + offsetY);

                    }else if(boundMode == BOUND_MODE.LEFTRIGHT)
                    {
                        contentView.layout(rect.left + offsetX, rect.top,
                                rect.right + offsetX, rect.bottom);
                    }else{
                        contentView.layout(rect.left + offsetX, rect.top + offsetY,
                                rect.right + offsetX, rect.bottom + offsetY);
                    }

                    IsMoved = true;
                }

                break;

            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                boundBack();
                break;

        }
        return super.dispatchTouchEvent(ev);
    }

    private void boundBack() {
        if (!IsMoved)
            return;
        TranslateAnimation anim = null;
        if(boundMode == BOUND_MODE.UPDOWN) {
            anim = new TranslateAnimation(0, 0, contentView.getTop(),
                    rect.top);
        }else if(boundMode == BOUND_MODE.LEFTRIGHT){
            anim =  new TranslateAnimation(contentView.getLeft(), rect.left, 0,
                    0);
        }else{
            anim =  new TranslateAnimation(contentView.getLeft(), rect.left, contentView.getTop(),
                    rect.top);
        }
        anim.setDuration(AnimDuration);

        contentView.startAnimation(anim);
        contentView.layout(rect.left, rect.top, rect.right, rect.bottom);
        IsMoved = false;
    }


    public void setMoveFactor(float moveFactor){
        this.MoveFactor = moveFactor;
    }

    public float getMoveFactor(){
        return MoveFactor;
    }

    public void setAnimDuration(int AnimDuration){
        this.AnimDuration = AnimDuration;
    }

    public int getAnimDuration(){
        return AnimDuration;
    }

    public void setBoundMode(BOUND_MODE boundMode){
        this.boundMode = boundMode;
    }

    public BOUND_MODE getBoundMode(){
        return boundMode;
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值