优于别人,并不高贵,真正得高贵是优于过去得自己---海明威
下面是我做的效果
![](https://img.haomeiwen.com/i4334980/95aec76dc9402903.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>
网友评论