先看效果

image.png

代码

/**

* 六边形水位效果

*/

public class SixWave extends View {

private static final float DEFAULT_AMPLITUDE_RATIO = 0.1f;

private static final float DEFAULT_AMPLITUDE_VALUE = 50.0f;

private static final float DEFAULT_WATER_LEVEL_RATIO = 0.5f;

private static final float DEFAULT_WAVE_LENGTH_RATIO = 1.0f;

private static final float DEFAULT_WAVE_SHIFT_RATIO = 0.0f;

private static final int DEFAULT_WAVE_PROGRESS_VALUE = 50;

private static final int DEFAULT_WAVE_COLOR = Color.parseColor("#212121");

private static final int DEFAULT_WAVE_BACKGROUND_COLOR = Color.parseColor("#00000000");

private static final float DEFAULT_BORDER_WIDTH = 0;

private int mCanvasSize;

private float mAmplitudeRatio;//振幅度比列大小

private int mWaveBgColor;

private int mWaveColor;

private float mDefaultWaterLevel;//默认水位等级

private float mWaterLevelRatio = 1f;//变速等级

private float mWaveShiftRatio = DEFAULT_WAVE_SHIFT_RATIO;//变速比率

private int mProgressValue = DEFAULT_WAVE_PROGRESS_VALUE;//进度

private BitmapShader mWaveShader;//水位渲染

private Matrix mShaderMatrix;//矩阵着色

private Paint mWavePaint;

private Paint mWaveBgPaint;

private Paint mBorderPaint;

private ObjectAnimator waveShiftAnim;//执行动画

private AnimatorSet mAnimatorSet;//动画组合 用来控制 暂停开始

private Context mContext;

public SixWave(final Context context) {

this(context, null);

}

public SixWave(Context context, AttributeSet attrs) {

this(context, attrs, 0);

}

public SixWave(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

init(context, attrs, defStyleAttr);

}

private void init(Context context, AttributeSet attrs, int defStyleAttr) {

mContext = context;

mShaderMatrix = new Matrix();

mWavePaint = new Paint();

mWavePaint.setAntiAlias(true);

mWaveBgPaint = new Paint();

mWaveBgPaint.setAntiAlias(true);

initAnimation();

TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.SixWave, defStyleAttr, 0);

mWaveColor = attributes.getColor(R.styleable.SixWave_sw_waveColor, DEFAULT_WAVE_COLOR);

mWaveBgColor = attributes.getColor(R.styleable.SixWave_sw_wave_background_Color, DEFAULT_WAVE_BACKGROUND_COLOR);

mWaveBgPaint.setColor(mWaveBgColor);

float amplitudeRatioAttr = attributes.getFloat(R.styleable.SixWave_sw_waveAmplitude, DEFAULT_AMPLITUDE_VALUE) / 1000;

mAmplitudeRatio = (amplitudeRatioAttr > DEFAULT_AMPLITUDE_RATIO) ? DEFAULT_AMPLITUDE_RATIO : amplitudeRatioAttr;

mProgressValue = attributes.getInteger(R.styleable.SixWave_sw_progressValue, DEFAULT_WAVE_PROGRESS_VALUE);

setProgressValue(mProgressValue);

mBorderPaint = new Paint();

mBorderPaint.setAntiAlias(true);

mBorderPaint.setStyle(Paint.Style.STROKE);

mBorderPaint.setStrokeWidth(attributes.getDimension(R.styleable.SixWave_sw_borderWidth, dp2px(DEFAULT_BORDER_WIDTH)));

mBorderPaint.setColor(attributes.getColor(R.styleable.SixWave_sw_borderColor, DEFAULT_WAVE_COLOR));

attributes.recycle();

}

@Override

public void onDraw(Canvas canvas) {

mCanvasSize = canvas.getWidth();

if (canvas.getHeight() < mCanvasSize) {

mCanvasSize = canvas.getHeight();

}

if (mWaveShader != null) {

if (mWavePaint.getShader() == null) {

mWavePaint.setShader(mWaveShader);

}

mShaderMatrix.setScale(1, mAmplitudeRatio / DEFAULT_AMPLITUDE_RATIO, 0, mDefaultWaterLevel);

mShaderMatrix.postTranslate(mWaveShiftRatio * getWidth(),

(DEFAULT_WATER_LEVEL_RATIO - mWaterLevelRatio) * getHeight());

mWaveShader.setLocalMatrix(mShaderMatrix);

//六边形主要代码

drawPolygon(canvas);

} else {

mWavePaint.setShader(null);

}

}

