美文网首页
android 水波进度条柱状图根据Recyclerview的滑

android 水波进度条柱状图根据Recyclerview的滑

作者: 南娇 | 来源:发表于2018-09-04 09:39 被阅读115次

    优于别人,并不高贵,真正得高贵是优于过去得自己---海明威

    下面是我做的效果


    录屏_20180903_180213.gif

    图片格式转换的不太好不太清除,大家凑合看吧

    用到的知识:
    自定义view的相关知识
    还是recyclerView的滑动监听

    下面是自定义view,注释写的还行我就不解释了

     public class WaterView extends View {
    
    private int mHeight;
    private int mWidth;
    
    //柱状图高度
    private int mWaterHeight;
    //柱状图宽度
    private int mWaterWidth;
    //水波颜色
    private int mWaterColor=Color.RED;
    //边框颜色
    private int mWaterSideColor=Color.WHITE;
    //边框宽度
    private int mSideWidth;
    //边框画笔
    private Paint mSidePaint;
    //填充画笔
    private Paint mPaint;
    //内部矩形画笔
    private Paint mNBPaint;
    //内部矩形路径
    private Path mNBPath;
    
    //百分比画笔
    private Paint mTextPaint;
    
    
    //边框路径
    private Path mSidePath;
    //填充路径
    private Path mPath;
    
    //水波振幅
    private int mSwing=0;
    //波长
    private int mWaveWidth=120;
    //波得数量
    private int mWaveCount;
    //水波偏移距离
    private int mMoveX;
    //判断动画是否已经开启
    private boolean isStart=false;
    //水波上升百分比
    private float mPersent;
    
    //缓存bigmap
    private Bitmap mBitmap;
    private Canvas mBitmapCanvas;
    
    //水波滚动动画
    private ValueAnimator  animation;
    
    
    
    
    
    
    
    
    
    
    public WaterView(Context context) {
        this(context,null);
    }
    
    public WaterView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }
    
    public WaterView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    
        TypedArray array=context.obtainStyledAttributes(attrs, R.styleable.WaterView);
        mWaterHeight=array.getDimensionPixelOffset(R.styleable.WaterView_waterHeight,mWaterHeight);
        mWaterWidth=array.getDimensionPixelOffset(R.styleable.WaterView_waterWidth,mWaterWidth);
        mWaterColor=array.getColor(R.styleable.WaterView_waterColor,mWaterColor);
        mWaterSideColor=array.getColor(R.styleable.WaterView_waterSideColor,mWaterSideColor);
        mSideWidth=array.getDimensionPixelOffset(R.styleable.WaterView_waterSideWidth,mSideWidth);
        array.recycle();
    
        initPaint();
    
    }
    
    //初始化画笔
    private void initPaint() {
    
        mSidePaint=new Paint();
        mSidePaint.setStyle(Paint.Style.STROKE);
        mSidePaint.setColor(mWaterSideColor);
        mSidePaint.setAntiAlias(true);
        mSidePaint.setStrokeWidth(mSideWidth);
    
    
        mPaint=new Paint();
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setColor(mWaterColor);
        mPaint.setAntiAlias(true);
        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
    
        mNBPaint=new Paint();
        mNBPaint.setStyle(Paint.Style.FILL);
        mNBPaint.setColor(Color.BLUE);
        mNBPaint.setAntiAlias(true);
    
        mTextPaint=new Paint();
        mTextPaint.setColor(Color.BLACK);
        mTextPaint.setAntiAlias(true);
        mTextPaint.setTextSize(20);
    
        mSidePath=new Path();
        mPath=new Path();
        mNBPath=new Path();
    }
    
    
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mWidth=MeasureSpec.getSize(widthMeasureSpec);
        mHeight=MeasureSpec.getSize(heightMeasureSpec);
    
        mWaveCount= (int) Math.ceil(mWidth/mWaveWidth);
    
        mBitmap=Bitmap.createBitmap(mWidth,mHeight,Bitmap.Config.ARGB_8888);
        mBitmapCanvas=new Canvas(mBitmap);
    }
    
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    
    
        //根据上升得高度设置振幅
    
        drawRect();
    
        drawWater(canvas);
    
        drawSide(canvas);
    
        drawText();
    
        canvas.drawBitmap(mBitmap,0,0,null);
    
    
    
    }
    
    //画文字
    private void drawText() {
        String text=(int)(mPersent*100)+"%";
        int x= (int) (mWidth/2-mTextPaint.measureText(text)/2);
        int y=(mHeight-mWaterHeight)+mWaterHeight/2;
    
        mBitmapCanvas.drawText(text,x,y,mTextPaint);
    
    }
    
    
    /**
     * 画水波
     * @param canvas
     */
    private void drawWater(Canvas canvas) {
        
        //这里一定要reset不然界面会有重叠
        mPath.reset();
        mPath.moveTo(-mWidth,mHeight);
        mPath.lineTo(-mWidth+mMoveX,(mHeight-mWaterHeight)+mWaterHeight*(1-mPersent));
        for(int i=0;i<mWaveCount*2;i++){
            mPath.quadTo(-mWidth+mWaveWidth/4+i*mWaveWidth+mMoveX,(mHeight-mWaterHeight)+mWaterHeight*(1-mPersent)+mSwing,-mWidth+mWaveWidth/2+i*mWaveWidth+mMoveX,(mHeight-mWaterHeight)+mWaterHeight*(1-mPersent));
            mPath.quadTo(-mWidth+mWaveWidth*3/4+i*mWaveWidth+mMoveX,(mHeight-mWaterHeight)+mWaterHeight*(1-mPersent)-mSwing,-mWidth+  mWaveWidth+i*mWaveWidth+mMoveX,(mHeight-mWaterHeight)+mWaterHeight*(1-mPersent));
        }
        mPath.lineTo(mWidth,(mHeight-mWaterHeight)+mWaterHeight*(1-mPersent));
        mPath.lineTo(mWidth,mHeight);
        mPath.close();
    
        mBitmapCanvas.drawPath(mPath,mPaint);
    }
    /**
     * 画边框
     * @param canvas
     */
    private void drawSide(Canvas canvas) {
    
        //柱状图距离左边得距离
        int left=(mWidth-mWaterWidth)/2;
        //距离顶部得距离
        int top=mHeight-mWaterHeight;
    
    
        mSidePath.moveTo(left,mHeight);
        mSidePath.lineTo(left,top);
        mSidePath.lineTo(left+mWaterWidth,top);
        mSidePath.lineTo(left+mWaterWidth,mHeight);
        mSidePath.close();
    
        mBitmapCanvas.drawPath(mSidePath,mSidePaint);
    }
    
    //画内部矩形
    private void drawRect() {
        //柱状图距离左边得距离
        int left=(mWidth-mWaterWidth)/2;
        //距离顶部得距离
        int top=mHeight-mWaterHeight;
    
    
    
    
        mNBPath.moveTo(left-mSideWidth,mHeight);
        mNBPath.lineTo(left-mSideWidth,top);
        mNBPath.lineTo(left+mWaterWidth+mSideWidth,top);
        mNBPath.lineTo(left+mWaterWidth+mSideWidth,mHeight);
        mNBPath.close();
    
        mBitmapCanvas.drawPath(mSidePath,mNBPaint);
    
    }
    
    
    /**
     * 水波平移动画
     */
    private void startWaterAnimation() {
    
        if(!isStart){
            isStart=true;
            animation=ObjectAnimator.ofInt(0,mWidth);
            animation.setDuration(10000);
            animation.setRepeatCount(Animation.INFINITE);
            animation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
    
                        mMoveX= (int) animation.getAnimatedValue();
                        postInvalidate();
                }
            });
            animation.start();
        }
    }
    
    
    //设置上升百分比
    public void setPersent(float persent){
        this.mPersent=persent;
        if(persent>0){
            mSwing= (int) (20*(1-mPersent));
        }else{
            mSwing=0;
        }
    
        invalidate();
    }
    
    //开始平移动画
    public void startMove(){
        startWaterAnimation();
    }
    

    }

    下面是mainActivity中的方法

     public class MainActivity extends AppCompatActivity {
    
    private WaterView mWaterView;
    
    private RecyclerView mRecyclerview;
    
    private Adapter mAdapter;
    
    private List<String> mDatas;
    
    //第一屏显示的高度
    private int mHeight;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mWaterView = findViewById(R.id.waterview);
        mRecyclerview=findViewById(R.id.recyclerview);
    
    
        mDatas=new ArrayList<>();
        for(int i=0;i<50;i++){
            mDatas.add(i+"text");
        }
    
    
        mAdapter=new Adapter(this,mDatas);
        mRecyclerview.setLayoutManager(new LinearLayoutManager(this));
        mRecyclerview.setAdapter(mAdapter);
    
        mRecyclerview.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
            }
    
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
           
            mWaterView.setPersent(getY()/getH());
            mWaterView.startMove();
    
            }
        });
    
    
    
    }
    
    //获取当前滚动的距离
    public float getY(){
        LinearLayoutManager layoutManager = (LinearLayoutManager) mRecyclerview.getLayoutManager();
        //获取第一个显示的位置
        int position = layoutManager.findFirstVisibleItemPosition();
        //根据位置获取第一个位置的view
        View firstVisiableChildView = layoutManager.findViewByPosition(position);
        //获取第一个view的高度
        int itemHeight = firstVisiableChildView.getHeight();
        return (position) * itemHeight - firstVisiableChildView.getTop();
    }
    
    
    //获取滚动的总距离
    public float getH(){
       //mRecyclerview.computeVerticalScrollRange() 这个方法是获取recyclerview的总高度
        //mRecyclerview.computeVerticalScrollExtent();这个方法是获取recyclerview的当前屏幕显示的高度
        return mRecyclerview.computeVerticalScrollRange()-mRecyclerview.computeVerticalScrollExtent();
                }
       }
    

    style中定义的属性

      <declare-styleable name="WaterView">
        <!-- 水柱的高度-->
        <attr name="waterHeight" format="dimension"/>
        <!-- 水柱的宽度-->
        <attr name="waterWidth" format="dimension"/>
        <!-- 水柱的填充颜色-->
        <attr name="waterColor" format="color"/>
        <!-- 水柱的边框颜色-->
        <attr name="waterSideColor" format="color"/>
        <!-- 水柱的边框宽度-->
        <attr name="waterSideWidth" format="dimension"/>
    
        </declare-styleable>
    

    相关文章

      网友评论

          本文标题:android 水波进度条柱状图根据Recyclerview的滑

          本文链接:https://www.haomeiwen.com/subject/hvxiwftx.html