Android 自定义音浪

package com.as.flypig06;

import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.view.animation.TranslateAnimation;

import androidx.annotation.Nullable;

import com.blankj.utilcode.util.SizeUtils;

public class SlidePlusView extends View implements View.OnTouchListener, Runnable {

    private static final String TAG = "SlidePlusView";
    //线的最小高度的倍数=最大高度 * f
    private static final float f = 0.22f;

    //画笔
    private Paint mPaint;
    //当前滑动的位置
    private int mPosition;
    //所有滑动的数据
    private int mLength;
    //线的宽度
    private int mLineWidth;
    //线的最大高度
    private int mLineMaxHeight;
    //线的最小高度
    private int mLineMinHeight;
    //滑动的x坐标
    private float mSlideX = 0;
    //这个控件可以画几条线,同时也是线与线之间的距离
    private float range = 0;
    //控件的中间
    private float center = 0;
    //事件监听
    private OnMoveListener moveListener;
    //记录按下的x坐标
    private float downX;
    //记录按下是的当前移动的x坐标
    private float downSlideX;
    private int oldPosition;
    private Paint paint;

    public SlidePlusView(Context context) {
        this(context, null);
    }

    public SlidePlusView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    private void init(Context context) {
        mLineWidth = SizeUtils.dp2px(4);
        mLineMaxHeight = SizeUtils.dp2px(30);
        mLineMinHeight = (int) (mLineMaxHeight * f);

        mPaint = new Paint();
        //设置抗锯齿
        mPaint.setAntiAlias(true);
        //设置笔的两端圆角
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        //设置线的粗细
        mPaint.setStrokeWidth(mLineWidth);


        paint = new Paint();
        paint.setTextSize(20);
        //加入滑动事件
        setOnTouchListener(this);
    }

    @Override
    public void run() {
        //一共显示几条线
        range = getMeasuredWidth() / 28f;
        //获取中间x坐标
        center = getMeasuredWidth() / 2f;
        //计算position出现的位置
        mSlideX = -mPosition * range;
        invalidate();
//        initAnimation(0, mSlideX);



    }


    @SuppressLint("DrawAllocation")
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        float[] cf;
//            //从中间开始画
//            mPaint.setAlpha(255);
//            cf = getLineHeight(mLineMaxHeight);
//            canvas.drawLine(center,cf[0],center,cf[1], mPaint);

//            //这个控件可以画几条线,同时也是线与线之间的距离
//            range = getMeasuredWidth() / 20f;
//            //计算开始画的x左边
//            float x = center - (mPosition * range) + (mSlideX % range);
//            for (int i = 0; i < mData.size(); i++) {
//                if (mPosition == i){
//                    continue;
//                }
//                cf = getLineHeight(mLineMinHeight);
//                float x2 = x + (i * range);
//                canvas.drawLine(x2,cf[0],x2,cf[1], mPaint);
//            }

        //计算开始画的x左边 从中间开始计算+移动的偏移值
        float x = center + mSlideX;
        int t;
        int alpha;
        for (int i = 0; i < mLength; i++) {
            //计算透明值
            //滑动位置mPosition的左右边透明度使用位移算法计算,最小值为79
            //使用位移算法的原因,最高亮到透明是上一条线的透明度的一倍
            t = Math.abs(i - mPosition);
            alpha = 255 * 10 / (1 << t);
            if (alpha < 79) {
                alpha = 79;
            }
            mPaint.setAlpha(alpha);

            if (mPosition == i) {
                //画选中mPosition的线
                cf = getLineHeight(mLineMaxHeight);

                mPaint.setColor(Color.BLACK);
//            } else if (mPosition == i + 1 || mPosition == i - 1 ||) {
            } else if (mPosition == i + 1 || mPosition == i - 1 ) {
                //画 mPosition 左右两边的线
                cf = getLineHeight(mLineMaxHeight * 0.5f);

                mPaint.setColor(Color.BLACK);
            } else {

                if(mPosition == i + 2 || mPosition == i - 2 ){
                    mPaint.setColor(Color.BLACK);
                }else{
                    mPaint.setColor(Color.GRAY);
                }
                //画小线
                cf = getLineHeight(mLineMinHeight);


            }
            float x2 = x + (i * range);


            canvas.drawLine(x2, cf[0], x2, cf[1], mPaint);

            canvas.drawText(mPosition+"", x2, cf[1]+10,paint);
        }

    }



    /**
     * 获取线的高度,通过传入的height,计算出现这个控件中间的位置
     * f[0] = 开始画的y坐标
     * f[1] = 结束的y坐标
     *
     * @param height
     * @return
     */
    private float[] getLineHeight(float height) {
        float f[] = new float[2];
        float y = (getMeasuredHeight() - height) / 2f;
        f[0] = y;
        f[1] = y + height;
        return f;
    }

    //设置显示的位置
    public void setPosition(int position) {
        mPosition = position;
        post(this);
    }

    public int getPosition() {
        return mPosition;
    }

    //设置长度
    public void setLength(int length) {
        this.mLength = length;
        post(this);
    }

    public void setOnMoveListener(OnMoveListener onSlideListener) {
        this.moveListener = onSlideListener;
    }