private void drawPolygon(Canvas canvas) {

Path path = new Path();

float radius, centerX, centerY;

radius = centerX = centerY = Math.min(getWidth(), getHeight()) * 0.5f;

radius -= getBorderWidth() * 0.5f;

float offsetAngle = 0;

offsetAngle = (float) (Math.PI * offsetAngle / 180);

for (int i = 0; i < getSides(); i++) {

float x = (float) (centerX + radius * Math.cos(offsetAngle));

float y = (float) (centerY + radius * Math.sin(offsetAngle));

offsetAngle += 2 * Math.PI / getSides();

if (i == 0) {

path.moveTo(x, y);

} else {

path.lineTo(x, y);

}

}

path.close();

if (getSides() % 2 != 0) {

Matrix mMatrix = new Matrix();

mMatrix.postRotate(-90, centerX, centerY);

path.transform(mMatrix);

}

canvas.drawPath(path, mBorderPaint);

canvas.drawPath(path, mWavePaint);

}

private int getSides() {

return 6;//6边形

}

@Override

protected void onSizeChanged(int w, int h, int oldw, int oldh) {

super.onSizeChanged(w, h, oldw, oldh);

mCanvasSize = w;

if (h < mCanvasSize) mCanvasSize = h;

updateWaveShader();

}

/**

* 初始动画

*/

private void initAnimation() {

waveShiftAnim = ObjectAnimator.ofFloat(this, "waveShiftRatio", 0f, 1f);

waveShiftAnim.setRepeatCount(ValueAnimator.INFINITE);

waveShiftAnim.setDuration(1000);

waveShiftAnim.setInterpolator(new LinearInterpolator());

mAnimatorSet = new AnimatorSet();

mAnimatorSet.play(waveShiftAnim);

}

/**

* 进度值动画

*

* @param progress

*/

public void setProgressValue(int progress) {

mProgressValue = progress;

ObjectAnimator waterLevelAnim = ObjectAnimator.ofFloat(this, "waterLevelRatio", mWaterLevelRatio, ((float) mProgressValue / 100));

waterLevelAnim.setDuration(1000);

waterLevelAnim.setInterpolator(new DecelerateInterpolator());

AnimatorSet animatorSetProgress = new AnimatorSet();

animatorSetProgress.play(waterLevelAnim);

animatorSetProgress.start();

}

/*

大波浪

*/

private void updateWaveShader() {

int width = getMeasuredWidth();

int height = getMeasuredHeight();

if (width > 0 && height > 0) {

double defaultAngularFrequency = 2.0f * Math.PI / DEFAULT_WAVE_LENGTH_RATIO / width;

float defaultAmplitude = height * DEFAULT_AMPLITUDE_RATIO;

mDefaultWaterLevel = height * DEFAULT_WATER_LEVEL_RATIO;

Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);

Canvas canvas = new Canvas(bitmap);

Paint wavePaint = new Paint();

wavePaint.setStrokeWidth(2);

wavePaint.setAntiAlias(true);

final int endX = width + 1;

final int endY = height + 1;

float[] waveY = new float[endX];

wavePaint.setColor(adjustAlpha(mWaveColor, 0.3f));

for (int beginX = 0; beginX < endX; beginX++) {

double wx = beginX * defaultAngularFrequency;

float beginY = (float) (mDefaultWaterLevel + defaultAmplitude * Math.sin(wx));

canvas.drawLine(beginX, beginY, beginX, endY, wavePaint);

waveY[beginX] = beginY;

}

wavePaint.setColor(mWaveColor);

final int wave2Shift = (int) ((float) width / 4);

for (int beginX = 0; beginX < endX; beginX++) {

canvas.drawLine(beginX, waveY[(beginX + wave2Shift) % endX], beginX, endY, wavePaint);

}

mWaveShader = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);

this.mWavePaint.setShader(mWaveShader);

}

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

int width = measureWidth(widthMeasureSpec);

int height = measureHeight(heightMeasureSpec);

int imageSize = (width < height) ? width : height;

setMeasuredDimension(imageSize, imageSize);

}

private int measureWidth(int measureSpec) {

int result;

int specMode = MeasureSpec.getMode(measureSpec);

int specSize = MeasureSpec.getSize(measureSpec);

if (specMode == MeasureSpec.EXACTLY) {

result = specSize;

} else {

result = specSize;

}

return result;

}

private int measureHeight(int measureSpecHeight) {

int result;

int specMode = MeasureSpec.getMode(measureSpecHeight);

int specSize = MeasureSpec.getSize(measureSpecHeight);

if (specMode == MeasureSpec.EXACTLY) {

result = specSize;

} else {

result = specSize;

}

return (result + 2);

}

