EdgeEffect的使用(在自定义ScrollView中使用)

文章目录

      • 前言
      • EdgeEffect是什么
      • EdgeEffect的一些方法说明
      • EdgeEffect在项目中的使用说明
        • 1 初始化配置
        • 3 状态控制
        • 4 绘制效果
      • 总结

前言

在写OverScroller使用(自定义一个ScrollView)的文章时,觉得EdgeEffect的使用有必要单独提出来做说明,主要是在一些可以滑动或放缩的自定义ViewGroup类控件中经常用到,并且是用来提示用户已经滑动到边界的。比较常见的例子就是ScrollView,当滑动到边界时就会在边界延申出一部分颜色弧形边块。本文代码例子(OverScroller使用)中就是使用EdgeEffect类来实现滑动边界提醒的。

git项目: https://gitee.com/guaishoun/over_scroller_edge_effect.git

EdgeEffect是什么

EdgeEffect英文直译就边界效果,用于在可滑动的控件中提示用户已经滑动到边界了。EdgeEffect是通过控制边界状态来控制绘制的,主要状态有拉onPull、碰撞速度吸收onAbsorb、释放onRelease这三种状态,然后在绘制中传入canvas绘制边界效果,其中控制状态主要还是根据onTouchEvent触摸事件处理来决定。所以分三步使用EdgeEffect:初始化配置、状态控制、绘制

EdgeEffect的一些方法说明

主要关注拉onPull、碰撞速度吸收onAbsorb、释放onRelease这三种状态及绘制draw。

onPull

/**
* 拉状态
* deltaDistance 高度颜色深浅,范围0-1,注意是比例,比例越大边界效果越完整,颜色越深
* displacement  效果弧形的中心点,范围0-1,中心点位于设置的宽度的位置
**/
public void onPull(float deltaDistance, float displacement);

onAbsorb

/**
*撞击边界时的状态,在配合fling甩动使用,惯性滑动到边界时吸收速度显示边界效果
* Velocity 撞击时剩余的速度
*/
public void onAbsorb(int velocity);

onRelease

/**
* 当拉状态结束时,使用释放状态
*/
public void onRelease()

draw

/**
*传入canva绘制边界效果
* 1 要放在最后绘制,比如放到GroupView的onDrawForeground(Canvas canvas)中绘制
* 2 默认是绘制在未变换坐标上画的,也就是控件top位置,如果要画到其他位置需要自己的变换坐标来绘制
* 3 效果没有finish的话,自己需要Invalidate()触发重画
**/
public boolean draw(Canvas canvas)

EdgeEffect在项目中的使用说明

1 初始化配置

...
public OverScrollerEdgeEffectView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
     
        super(context, attrs, defStyleAttr, defStyleRes);
        mScroller = new OverScroller(context);
        ViewConfiguration vc = ViewConfiguration.get(context);
        mTouchSlop = vc.getScaledTouchSlop()*0.8f;
        mMinimumVelocity = vc.getScaledMinimumFlingVelocity();
        mMaximumVelocity = vc.getScaledMaximumFlingVelocity();
    	//定义上下边界和颜色
        edgeEffectTop = new EdgeEffect(context);
        edgeEffectTop.setColor(Color.DKGRAY);
        edgeEffectBottom = new EdgeEffect(context);
        edgeEffectBottom.setColor(Color.GREEN);
    }
....
@Override
public void onSizeChanged(int w, int h, int oldw, int oldh) {
     
      //设置宽高,可以放到其他位置
      edgeEffectTop.setSize(w,h);
      edgeEffectBottom.setSize(w,h);
}
...

3 状态控制

onTouchEvent中处理拉及释放

    @Override
    public boolean onTouchEvent(MotionEvent event) {
     
        int action = event.getAction()&MotionEvent.ACTION_MASK;
        switch (action) {
     
            case MotionEvent.ACTION_DOWN:
				//恢复
                edgeEffectTop.finish();
                edgeEffectBottom.finish();
                postInvalidateOnAnimation();
                break;
            case MotionEvent.ACTION_MOVE:
				...
                //下拉状态    
                if(getScrollY()+v< 0 ){
     
                    edgeEffectTop.onPull(Math.abs(v/getHeight()),event.getX()/getWidth());
                }
                if(getScrollY()+getHeight()+v> containHeight){
     
                    edgeEffectBottom.onPull(Math.abs(v/getHeight()),1f-event.getX()/getWidth());
                }
                postInvalidateOnAnimation();
                ....
                break;
            case MotionEvent.ACTION_UP:
				....
                //释放
                edgeEffectTop.onRelease();
                edgeEffectBottom.onRelease();
                postInvalidateOnAnimation();
                break;
            default:
                break;
        }
        return true;
    }

computeScroll 撞击吸收

    @Override
    public void computeScroll() {
     
        if (mScroller.computeScrollOffset()) {
     
            int y = mScroller.getCurrY();
            scrollTo(0,y);
            //Absorb Velocity
            if(edgeEffectTop.isFinished() && getScrollY()< 0 ){
     
                edgeEffectTop.onAbsorb((int) mScroller.getCurrVelocity());
            }

            if(edgeEffectBottom.isFinished() && getScrollY()+getHeight()> containHeight){
     
                edgeEffectBottom.onAbsorb((int) mScroller.getCurrVelocity());
            }
            postInvalidateOnAnimation();
        }
    }

4 绘制效果

    @Override
    public void onDrawForeground(Canvas canvas){
     
        super.onDrawForeground(canvas);
        //绘制上边界
        if(!edgeEffectTop.isFinished()){
     
            canvas.save();
            edgeEffectTop.draw(canvas);
            canvas.restore();
            invalidate();
        }

        //绘制下边界,要自己变换坐标哟
        if(!edgeEffectBottom.isFinished()){
     
            canvas.save();
            canvas.translate(-getWidth(),0);
            canvas.rotate(180,getWidth(),0);
            canvas.translate(0,-containHeight);
            edgeEffectBottom.draw(canvas);
            canvas.restore();
            invalidate();
        }
    }

总结

通过上面的介绍,可以发现边界效果EdgeEffect封装了边界绘制效果,使用方法主要为初始化配置、控制状态和绘制三个步骤,抓住这三个步骤就很容易理解和使用边界效果了。

你可能感兴趣的:(自定义控件,android,canvas,java)