美文网首页
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