public void setWaveBgColor(int color) {

this.mWaveBgColor = color;

mWaveBgPaint.setColor(this.mWaveBgColor);

updateWaveShader();

invalidate();

}

public int getWaveBgColor() {

return mWaveBgColor;

}

public void setWaveColor(int color) {

mWaveColor = color;

updateWaveShader();

invalidate();

}

public int getWaveColor() {

return mWaveColor;

}

public void setBorderWidth(float width) {

mBorderPaint.setStrokeWidth(width);

invalidate();

}

public float getBorderWidth() {

return mBorderPaint.getStrokeWidth();

}

public void setBorderColor(int color) {

mBorderPaint.setColor(color);

updateWaveShader();

invalidate();

}

public int getBorderColor() {

return mBorderPaint.getColor();

}

public void setAmplitudeRatio(int amplitudeRatio) {

if (this.mAmplitudeRatio != (float) amplitudeRatio / 1000) {

this.mAmplitudeRatio = (float) amplitudeRatio / 1000;

invalidate();

}

}

public float getAmplitudeRatio() {

return mAmplitudeRatio;

}

public int getProgressValue() {

return mProgressValue;

}

public void setWaveShiftRatio(float waveShiftRatio) {

if (this.mWaveShiftRatio != waveShiftRatio) {

this.mWaveShiftRatio = waveShiftRatio;

invalidate();

}

}

public float getWaveShiftRatio() {

return mWaveShiftRatio;

}

public void setWaterLevelRatio(float waterLevelRatio) {

if (this.mWaterLevelRatio != waterLevelRatio) {

this.mWaterLevelRatio = waterLevelRatio;

invalidate();

}

}

public float getWaterLevelRatio() {

return mWaterLevelRatio;

}

public void startAnimation() {

if (mAnimatorSet != null) {

mAnimatorSet.start();

}

}

public void endAnimation() {

if (mAnimatorSet != null) {

mAnimatorSet.end();

}

}

public void cancelAnimation() {

if (mAnimatorSet != null) {

mAnimatorSet.cancel();

}

}

@TargetApi(Build.VERSION_CODES.KITKAT)

@SuppressWarnings("deprecation")

public void pauseAnimation() {

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {

if (mAnimatorSet != null) {

mAnimatorSet.pause();

}

}

}

@TargetApi(Build.VERSION_CODES.KITKAT)

@SuppressWarnings("deprecation")

public void resumeAnimation() {

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {

if (mAnimatorSet != null) {

mAnimatorSet.resume();

}

}

}

public void setAnimDuration(long duration) {

waveShiftAnim.setDuration(duration);

}

@Override

protected void onAttachedToWindow() {

startAnimation();

super.onAttachedToWindow();

}

@Override

protected void onDetachedFromWindow() {

cancelAnimation();

super.onDetachedFromWindow();

}

private int adjustAlpha(int color, float factor) {

int alpha = Math.round(Color.alpha(color) * factor);

int red = Color.red(color);

int green = Color.green(color);

int blue = Color.blue(color);

return Color.argb(alpha, red, green, blue);

}

private int dp2px(float dp) {

final float scale = mContext.getResources().getDisplayMetrics().density;

return (int) (dp * scale + 0.5f);

}

}

attrs

xml

android:id="@+id/sixWave"

android:layout_width="match_parent"

android:layout_height="wrap_content"

app:sw_borderColor="@color/colorAccent"

app:sw_borderWidth="3dp"

app:sw_progressValue="70"

app:sw_waveAmplitude="50"

app:sw_waveColor="@color/colorAccent" />

activity

override fun initData() {

// sixWave.setBorderColor(Color.BLUE)

// sixWave.setWaveColor(Color.BLUE)

// sixWave.setWaveBgColor(Color.TRANSPARENT)

// sixWave.setAmplitudeRatio(40)

// sixWave.setWaveShiftRatio(0.2f)

// sixWave.setProgressValue(70)

sixWave.setAnimDuration(3000)

}

六边形图形效果根据WaveLoadingView修改。可以改多种样式,三角形,正方形,矩形,圆形,圆角矩形

