自定义view实现滑动效果

话不多说!直接先看效果图:
这里写图片描述
在这里我们实现了滑动的的左右滑动(防止其超出边界,在滑动的距离过程中,有个自动选择的效果,并配备文字说明)
首先我们必须知道:
view绘制的流程:onMeasure()测量—>onLayout()布局—->onDraw()绘制—->onTouch()事件

代码如下:
1,新建一个类继承于view,并在布局文件中引入该自定义类

public class SlideButton extends View {

    private Bitmap mBitmap_bg;
    private Bitmap mBitmap_btn;
    private Paint mPaint;
    private int mMRight;

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

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

    private void initView() {
        //获取图片资源
        mBitmap_bg = BitmapFactory.decodeResource(getResources(), R.drawable.background);
        mBitmap_btn = BitmapFactory.decodeResource(getResources(), R.drawable.slide_button);
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //测量背景资源的尺寸
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        switch (widthMode) {
            case MeasureSpec.AT_MOST:
                widthSize = mBitmap_bg.getWidth();
                break;
        }
        switch (heightMode) {
            case MeasureSpec.AT_MOST:
                heightSize = mBitmap_bg.getHeight();
                break;
        }
        //重新测量其尺寸大小
        setMeasuredDimension(widthSize, heightSize);
    }

    //触摸事件
    private float mStartX;
    private float mStartY;
    private float mChangedemotion;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int action = event.getAction();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                mStartX = event.getRawX();
                mStartY = event.getRawY();
                break;
            case MotionEvent.ACTION_MOVE:
                float newX = event.getRawX();
                float newY = event.getRawY();

                //偏移量
                float dx = newX - mStartX;
                //移动
                mChangedemotion += dx;

                //从新赋值
                mStartX = newX;
                mStartY = newY;
                break;
            case MotionEvent.ACTION_UP://抬起
                //在抬起的时候,判断,其划动的的时候在那一边,自动跳转到那一边
                //获得总体距离的一半
                int sum = mBitmap_bg.getWidth() / 2;
                //获得滑动的距离和控件距离的一半
                float everything = mBitmap_btn.getWidth() / 2 + mChangedemotion;

                if (everything >= sum) {
                    //跳到最右边,偏移量的改变
                    mChangedemotion = mMRight;
                    if (mListener != null) {
                        mListener.onChange(false);
                    }
                } else {
                    mChangedemotion = 0;
                    if (mListener != null) {
                        mListener.onChange(true);
                    }
                }
                break;
        }
        //重绘--->区别于从新布局requestLayout();
        invalidate();
        return true;
    }

    //绘制图片
    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawBitmap(mBitmap_bg, 0, 0, mPaint);
        //过滤掉开关出界的情况
        if (mChangedemotion < 0) {
            mChangedemotion = 0;
        }
        //获得滑动的最大的距离
        mMRight = mBitmap_bg.getWidth() - mBitmap_btn.getWidth();
        if (mChangedemotion > mMRight) {
            mChangedemotion = mMRight;
        }
        canvas.drawBitmap(mBitmap_btn, mChangedemotion, 0, mPaint);
        super.onDraw(canvas);
    }

    private OnStateChangeListenere mListener;

    //对外提供一个方法供外部去设置onstateChangeListener接口
    public void setOnStategeListener(OnStateChangeListenere listener) {
        if (listener != null) {
            this.mListener = listener;
        }
    }
}

2,自定义一个接口

public interface OnStateChangeListenere {
    void onChange(boolean isOpen);
}

3,在activity中实现对外提供的方法,即需要回调其接口方法


public class MainActivity extends Activity {
    private SlideButton mSilede;
    private TextView mTv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        mSilede = (SlideButton) findViewById(slide);
        mTv = (TextView)findViewById(R.id.tv);
        mSilede.setOnStategeListener(new OnStateChangeListenere() {
            @Override
            public void onChange(boolean isOpen) {
                //因为使用了接口,此处修改了后(变更为图片或其他的),原实现逻辑代码可以不用修改
                mTv.setText(isOpen ?"开启":"关闭");
            }
        });
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值