//    public OnSlideListener getOnSlideListener() {
//        return mOnSlideListener;
//    }

    //滑动出这个控件的外部,滑动事件依然有效
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_MOVE) {
            getParent().requestDisallowInterceptTouchEvent(true);
        }
        return super.dispatchTouchEvent(event);
    }

    //滑动事件
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (mLength  <= 0) {
            return false;
        }
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                //记录上次的数据
                downX = event.getX();
                downSlideX = mSlideX;
                oldPosition = mPosition;
                break;
            case MotionEvent.ACTION_MOVE:
                float x = event.getX() - downX;
                mSlideX = x + downSlideX;
                //滑动右边是否超出,超过不计算,给最小值
                if (mSlideX > 0) {
                    mSlideX = 0;
                    mPosition = 0;
                } else {
                    //计算滑动到那个position
                    mPosition = (int) Math.abs(mSlideX / range);
                    //计算滑动左边是否超出,超过不计算,给最大值
                    if (mPosition >= mLength) {
                        mPosition = mLength - 1;
                        mSlideX = -mPosition * range;
                    }
                }
                if (moveListener != null) {
                    if (oldPosition != mPosition) {
                        oldPosition = mPosition;
                        moveListener.onSlide(this, mPosition,x);
                    }
                }
                break;
        }
        invalidate();
        return true;
    }

    public interface OnMoveListener {
        void onSlide(View v, int position, float x);
    }

    private void initAnimation(float start, float end) {
        TranslateAnimation nameAnimator = new TranslateAnimation(start, end, 0f, 0f);
        nameAnimator.setDuration(800);
        nameAnimator.setInterpolator(new DecelerateInterpolator());


        this.startAnimation(nameAnimator);

    }
}

 

public class MainActivity extends BaseActivity<ActivityMainBinding> implements View.OnClickListener {

    @Override
    protected int getLayoutId() {
        return R.layout.activity_main;
    }

    @Override
    protected void initShape() {

    }

    @Override
    protected void initView() {
        mViewBinding.spv.setLength(100);
        mViewBinding.spv.setOnMoveListener(new SlidePlusView.OnMoveListener() {
            @Override
            public void onSlide(View v, int position, float x) {
                ToastUtils.showShort("position :" + position);
            }
        });

        mViewBinding.but1.setOnClickListener(this);
        mViewBinding.but2.setOnClickListener(this);
        mViewBinding.but3.setOnClickListener(this);
        mViewBinding.but4.setOnClickListener(this);
    }

    @Override
    protected void initData() {

    }

    @Override
    protected void initListener() {

    }

    @Override
    public void onClick(View view) {
        switch (view.getId()){
                    case  R.id.but1:
                        mViewBinding.spv.setPosition(0*10);
                        break;
                    case  R.id.but2:
                        mViewBinding.spv.setPosition(1*10);
                        break;
                    case  R.id.but3:
                        mViewBinding.spv.setPosition(2*10);
                        break;
                    case  R.id.but4:
                        mViewBinding.spv.setPosition(3*10);
                        break;
                    default:
                        break;
                }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值