android 六边形简书,水波浪贝塞尔效果(六边形)相关推荐

  1. android计步器简书,自定义View-仿QQ运动步数进度效果

    自定义View-仿QQ运动步数进度效果 一.写在前面 (1) 图一,仿QQ步数运行效果 (2) 图二,完整的圆效果 完整代码请看这 二.正文开始 (1)首先来个三部曲,自定义属性,布局设置,属性获取 ...

  2. android 仿简书评论,Android仿简书搜索框效果的示例代码

    前言 之前用简书的时候一直是在web端,后来下载了客户端,看到了搜索的那个动画,就尝试的去写了,没写之前感觉挺容易的,写了之后,就感觉里面还是有些要注意的东西的.话不多说,直接上图. Activity ...

  3. Android仿简书、淘宝等APP View弹出效果

    在用简书App的时候觉得这个View的弹出效果特别好,而且非常平滑. 先看看效果: 主要是scale,alpha,translation几个普通动画组合,这里不再分析. 实现效果图: 代码:https ...

  4. android 六边形简书,深入理解六边形架构

    六边形架构或六角架构是Alistair Cockburn在2005年提出,解决了传统的分层架构所带来的问题,实际上它也是一种分层架构,只不过不是上下或左右,而是变成了内部和外部.在领域驱动设计(DDD ...

  5. 实现简书个人中心UI效果

    这两天比较闲,简单实现了一下个人中心页面scrollView嵌套的效果,也就是下边这个页面,大家感受一下先: JSDemo2.gif 首先讲下实现思路,很多人看到这个界面觉得是多个scrollView ...

  6. android jsoup简书,jsoup爬虫简书首页数据做个小Demo

    昨天LZ去面试,遇到一个大牛,被血虐一番,发现自己基础还是很薄弱,对java一些原理掌握的还是不够稳固,比如java反射注解,知道一点就是说不出来,很尴尬... 生命不止,学习不止啊 之前那个项目 Q ...

  7. android 仿简书评论,Android 开发仿简书登录框可删除内容或显示密码框的内容

    简书App 是我很喜欢的一款软件.今天就模仿了一下他的登录框.先上图: 好了下面上代码,自定义ImgEditText 继承与EditText.重写一些方法. package lyf.myimgedit ...

  8. android仿简书编辑器,类似zine,简书的app移动编辑器-Light Seven

    原标题:类似zine,简书的app移动编辑器-Light Seven 无论你是否从事文字编辑工作,我相信每个人都会接触到文字编辑.既然接触到文字编辑,顺理成章的就会接触到文字编辑的应用和软件. 在生活 ...

  9. android 购物车 简书,Android仿饿了么购物车效果

    先看下效果图: ezgif-1-8f133ca916.gif 1.首先列表布局采用Recycleview android:id="@+id/container" android:l ...

  10. android 心跳 简书,如何高效维持网络长连接:手把手教你实现 自适应的心跳保活机制...

    前言 当实现具备实时性需求时,我们一般会选择长连接的通信方式 而在实现长连接方式时,存在很多性能问题,如 长连接保活 今天,我将 手把手教大家实现自适应的心跳保活机制,从而能高效维持长连接 目录 示意 ...

最新文章

  1. 链表问题11——两个单链表相交的系列问题(三):判断两个有环链表是否相交
  2. BZOJ2741 【FOTILE模拟赛】L
  3. java RSA加密解密实现(含分段加密)
  4. java获取项目的部署目录结构_JAVA WEB项目目录结构以及web应用部署的根目录,编译路径和项目根目录的区别...
  5. 我的技术回顾因ABP框架触发DevOps云原生之路-2020年
  6. Python爬虫用Selenium抓取js生成的文件(一)
  7. vue设置img大小的属性_Vue.js自定义标签属性并获取属性,及绑定img的src属性的坑...
  8. [Python] L1-021. 重要的话说三遍-PAT团体程序设计天梯赛GPLT
  9. hdfs 中chunk_HDFS读写流程
  10. CUDA安装失败,及解决方案
  11. [PKUSC2018游记]
  12. JAVA面试技巧之项目介绍
  13. Android APP如何获取framework下的资源?
  14. STM32L476入坑-3-新建工程并点亮LED灯
  15. 解决margin坍塌
  16. 高校青年教师应该怎么提高收入
  17. windows 多开微信
  18. 关于计算机系调查问卷表,计算机系统调查问卷.xls
  19. 关于sdcard读写速率慢的问题排查
  20. 麒麟系统(Fedora 64)安装谷歌(chrome)浏览器

热门文章

  1. 前端移动端端测试——显示控制台
  2. 百度地图小区边界爬取
  3. springboot+vue疫情管理大作业
  4. linux系统外接硬盘挂载
  5. 如何生成smali文件
  6. 我的过错不值得原谅,麻木的岁月我还要背负多久。
  7. 开源项目推荐系列(短信网关)
  8. OpenCV图像识别技术+Mediapipe与Unity引擎的结合
  9. C#:BackgroundWorker的简单使用
  10. 贴片天线的特征模分析及其应用